Melayani tugas latar belakang di situs besar

49

Kami sedang menghadapi masalah yang menarik di StackOverflow.

Kami punya banyak tugas kecil "yang harus segera dikerjakan". Contohnya adalah memperbarui daftar "Pertanyaan Terkait". Apa yang telah kami lakukan di masa lalu adalah untuk membuntuti tugas-tugas tersebut ke beberapa halaman pengguna.

Ini tidak pernah ideal, tetapi itu tidak terlalu terlihat. Sekarang SO telah melewati tanda tanya 1.000.000, para pengguna yang sial mulai merasakannya.

Solusi alami adalah benar-benar mendorong tugas-tugas ini ke latar belakang. Ada dua cara luas untuk melakukan ini, saya sedang mempertimbangkan.

1. Di IIS sebagai Thread-Pool / Work-Queue khusus

Pada dasarnya, kami memutar beberapa (non- ThreadPool , agar tidak mengganggu IIS) dan meminta mereka melayani beberapa koleksi yang kami dorong ke dalam Funcs .

Pro besar di sini adalah kesederhanaan. Kami tidak perlu khawatir tentang mengatur apa pun, kami juga tidak harus memastikan beberapa layanan eksternal siap dan merespons.

Kami juga mendapatkan akses ke semua kode umum kami.

Kontra adalah, yah, bahwa kita seharusnya tidak menggunakan utas latar belakang. Keberatan yang saya tahu semuanya berpusat di sekitar kelaparan IIS (jika Anda menggunakan ThreadPool) dan utas mati secara acak (karena daur ulang AppPool).

Kami memiliki infrastruktur yang ada untuk menjadikan kematian utas acak sebagai non-masalah (kemungkinan untuk mendeteksi tugas telah ditinggalkan, pada dasarnya), dan membatasi jumlah utas (dan menggunakan utas non-ThreadPool) juga tidak sulit.

Apakah saya melewatkan keberatan lain dalam antrian proses-threading / work-queue?

Pindah ke StackOverflow , karena tidak benar-benar dibahas di sini.

2. Sebagai Layanan

Baik solusi pihak ketiga, atau solusi kustom.

Pada dasarnya, kami akan menjalankan tugas melintasi batas proses untuk beberapa layanan dan lupakan saja. Agaknya kita menautkan beberapa kode, atau terbatas pada SQL + string koneksi mentah.

Pro adalah bahwa itu adalah "cara yang tepat" untuk melakukan ini.

Kontra adalah bahwa kita sangat terbatas dalam apa yang dapat kita lakukan, atau kita harus mengerjakan beberapa sistem untuk menjaga layanan ini sinkron dengan basis kode kita. Kita juga harus menghubungkan semua pemantauan dan kesalahan saat masuk, yang kita dapatkan secara gratis dengan opsi "In IIS".

Apakah ada manfaat atau masalah lain dengan pendekatan layanan?

Singkatnya, apakah ada masalah yang tak terduga dan tidak dapat diatasi yang membuat pendekatan # 1 tidak bisa diterapkan dan jika demikian, apakah ada layanan pihak ketiga yang baik yang harus kita perhatikan untuk pendekatan # 2?

Kevin Montrose
sumber
Cara yang benar adalah cara ketika Anda memutuskan untuk pergi ke arah lain Anda melihat ke belakang dan mengatakan kita seharusnya melakukan itu dengan cara yang benar. Pilihlah dengan bijak. Saya tidak cukup akrab dengan dunia IIS untuk mengomentari masalah khusus ini.
Chris
2
Saya ingin tahu karena saya memiliki skenario yang sama (pada skala yang jauh lebih kecil) dan saya juga hanya mendukung dukungan acak beberapa pengguna sial. Saya tidak terbiasa dengan solusi terbaik, jadi saya akan mengikuti di sini. :-)
pc1oad1etter
7
Saya tidak mengerti mengapa ini tidak ada di StackOverflow. Ini adalah tradeoff rekayasa, bukan penilaian subjektif. Anda meminta analisis dari berbagai pendekatan yang berbeda - itu semua objektif. Hanya ketika analisis telah memperjelas apa sebenarnya timbal baliknya, adakah subjektivitasnya, dan sejauh yang saya bisa lihat pertanyaan Anda bukanlah 'apa yang harus saya temukan lebih penting, waktu dan sumber daya server saya, atau waktu pengguna saya? ' atau yang serupa.
Joren
@Kevin Montrose - dari komentar Anda, sepertinya Anda membuat perbedaan antara "perlu segera dilakukan-ish" dan "dijadwalkan pada interval". Dapatkah Anda menguraikan mengapa mereka adalah dua yang berbeda jenis tugas latar belakang yang memerlukan pola / infrastruktur yang berbeda?
Portman
@ Portman - Perbedaan mendasarnya adalah bahwa tugas "segera-ish" tidak dapat dilakukan secara spekulatif, kita benar-benar harus menunggu sampai kita tahu bahwa mereka perlu dilakukan. Beberapa bagian belakang perhitungan amplop menunjukkan bahwa jika kami memindahkan kueri "Pertanyaan Terkait" (hanya satu dari banyak) ke tab cron "bodoh", diperlukan sekitar. satu minggu eksekusi yang solid untuk menyelesaikan semua pertanyaan. Secara umum kami juga ingin mereka berjalan sesegera mungkin (tanpa memengaruhi pengalaman pengguna), sedangkan tugas interval kami dapat dijalankan dengan tidak lebih sering daripada sekali dalam 5 menit (dan biasanya jauh lebih jarang).
Kevin Montrose

Jawaban:

17

Beberapa minggu yang lalu saya mengajukan pertanyaan serupa pada SO. Singkatnya, pendekatan saya untuk beberapa waktu sekarang adalah mengembangkan Layanan Windows. Saya akan menggunakan NServiceBus (dasarnya MSMQ di bawah selimut) untuk menyusun permintaan dari aplikasi web saya ke layanan saya. Saya dulu menggunakan WCF tetapi mendapatkan transaksi terdistribusi untuk bekerja dengan benar melalui WCF selalu tampak seperti menyebalkan. NServiceBus melakukan trik, saya bisa mengkomit data dan membuat tugas dalam transaksi dan tidak khawatir apakah layanan saya sudah berjalan dan berjalan pada saat itu. Sebagai contoh sederhana, jika saya perlu mengirim email (misalnya email pendaftaran) saya akan membuat akun pengguna dan mematikan sinyal ke Layanan Windows saya (untuk mengirim email) dalam transaksi. Penangan pesan di sisi layanan akan mengambil pesan dan memprosesnya.

Karena ASP .NET 4.0 dan AppFabric telah dirilis, ada sejumlah alternatif yang layak untuk mekanisme di atas. Mengacu kembali ke pertanyaan yang saya sebutkan di atas, kami sekarang memiliki AppInitialize AppFabric (via net.pipe) serta fitur Auto-Start ASP .NET 4.0 yang menjadikan pengembangan Layanan Windows sebagai aplikasi web sebagai alternatif yang layak. Saya sudah mulai melakukan ini sekarang karena sejumlah alasan (penyebaran terbesar adalah tidak lagi menyebalkan):

  1. Anda dapat mengembangkan UI web melalui layanan Anda (karena itu berjalan sebagai aplikasi web). Ini sangat berguna untuk melihat apa yang terjadi pada saat runtime.
  2. Model penerapan Anda untuk aplikasi web Anda akan berfungsi untuk aplikasi layanan Anda.
  3. IIS menyediakan beberapa fitur yang rapi untuk menangani kegagalan aplikasi (serupa dalam beberapa hal dengan Layanan Windows).
  4. Pengembang web sangat akrab dengan mengembangkan aplikasi web (secara alami), sebagian besar tidak tahu banyak tentang praktik terbaik ketika mengembangkan Layanan Windows.
  5. Ini memberikan sejumlah alternatif untuk mengekspos API untuk dikonsumsi aplikasi lain.

Jika Anda menggunakan rute ini (maafkan saya karena menyalin dan menempel dari posting asli saya) saya pasti akan mempertimbangkan menjalankan logika latar belakang dalam aplikasi web yang terpisah. Ada beberapa alasan untuk ini:

  1. Keamanan . Mungkin ada model keamanan yang berbeda untuk UI yang menampilkan informasi tentang proses latar belakang yang sedang berjalan. Saya tidak ingin mengekspos UI ini kepada orang lain selain tim ops. Selain itu, aplikasi web dapat berjalan sebagai pengguna yang berbeda yang memiliki serangkaian izin yang lebih tinggi.
  2. Pemeliharaan . Akan sangat bagus untuk dapat menerapkan perubahan pada aplikasi yang menjadi tuan rumah proses latar belakang tanpa berdampak pada pengguna yang menggunakan situs web front end.
  3. Performa . Setelah aplikasi terpisah dari situs utama memproses permintaan pengguna berarti bahwa utas latar belakang tidak akan mengurangi kemampuan IIS untuk menangani antrian permintaan yang masuk. Selanjutnya, aplikasi yang memproses tugas-tugas latar belakang dapat dikerahkan ke server terpisah jika diperlukan.

Melakukan ini akan kembali ke aspek marshaling. WCF, NServiceBus / RabbitMQ / ActiveMQ dll., Vanilla MSMQ, RESTful API (pikirkan MVC) adalah semua opsi. Jika Anda menggunakan Windows Workflow 4.0, Anda dapat mengekspos titik akhir host yang dapat dikonsumsi aplikasi web Anda.

Pendekatan web hosting untuk layanan masih cukup baru bagi saya, hanya waktu yang akan memberi tahu apakah itu pilihan yang tepat. Sejauh ini baik baik saja. Omong-omong, jika Anda tidak ingin menggunakan AppFabric (saya tidak bisa karena karena alasan yang aneh, Windows Server Web Edition tidak didukung), kemampuan Mulai Otomatis yang disebutkan dalam pos Gu berfungsi dengan baik. Tetap jauh dari file applicationhost.config, semua yang ada di postingan tersebut dapat diatur melalui konsol IIS (Editor Konfigurasi pada tingkat server utama).

Catatan: Saya awalnya memposting beberapa tautan lagi dalam pesan ini tetapi sayangnya, ini adalah posting pertama saya untuk pertukaran ini dan hanya satu tautan yang didukung! Pada dasarnya ada dua orang lain, untuk memberi mereka Google "Death to Windows Services ... Long Live AppFabric!" dan "auto-start-asp-net-aplikasi". Maaf soal itu.

Rohland
sumber
Gagasan dasar untuk menggunakan situs web terpisah sebagai layanan ini sangat menarik yang belum saya pertimbangkan ...
Kevin Montrose
Rohland, saya mungkin kehilangan sesuatu di sini, tetapi Anda tampaknya mengatakan bahwa Anda berinteraksi dengan Layanan Windows dari dalam penangan NServiceBus Anda, layanan kemudian mengirim email. Jika saya benar, dapatkah saya bertanya mengapa Anda tidak mengirim email dari penangan pesan NServiceBus, yang akan sangat mudah untuk dikembangkan, diuji dan digunakan?
Sean Kearon
Situs web mengirim pesan ke Layanan Windows. Penangan pesan Layanan Windows NServiceBus mengambil pesan dan mengirim pesan. Intinya, itu sama dengan proses yang Anda gambarkan.
Rohland
22

Sebenarnya ada cara ketiga di Windows untuk menjalankan layanan latar belakang, dan ini sangat umum di dunia UNIX. Cara ketiga adalah CRONpekerjaan yang menjalankan sebagian infrastruktur Anda. Di Windows ini dikenal sebagai task schedulerdan sangat umum untuk menjalankan kode secara terjadwal. Untuk menggunakan ini, Anda akan membuat aplikasi baris perintah yang dijalankan pada jadwal yang ditentukan sebelumnya. Keuntungan dari ini adalah bahwa Anda tidak perlu khawatir jika prosesnya tetap berjalan dan berjalan seperti layanan, karena jika gagal karena suatu alasan, itu akan mulai lagi di lain waktu.

Sedangkan untuk mengatur tugas-tugas tertentu, Anda benar-benar hanya perlu menyimpan tugas-tugas ini dalam penyimpanan biner yang persisten. Sampai aplikasi baris perintah mengambil mereka dari penyimpanan dan mengeksekusi mereka. Saya telah melakukan ini di masa lalu dengan menggunakan basis data Cassandra sebagai Penyedia Status Sesi untuk menjejali tugas-tugas latar belakang untuk pengguna tertentu dalam basis data Cassandra, dan kemudian meminta commandline mengambilnya dan menjalankannya untuk pengguna.

Ini mungkin bukan solusi rawa-rawa yang umum, tetapi ini bekerja dengan sangat baik bagi saya dan ternyata menjadi solusi yang sangat elegan, karena tugas yang dijadwalkan selamat dari shutdown, masalah jaringan, dan mesin apa pun yang dapat menjalankan tugas karena itu terpusat disimpan.

Promosi yang memalukan, tetapi ini adalah proyek saya dan solusi yang saya jelaskan secara singkat adalah alasan saya membuat proyek: http://github.com/managedfusion/fluentcassandra/

Nick Berardi
sumber
2
Saya melakukan ini dengan layanan hosting bersama saya karena saya tidak memiliki akses shell. Tulis halaman PHP yang melakukan sesuatu yang penting, dan kemudian miliki tugas cron yang memuat halaman menggunakan wget atau lynx secara berkala. Ini kedengarannya seperti jenis hal yang akan bekerja dalam kasus ini dan sangat sederhana, hampir tidak memerlukan perubahan cara hal-hal saat ini dilakukan.
Ricket
Solusi yang sangat sederhana. Ini telah memunculkan ide untuk proyek saya sendiri yang bahkan belum saya pertimbangkan. Plus Anda memiliki akses penuh ke basis kode yang ada. Cukup tambahkan proyek konsol ke solusi dan referensi proyek yang ada.
Tim Murphy
10

Aplikasi Cron + Web

Ini adalah desain teruji bahwa skala horizontal bersama dengan peternakan web Anda dan memastikan bahwa Anda menggunakan tumpukan teknologi web Anda sudah tahu.

Begini cara kerjanya:

  1. Buat pengontrol / aksi di aplikasi web Anda untuk menangani tugas latar belakang terjadwal. Dengan konvensi, saya biasanya memanggil saya http://mydomain.com/system/cron.
  2. Untuk keamanan, tindakan ini harus dikunci hanya untuk alamat IP yang diautentikasi pada jaringan lokal.
  3. Pada mesin terpisah, instal Wget dan atur Tugas Terjadwal agar wget mengambil sumber daya dari langkah 1. Anda dapat membuat tugas berjalan sesering yang Anda inginkan (saya biasanya memilih 30 detik). Jangan lupa untuk meneruskan argumen cookie yang sesuai ke Wget sehingga itu diautentikasi ke aplikasi web Anda.
  4. Untuk redundansi, Anda juga dapat menginstal wget terjadwal kedua pada mesin kedua.

Hore! Sekarang Anda memiliki rute yang akan dipanggil setiap 30 detik. Dan jika permintaan membutuhkan waktu 5 menit untuk diproses, tidak ada yang akan peduli, karena itu bukan bagian dari permintaan halaman pengguna.

The cronaksi akhirnya tampak sangat sederhana: ia memiliki daftar metode untuk mengeksekusi pada frekuensi tertentu. Ketika permintaan masuk, ia melihat apakah ada metode yang perlu dieksekusi dan memanggil metode yang sesuai. Ini berarti Anda dapat mengontrol jadwal di basis data Anda , di mana Anda mungkin sudah memiliki banyak data konfigurasi penting untuk situs Anda.

Lebih penting lagi (untuk Anda), ini berarti bahwa pekerjaan Anda tidak harus dipanggil pada jadwal yang tetap. Anda dapat menulis logika apa pun yang Anda inginkan untuk menentukan kapan harus mengeksekusi suatu metode.

Pro dan kontra

Pro
  • Anda sudah sangat pandai menulis kode ASP.NET MVC, jadi ini memungkinkan Anda menulis tugas latar belakang di platform yang sama dengan tempat Anda menulis sisanya.
  • Tugas dijalankan dalam konteks yang sama dengan aplikasi web Anda, sehingga Anda dapat berbagi cache dan menggunakan metode pembantu yang sudah ada.
  • Jika Anda ingin mengambil URI beban-seimbang , maka tugas latar belakang Anda sekarang juga seimbang.
  • Penempatan serentak - Anda tidak perlu khawatir tentang menyinkronkan aplikasi web Anda dengan logika tugas latar belakang Anda, karena semuanya ada dalam penerapan yang sama.
Cons
  • Selama bertahun-tahun, beberapa orang mengatakan kepada saya bahwa desain ini "sangat berpasangan", tetapi ketika ditekan mereka belum dapat mengartikulasikan mengapa itu adalah hal yang buruk.

Catatan: Jika ada pertanyaan atau masalah, silakan tambahkan komentar . Saya senang menguraikan.

Portman
sumber
7

Saya telah mencoba dan menggunakan hampir setiap cara yang mungkin untuk melakukan ini dalam aplikasi saya saat ini. Saya mulai melakukan hal yang sama seperti yang Anda lakukan saat ini, membuntuti permintaan pengguna untuk mengisi data dan kemudian menyimpannya. Saya menyadari ini adalah ide yang buruk juga (terutama karena Anda skala ke beberapa server web, lebih banyak pengguna menerima pukulan).

Saya juga telah memiliki pekerjaan yang dijadwalkan yang mengenai URL di aplikasi ASP.NET - ini adalah solusi yang layak tetapi itu mulai memecah saat Anda skala melewati 1 server web.

Saat ini saya menggunakan dua metode yang berbeda, keduanya menggunakan Quartz.NET yang merupakan perpustakaan kecil yang hebat. Yang pertama adalah Quartz.NET berjalan dalam proses dengan ASP.NET, itu adalah setup di global.asax dan berjalan setiap beberapa menit. Saya menggunakan ini untuk memperbarui cache ASP.NET keluar dari band yang merupakan satu-satunya alasan dijalankan sebagai bagian dari ASP.NET.

Yang kedua adalah saya menulis perpustakaan untuk membungkus Quartz.NET disebut DaemonMaster - membuatnya mudah untuk menjatuhkan DLL ke direktori dan menjalankannya di layanan Windows. Saya menemukan itu membantu menghindari beberapa bagian yang mengganggu dari bekerja dengan Layanan Windows dan juga membersihkan api Quartz.NET beberapa. Layanan yang dijalankan melalui DaemonMaster memiliki dua rasa berbeda, yang pertama adalah pekerjaan yang perlu dijalankan setiap malam atau setiap X minuts. Pekerjaan lain bekerja dari antrian berdasarkan data yang masuk dari aplikasi ASP.NET. Aplikasi ASP.NET menjatuhkan objek JSON di RabbitMQ dan polling layanan RabbitMQ kemudian memproses data.

Berdasarkan ini saya akan menyarankan Anda pergi dengan layanan Windows (dan periksa DaemonMaster) dan jika perlu gunakan antrian seperti RabbitMQ untuk meneruskan data dari aplikasi ASP.NET ke layanan - itu telah bekerja dengan baik dari semua solusi ini . Jika Anda memuat cache kemudian menjalankan di ASP.NET masuk akal, kalau tidak saya tidak berpikir begitu.

James Avery
sumber
6

Saya akan melakukannya dengan cara yang benar dan menjalankan Layanan Windows yang memonitor "antrian". Saya mengatakan "antrian" karena pemrograman dengan MSMQ mirip dengan menempelkan hot pokers di bola mata Anda.

Saya telah jatuh cinta dengan kesederhanaan Delayed :: Job in Rails, dan hal serupa dapat dengan mudah dilakukan di .NET.

Pada dasarnya Anda menambahkan segala jenis SomethingOperation(sesuatu yang memiliki Perform()metode). Kemudian hanya membuat serial parameter yang relevan, berikan prioritas, semacam perilaku coba lagi default dan masukkan ke dalam database.

Layanan Anda hanya akan memonitor ini dan mengerjakan pekerjaan dalam antrian.

Ben Scheirman
sumber
Menerialisasi parameter yang relevan sebenarnya bukan "adil," itu hampir "semua." Ini adalah salah satu keberatan saya yang lebih besar tentang pendekatan proses terpisah ...
Kevin Montrose
Ya itu semacam solusi yang sama dengan yang saya gunakan, namun saya membuat serial seluruh objek ke dalam database sebagai biner dan kemudian menariknya untuk dieksekusi. Saya menggunakan Cassandra sebagai penyimpanan persisten dan Penjadwal Tugas saya sebagai penjadwal CRON saya untuk aplikasi baris perintah yang akan menjalankan dan menjalankan tugas.
Nick Berardi
Kami mulai dengan hanya memasukkan sepotong data sederhana ke dalam pesan dan berakhir dengan melemparkan seluruh objek. Itu masih bekerja dengan baik. Saya akan mempertimbangkan pemisahan karena memiliki manfaat lain juga.
Nathan Palmer
@Kevin - andai saja kami memiliki beberapa orang dengan banyak sejarah serialisasi ....
Marc Gravell
4

Kami sangat senang dengan pendekatan Bus Layanan / Antrian Pesan / Layanan. Arsitektur dasarnya adalah ini.

Situs web mengirim pesan ke antrian

bus.Send(new ProjectApproved()); // returns immediately

Layanan Windows menerima dan memproses pesan pada waktunya sendiri

public class DoesSomethingAwesome : ConsumerOf<ProjectApproved>
{
   public void Consume(ProjectApproved Message)
   {
      // Do something "offline"
   }
}

Keuntungannya adalah tidak ada penundaan untuk layanan front-end yang terhubung dengan pengguna juga. Layanan windows dapat dimatikan dan ditingkatkan tanpa gangguan ke situs utama. Plus itu sangat cepat .

Jika Anda tidak dapat menyimpan semua data dalam pesan, Anda selalu dapat menyimpannya dan mengambilnya nanti. Saya sarankan menggunakan mekanisme penyimpanan dokumen seperti: RavenDB atau MongoDB di mana sangat mudah untuk menyimpan kelas Anda tanpa perubahan.

Situs web mengirim pesan ke antrian

// Save your object
store.Save(completeProject);

// Send a message indicating its ready to be processed
bus.Send(new ProjectApproved() { ProjectId = completeProject.Id });

Layanan Windows menerima dan memproses pesan pada waktunya sendiri

public class DoesSomethingAwesome : ConsumerOf<ProjectApproved>
{
   public void Consume(ProjectApproved Message)
   {
      // Retrieve your object back
      var completeProject = store.Get(Message.ProjectId);
   }
}

Untuk mempermudah, kami menggunakan: Badak ESB dan Topshelf . Konfigurasi ini sangat sederhana dan menempatkan ini untuk aplikasi yang sudah ada terbukti membutuhkan waktu yang sangat sedikit.

Nathan Palmer
sumber
Bagaimanapun, menggunakan bus layanan dengan CQRS selalu merupakan cara yang baik untuk meningkatkan skalabilitas Anda
thinkbeforecoding
3

Saya ingin tahu mengapa kombinasi keduanya bukan pilihan yang layak. Saat ini Anda memicu pekerjaan pada tampilan halaman, dengan beberapa getah sial macet menunggu 10 detik untuk halaman muncul. Setidaknya itulah pemahaman saya tentang metode Anda saat ini.

Namun pekerjaan itu membutuhkan waktu lebih lama dan lebih lama untuk berjalan seiring pertumbuhan situs, dan Anda tidak ingin menggagalkan pengalaman pengguna di situs. Bahkan untuk beberapa (atau mungkin banyak) pengguna yang tidak beruntung sepanjang hari, jadi sekarang Anda berpikir tentang menjadwalkan pekerjaan di latar belakang.

Saya tidak mengerti mengapa pekerjaan latar belakang berjalan secara berkala tidak dapat meniru pengunjung. Sekarang saya bukan programmer Windows, tetapi di dunia Linux saya akan mengatur pekerjaan cron yang berjalan pada interval reguler, dan itu akan memiliki 2 baris kode.

#!/bin/bash
wget -O /dev/null http://stackoverflow.com/specially_crafted_url

Ini menggabungkan pro dari kedua sistem. Itu dilakukan di latar belakang. Itu tidak mempengaruhi pengguna. Masih menggunakan tampilan halaman untuk memulai pekerjaan. Saya telah melihat pendekatan ini digunakan sebelumnya. Itu cenderung menjadi jalan tengah antara cara-cara sederhana yang lama, dan cara-cara yang lebih kompleks yang muncul.

Memperbarui

Saya pikir Anda bisa mengatasi masalah penyeimbangan beban dengan menjalankan pelari kerja di server web sendiri. Pelari pekerjaan menarik URL dari antrian pekerjaan, dan menjalankannya seperti ini:

wget -O /dev/null http://localhost/specially_crafted_url

Karena sifat antrian pekerjaan / perpesanan, pekerjaan tersebut akan didistribusikan secara merata di antara para pelari kerja, yang berarti special_crafted_url akhirnya didistribusikan di antara server web Anda.

mellowsoon
sumber
Kami sudah melakukan itu untuk semua yang berjalan pada interval yang dapat diprediksi, yang tersisa adalah hal-hal yang tidak dapat diprediksi terlalu jauh sebelumnya. Misalnya, "blok pertanyaan terkait" hanya diperbarui pada pertanyaan yang baru saja dilihat. Daftar pertanyaan yang ditandai juga hanya di-cache jika seseorang peduli untuk memeriksa tag tersebut. Karena kami memiliki lebih dari sejuta pertanyaan, dan mendekati tag 25k, kami tidak dapat menjalankan semua tugas terkait (dan itu hanya 2 contoh) "berjaga-jaga."
Kevin Montrose
Ada juga masalah keseimbangan beban, karena SO dibagi di beberapa server. Pada dasarnya, jika Anda pergi ke stackoverflow.com Anda akan selalu menekan server yang sama. Pendekatan wget akan memaksa kita untuk mengatur semua tugas ke satu server (atau benar-benar memperbaiki pengaturan penyeimbangan beban kita), yang akan sangat menyakitkan.
Kevin Montrose
Bersikaplah baik jika segala sesuatunya berjalan secara berkala, ya? Saya mengerti apa yang Anda katakan, tetapi metodologi yang diuraikan di atas (dan saya pikir disebutkan oleh beberapa orang lain) tidak berubah. Ketika tampilan halaman mengatakan "sudah waktunya untuk menjalankan pekerjaan ini", Anda memasukkan pekerjaan dalam antrian pesan. Pekerjaan latar belakang yang berjalan lama menjalankan pekerjaan yang ditemukannya. Dalam hal ini pekerjaan tidak lebih dari URL yang perlu diminta. hehe Anda mungkin dapat mengatur ini pada $ 20 server bersama sebulan, karena tidak perlu basis kode Anda untuk menjalankan. Lihatlah Amazon SQS untuk layanan pengiriman pesan yang mudah digunakan.
mellowsoon
Mengenai masalah keseimbangan beban. Dimana ada kemauan disitu ada jalan! Alih-alih membuat permintaan ke stackoverflow.com, Anda bisa menekan server secara acak dengan menggunakan alamat IP itu. Jika penyeimbang memuat cookie untuk permintaan pipa, Anda bisa memalsukan cookie. Jika memeriksa alamat IP, Anda mungkin bisa memalsukan itu (karena Anda tidak peduli dengan respons dari server).
mellowsoon
Setuju bahwa load balancing seharusnya tidak menjadi alasan untuk tidak melakukan ini. Karena permintaan specially_crafted_urlberasal dari IP yang dikenal, Anda bisa menambahkan aturan pada load balancer Anda untuk melakukan round-robin hanya untuk permintaan dari IP itu.
Portman
2

Saya pikir tipuan dengan pendekatan layanan murni adalah bahwa Anda memiliki kode yang tersebar ke dalam layanan dan jauh dari aplikasi inti.

Inilah yang telah kami lakukan dengan pekerjaan latar belakang non-sensitif yang besar, yang menjaga kode bersama dan menyederhanakan layanan:

  1. Buat antrian pekerjaan (baik dalam memori atau DB, apa pun kegigihan yang dibutuhkan untuk jenis pekerjaan)
  2. Buat layanan web yang akan menjalankan pekerjaan yang antri
  3. Aplikasi layanan mati sederhana yang memanggil layanan web pada interval yang ditentukan, meninggalkan semua hal yang kompleks (pengambilan pekerjaan dan eksekusi) ke layanan web dalam basis kode inti Anda.

Lebih sederhana lagi, cukup buat panggilan di aplikasi konsol dan gunakan Penjadwal Tugas atau VisualCron untuk mengubahnya menjadi "layanan".

Brandon
sumber
1
Saya mendapatkan ini dalam aplikasi signifikan di tempat kerja - Layanan Windows yang memicu aplikasi web secara berkala. Aplikasi web tetap tanpa kewarganegaraan, menarik status dari basis data sesuai kebutuhan. Berhasil.
Bevan
1

Saya suka TopShelf. Menjaga kesederhanaan, namun tetap melakukannya dengan cara yang benar berjalan sebagai Layanan Windows. Pada dasarnya buat Aplikasi Konsol, tambahkan sekitar 15-20 baris kode, lalu instal sebagai layanan.

http://code.google.com/p/topshelf/

Shane
sumber
1

Bagaimana dengan memiliki layanan Windows yang sangat sederhana yang berjalan di server web dan secara berkala mengenai URL pemeliharaan yang melakukan tugas-tugas lain Anda. Apakah itu mencekik berapa banyak pekerjaan yang dilakukannya dalam permintaan yang diberikan.

Rob Sobers
sumber
1

Saya akan melawan tren nyata di sini dan menyarankan untuk menggunakan model in-IIS. Saya sudah menggunakannya sendiri dan berfungsi dengan sangat baik. Benar-benar tidak sulit untuk mengimplementasikan kelas thread-pool yang layak (selama bertahun-tahun, saya telah memperpanjang kelas thread-pool saya untuk mendukung penciptaan dan penghancuran thread yang dinamis, mencoba kembali pekerjaan dan sebagainya). Keuntungannya adalah:

  • Tidak ada layanan eksternal untuk dipantau
  • Kesederhanaan implementasi: tidak ada proses lintas proses, tidak ada pemantauan pekerjaan lanjutan
  • Anda masih dalam proses IIS Anda, sehingga Anda dapat melakukan semua pendataan yang biasa dan seterusnya (tidak perlu untuk banyak file log)
  • Penyebaran yang sangat disederhanakan (saat Anda memperbarui layanan, Anda harus menghentikan layanan, menyalin file, memulai layanan - ini merupakan tambahan untuk pembaruan biasa ke kode situs web)

Menurut pendapat saya, solusi di-IIS hanyalah "langkah berikutnya" dari memboncengkan pekerjaan ke tampilan halaman acak.

Dean Harding
sumber
1

Resque bagus. Atau bahkan Kthxbye jika Anda perlu diberitahu tentang nilai yang dihasilkan setelah selesai.

Keduanya berbasis Redis / Ruby.

Jujur, jika Anda melakukan pendekatan berbasis layanan, itu benar-benar tidak perlu super-terintegrasi dengan platform Anda saat ini, yang saya rasa merupakan nilai tambah. Saya berharap itu bisa menjadi sistem set-dan-lupa yang akan berjalan (dengan pemantauan semacam) dan menyelesaikan pekerjaan. Saya tidak yakin itu harus dijalankan pada platform yang sama sekali karena hanya memperbarui / memodifikasi info basis data.

Cukup yakin Anda bisa lolos dengan lebih banyak dengan lebih sedikit jika Anda menanam ini agak berhasil untuk entitas yang terpisah, terutama karena tampaknya Anda sedang berurusan dengan masalah threading. Baik Resque dan Kthxbye memindahkan pemrosesan ke proses terpisah untuk memungkinkan OS menangani konkurensi.

Dijual kembali

Kthxbye

Lukas
sumber
Saya harus mencoba Kthxbye jika hanya karena nama yang hebat!
Nathan Palmer
cukup luar biasa. selanjutnya akan menjadi ORLY? Perpustakaan. mungkin untuk pemantauan statistik semacam ...;)
Lukas
0

Saya akan menggunakan layanan WCF yang di-hosting WAS mendengarkan Antrian MSMQ.

Pro

  • Api dan lupakan pesan satu arah dari aplikasi web

  • Throttling dan coba ulang MSMQ / WCF

  • Pengiriman terjamin; D

  • Manajemen Surat Mati

  • Pemrosesan terdistribusi

  • Aktivasi WAS / MSMQ

Con

  • MSMQ (belum mati ... Belum)

Fitur MSMQ di WCF membuat penggunaan MSMQ sangat bagus. Ya, Anda akan kehabisan konfigurasi tetapi manfaatnya akan lebih besar dari pengorbanan.


sumber
0

Saya pernah mengalami ini beberapa kali ketika mengembangkan aplikasi web. Kami telah menyelesaikannya dengan membuat aplikasi konsol windows yang melakukan tugas, dan membuat tugas terjadwal yang berjalan sesering mungkin untuk benar-benar melakukan tugas tersebut.

John Christensen
sumber
0

Anda dapat shunt bekerja ke utas latar (atau banyak utas latar belakang) menggunakan Rx dan sesuatu seperti berikut:

var scheduler = new EventLoopScheduler( SchedulerThreadName );
_workToDo = new Subject<Action>();
var queueSubscription = _workToDo.ObserveOn( scheduler ).Subscribe( work => work() );
_cleanup = new CompositeDisposable( queueSubscription, scheduler );

Menggunakan:

var work = () => { ... };
_workToDo.OnNext( work ); // Can also put on error / on complete in here

Host semua itu di dalam kelas yang hanya ada satu (alias singleton, tetapi lakukan dengan benar - gunakan wadah IoC Anda untuk menentukan gaya hidup).

Anda dapat mengontrol ukuran kumpulan utas dll dengan menulis penjadwal kustom sebagai pengganti menggunakan EventLoopScheduler (yang menjalankan utas tunggal).

Neal
sumber
0

Saya telah menerapkan hal semacam ini beberapa kali. Di windows, saya membuat program baris perintah python yang melakukan sesuatu di berbagai waktu. Program ini juga memperlihatkan antarmuka xmlrpc di porta. Kemudian, tugas terjadwal berjalan setiap menit dan menanyakan antarmuka xmlrpc. Jika tidak, mereka mencoba meluncurkannya. Jika tidak, email saya.

Keuntungannya adalah bahwa pekerjaan yang dijalankan tidak terikat cron atau jadwal. Saya memiliki pekerjaan proses yang berjalan setiap detik, tetapi akan menunggu lebih lama antara memulai pekerjaan baru tergantung pada apakah pekerjaan itu harus dilakukan. Juga, dapat digunakan untuk bertindak secara cerdas berdasarkan hasil. Punya 500 kesalahan? Punya penundaan sangat lama? Lakukan sesuatu yang lain. Beri tahu layanan lain. Dll

Dan sistem yang sama berfungsi pada unix, dengan sedikit modifikasi.

Christopher Mahan
sumber
0

Saya sendiri tidak punya jawaban untuk Anda, tetapi masalahnya berbunyi lonceng - Saya ingat beberapa pria acak mendiskusikannya di podcast sekali .

Spolsky: Saya perhatikan salah satu pertanyaan yang Anda tanyakan di blog adalah bagaimana seharusnya Anda menangani tugas pemeliharaan rutin secara umum?

Atwood: Ya.

Spolsky: Apakah itu karakterisasi yang adil? Setiap situs web memiliki beberapa tugas yang tidak ingin Anda lakukan pada saat sebuah halaman web dimuat, tetapi Anda ingin menjalankannya dengan semacam pengulangan.

Atwood: Ya, tugas-tugas latar belakang semacam itu.

Spolsky: Ya, jadi apa yang Anda pikirkan?

Atwood: Ya, saya awalnya bertanya di Twitter, karena saya hanya menginginkan sesuatu yang ringan. Saya benar-benar tidak ingin suka menulis layanan windows. Saya merasa seperti itu keluar dari kode band. Ditambah kode yang benar-benar berfungsi adalah halaman web pada kenyataannya, karena bagi saya yang merupakan unit kerja logis pada situs web adalah halaman web. Jadi, sepertinya kami menelepon kembali ke situs web, itu seperti permintaan lain di situs web, jadi saya melihatnya sebagai sesuatu yang harus tetap sejalan, dan sedikit pendekatan yang kami lakukan yang direkomendasikan kepada saya di Twitter adalah pada dasarnya untuk menambahkan sesuatu ke cache aplikasi dengan kedaluwarsa tetap, maka Anda memiliki panggilan kembali sehingga ketika yang kedaluwarsa itu memanggil fungsi tertentu yang berfungsi kemudian Anda menambahkannya kembali ke cache dengan kedaluwarsa yang sama.

Berpikir aneh
sumber
1
Ya, itu berfungsi untuk situs yang jauh lebih kecil daripada StackOverflow. Skala adalah masalah besar di sini, sayangnya (atau untungnya, tergantung pada bagaimana Anda melihatnya).
Kevin Montrose
@ Kevin Montrose, saya mohon ketidaktahuan domain lengkap di sini. Bisakah Anda jelaskan mengapa memiliki halaman web rahasia melakukan pekerjaan (mungkin dalam unit kecil) dan dipanggil oleh pekerjaan menyegarkan halaman / cron di tempat lain tidak dapat diskalakan? Saya tidak ragu Anda benar, tetapi saya ingin belajar.
Oddthinking
saran khusus Anda (cache yang kadaluwarsa) tidak berskala karena semua kadaluwarsa cache (di ASP.NET) menjalankan utas tunggal (ini adalah peretasan yang cerdik untuk situs yang lebih kecil, seperti SO dulu). Tugas cron tidak skala karena kami telah melampaui satu server (SO sekarang 3, dan masih terus bertambah) dan tugas cron apa pun akan mengenai server tunggal (setidaknya, mengubah invarian itu akan sangat menyakitkan dengan beban kami- pengaturan keseimbangan). Tugas cron juga harus berjalan sangat sering, karena tugas ini berulang berdasarkan urutan menit.
Kevin Montrose
Perlu dicatat bahwa kami menggunakan penjadwalan "gaya cron" untuk menjalankan yang lebih jarang, interval tetap, tugas sudah, hal-hal seperti hibah lencana dan pemberitahuan email setiap hari.
Kevin Montrose
0

Ikhtisar Antrian API Java

Konsep Tugas
Dalam pemrosesan latar belakang App Engine, tugas adalah deskripsi lengkap dari unit kerja kecil. Deskripsi ini terdiri dari dua bagian:

  • Payload data yang menentukan parameter tugas.
  • Kode yang mengimplementasikan tugas.

Tugas sebagai Kait Web Offline
Untungnya, Internet sudah menyediakan solusi semacam itu, dalam bentuk permintaan HTTP dan responsnya. Payload data adalah isi permintaan HTTP, seperti variabel formulir web, XML, JSON, atau data biner yang disandikan. Referensi kode adalah URL itu sendiri; kode aktual adalah logika apa pun yang dijalankan server dalam menyiapkan respons.

antony.trupe
sumber
Saya tidak menyarankan menggunakan api antrian tugas GAE, tetapi mengikuti model mereka. Mereka sudah memikirkannya sebentar dan menulis implementasinya.
antony.trupe
0

Lakukan keduanya

Tambahkan parameter opsional ke jalur pertanyaan yang berfungsi saat Anda membonceng permintaan pengguna:

Melayani tugas latar belakang di situs besar

Membuat aplikasi konsol yang berjalan di setiap server dan membuka biner log bersama IIS dan membacanya ke akhir file saat ini. Gunakan pengamat sistem file atau interval waktu untuk membaca maju untuk mengumpulkan pembaruan saat IIS membersihkan log.

Gunakan informasi ini untuk menentukan halaman apa yang saat ini dilihat.

Gunakan url halaman dari log yang diuraikan untuk memanggil versi "extrastuff" dari url di localhost dengan objek klien web.

Tambahkan beberapa kode untuk beralih file pada akhir setiap periode log atau memulai kembali proses setiap periode log.

Tagihan
sumber