Arka planda görevlerin büyük bir sitede yapılması


49

StackOverflow'ta ilginç bir problemle karşı karşıyayız.

Bir sürü küçük "yakında yapılması gerekenler" görevimiz var. Bir örnek "İlgili Sorular" listelerini güncelliyor. Geçmişte yaptığımız şey, bu görevleri bazı kullanıcıların sayfa yüklerine geri döndürmek.

Bu asla ideal değildi, ama gerçekten farkedilmedi. Şimdi SO, 1.000.000 soru işaretini geçti, bu şanssız kullanıcılar bunu hissetmeye başlıyor.

Doğal çözüm, bu görevleri aslında arka plana itmek. Bunu yapmanın iki geniş yolu var.

1. Özel bir iş parçacığı havuzu / Work-Queue olarak IIS'de

Temel olarak, bir kaç ( ThreadPool olmayan , IIS ile çakışmayacak şekilde) konuları açıyoruz ve Funcs'a attığımız bazı koleksiyonlara hizmet veriyoruz .

Buradaki en büyük profesyonel sadelik. Herhangi bir şeyi paylaşmak konusunda endişelenmek zorunda değiliz, ne de bazı dış hizmetlerin açık ve yanıtlı olduğundan emin olmak zorunda değiliz.

Ayrıca tüm ortak kodumuza da erişebiliyoruz.

Con, arka plan iplikleri kullanmamamız gerektiğidir. Benim tanıdığım itirazların tümü (eğer ThreadPool kullanıyorsanız) açlıktan ölmek üzere olan ve rasgele (AppPool geri dönüşümü nedeniyle) ölen iplikler etrafında toplanıyor.

Rastgele iş parçacığı ölümünü bir sorun haline getirmek için mevcut bir altyapımız var (temelde bir görevi saptamak mümkün) ve iş parçacığı sayısını sınırlamak da (ve ThreadPool olmayan iş parçacıklarını kullanmak) da zor değil.

IIS işleminde iş parçacığı havuzu oluşturma / iş kuyrukları için başka herhangi bir itirazım var mı?

Burada gerçekten adreslenmediği için StackOverflow'a taşındı .

2. Bir Hizmet Olarak

Bazı üçüncü taraf çözümleri veya özel bir çözüm.

Temel olarak, süreç sınırını aşarak bazı hizmetlere bir görev verdik ve unut gitsin. Muhtemelen bazı kodları ham SQL + a bağlantı dizgisine bağladık ya da bunlarla sınırlıyız.

Profesyonel, bunu yapmanın "doğru yolu".

Dezavantajları ne yapabileceğimiz konusunda çok kısıtlı olduğumuz ya da bu hizmeti kod tabanımızla senkronize etmek için bir sistem üzerinde çalışmak zorunda kalacağız. Ayrıca, "IIS'de" seçeneğiyle ücretsiz olarak alacağımız tüm izleme ve hata günlüğü kayıtlarımızı bir şekilde bağlamamız gerekecek.

Hizmet anlayışının başka faydaları veya sorunları var mı?

Özet olarak, 1. yaklaşımı işlenemez hale getiren, öngörülemeyen ve aşılmaz bir problem var mı ve eğer öyleyse, 2. yaklaşımı aramamız gereken iyi üçüncü taraf hizmetleri var mı?


Doğru yol, diğer tarafa gitmeye karar verdiğinizde geriye dönüp baktığımızı ve doğru şekilde yapmamız gerektiğini söylememizdir. Akıllıca seçim. Ancak, IIS dünyası ile bu sorun hakkında yorum yapacak kadar aşina değilim.
Chris

2
Merak ediyorum çünkü benzer bir senaryoya sahibim (çok daha küçük ölçekte) ve ben de rastgele bazı kullanıcılar şanssız bağlantılara destek oluyorum. En iyi çözüme aşina değilim, bu yüzden burada devam edeceğim. :-)
pc1oad1etter

7
Bunun neden StackOverflow'ta olmadığını anlamıyorum. Bu bir mühendislik harikası, öznel bir değerleme değil. Farklı yaklaşımların analizini istiyorsun - hepsi bu. Ancak analiz tam olarak tradeoffların ne olduğunu açıkça ortaya koyduğunda, herhangi bir öznellik var mı ve sorunuzu görebildiğim kadarıyla 'daha önemli ne bulmalıyım, zaman ve sunucu kaynaklarımı veya kullanıcı zamanımı? ' Veya benzeri.
Joren

@Kevin Montrose - yorumlarınızdan, "yakında yapılması gerekenler" ile "belirli aralıklarla zamanlanmış" arasında bir ayrım yapıyormuşsunuz gibi görünüyor. Bunların neden farklı bir desen / altyapı gerektiren iki farklı tür arka plan görevi olduğunu açıklayabilir misiniz?
Portman

@Portman - Temel fark, "yakında-ish" görevlerinin spekülatif olarak yapılamamasıdır, yapılması gerektiğini bilene kadar gerçekten beklememiz gerekir . Zarf hesaplamalarının bir kısmı, "İlgili Sorular" sorgularını (sadece bir tanesinden) "aptal" bir cron sekmesine taşımak olsaydı, bunun yaklaşık alacağını gösteriyor. tüm sorular üzerinden çalışmak için sağlam bir uygulama. Genellikle onların da mümkün olan en kısa sürede (kullanıcı deneyimini etkilemeden) çalışmalarını isteriz; oysa aralık görevlerimiz 5 dakika içinde bir defadan daha sık (ve normalde daha az sıklıkta) çalıştırılarak elde edilebilir.
Kevin Montrose

Yanıtlar:


17

Birkaç hafta önce SO'da benzer bir soru sordum . Bir somun kabuğunda, bir süredir benim yaklaşımım bir Windows Hizmeti geliştirmek oldu. Web uygulamamdan hizmetime kadar marşal taleplerde NServiceBus'u (kapakların altındaki aslen MSMQ) kullanırdım. WCF kullanırdım, ancak WCF üzerinde doğru bir şekilde çalışmak için dağıtılmış bir işlem almak her zaman kıçımdaki bir acı gibi görünüyordu. NServiceBus numarayı yaptı, bir işlemde veri işleyebilir ve görevler oluşturabilir ve hizmetimin o sırada çalışıp çalışmadığına endişe etmem. Basit bir örnek olarak, eğer bir e-posta göndermem gerekiyorsa (örneğin bir kayıt e-postası), bir kullanıcı hesabını oluşturur ve bir işlemdeki Windows Hizmetime (e-postayı göndermek için) bir sinyal gönderirim. Servis tarafındaki mesaj işleyicisi mesajı alır ve buna göre işlem yapar.

ASP .NET 4.0 ve AppFabric piyasaya sürüldüğünden, yukarıdaki mekanizmaya uygun birçok alternatif var. Yukarıda bahsettiğim soruya geri dönersek, artık AppFabric'in AppInitialize (net.pipe) ile ASP .NET 4.0'ın Windows Başlat'ı web uygulamaları olarak geliştirmeyi uygun bir alternatif haline getiren Auto-Start (Otomatik Başlatma) özelliğine sahibiz. Bunu şimdi birkaç nedenden ötürü yapmaya başladım (en büyüğü konuşlandırmanın artık eşek ağrıları değil):

  1. Servisiniz üzerinden bir web kullanıcı arayüzü geliştirebilirsiniz (çünkü bir web uygulaması olarak çalışıyor). Bu, çalışma zamanında neler olduğunu görmek için son derece kullanışlıdır.
  2. Web uygulamalarınız için dağıtım modeliniz, servis uygulamanız için çalışacaktır.
  3. IIS, uygulama hatalarını ele almak için birkaç zarif özellik sunar (bazı durumlarda Windows Hizmetine benzer).
  4. Web geliştiricileri (doğal olarak) web uygulamaları geliştirmeye çok aşinarlar, çoğu Windows Hizmeti geliştirirken en iyi uygulama hakkında çok şey bilmezler.
  5. Bir API'yi diğer uygulamaların kullanması için göstermek için çeşitli seçenekler sunar.

Bu rotaya giderseniz (orijinal gönderimden kopyalayıp yapıştırdığım için beni bağışlayın) kesinlikle arka plan mantığını ayrı bir web uygulamasında çalıştırmayı düşünürdüm. Bunun nedenleri var:

  1. Güvenlik . Çalışan arka plan işlemleri hakkında bilgi görüntüleyen UI için farklı bir güvenlik modeli olabilir. Bu kullanıcı arayüzünü ops ekibinden başka kimseye ifşa etmek istemem. Ayrıca, web uygulaması, yükseltilmiş bir izin kümesine sahip farklı bir kullanıcı olarak çalışabilir.
  2. Bakım . Kullanıcının ön uç web sitesini kullanmasını etkilemeden arka plan işlemlerini barındıran uygulamadaki değişiklikleri uygulayabilmeniz harika olurdu.
  3. Performans . Uygulamanın ana site işleme kullanıcı isteklerinden ayrı tutulması, arka plan iş parçacıklarının IIS'nin gelen istek sırasını işleme yeteneğini azaltmayacağı anlamına gelir. Ayrıca, arka plan görevlerini işleyen uygulama, gerekirse ayrı bir sunucuya dağıtılabilir.

Bunu yapmak, büzülme yönüne geri döner. WCF, NServiceBus / RabbitMQ / ActiveMQ vb., Vanilya MSMQ, RESTful API (MVC'yi düşün) tüm seçeneklerdir. Windows Workflow 4.0 kullanıyorsanız, web uygulamanızın kullanabileceği bir ana bilgisayar uç noktasını ortaya çıkarabilirsiniz.

Web hizmetleri için barındırma yaklaşımı hala oldukça yeni, sadece doğru seçim olup olmadığını söyleyecektir. Şimdiye kadar çok iyi olsa. Bu arada, eğer AppFabric kullanmak istemiyorsanız (bazı tuhaf sebeplerden dolayı, Windows Server Web Edition desteklenmez), Gu'nun gönderisinde belirtilen Otomatik Başlatma özelliği iyi çalışıyor. Ancak applicationhost.config dosyasından uzak durun, bu yazıdaki her şey IIS konsolu (ana sunucu düzeyinde Konfigürasyon Düzenleyicisi) aracılığıyla ayarlanabilir.

Not: Aslen bu mesajda birkaç bağlantı daha göndermiştim, fakat ne yazık ki, bu borsada ilk gönderim ve sadece bir link desteklendi! Temelde iki kişi daha vardı; Google’ı “Windows Hizmetlerine Ölüm… Yaşasın AppFabric!” ve "auto-start-asp-net-apps". Bunun için üzgünüm.


Ayrı bir web sitesini hizmet olarak kullanmanın temel fikri, göz önünde bulundurmadığım ilgi çekici bir ...
Kevin Montrose

Rohland, burada bir şeyleri özlüyorum, ama NServiceBus işleyicinizin içinden bir Windows Servisi ile etkileşime girdiğinizi söylüyor gibi görünüyorsunuz, servis daha sonra e-postayı gönderiyor. Haklıysam, e-postayı neden bir NServiceBus ileti işleyicisinden göndermemeniz gerektiğini sorabilir miyim, geliştirmek, test etmek ve dağıtmak çok kolay olurdu?
Sean Kearon

Web sitesi, Windows Hizmetine bir mesaj gönderir. Windows Hizmeti NServiceBus ileti işleyicisi, iletiyi alır ve iletiyi gönderir. Temelde, tanımladığınız işlemle aynıdır.
Rohland

22

Aslında, arka plan hizmetlerini çalıştırmak için Windows'ta üçüncü bir yol var ve UNIX dünyasında çok yaygın. Üçüncüsü CRON, altyapınızın bir parçasını çalıştıran bir iştir. Windows'ta bu, task schedulerzamanlanmış kod çalıştırmak için çok yaygındır ve çok yaygındır. Bunu kullanmak için önceden tanımlanmış bir programda yürütülen bir komut satırı uygulaması oluşturacaksınız. Bunun avantajı, işlem bir hizmet gibi devam ederse ve çalışıyorsa endişelenmenize gerek kalmamasıdır, çünkü bir nedenden dolayı başarısız olursa, bir dahaki sefere başlayacaktır.

Belirli görevleri birleştirmeye gelince, bu görevleri kalıcı bir ikili depoda kaydetmeniz yeterlidir. Komut satırı uygulaması onları depolama alanından seçinceye ve yürütür. Bunu geçmişte Cassandra veritabanında belirli kullanıcılar için arka plan görevlerini doldurmak için Oturum Devlet Sağlayıcısı olarak Cassandra veritabanını kullanarak ve ardından komut satırının bunları seçip kullanıcı için yürütmesini sağladım.

Bu tipik marshaling çözümü olmayabilir, ancak benim için çok iyi sonuç verdi ve çok zarif bir çözüm olduğu ortaya çıktı, çünkü zamanlanmış görevler kesintilerden kurtuldu, ağ sorunları ve herhangi bir makine görevi yerine getirebildiğinden beri saklanmış.

Utanmaz tanıtım, ancak bu benim projem ve kısaca ayrıntılandırdığım çözüm, projeyi neden oluşturduğumdur: http://github.com/managedfusion/fluentcassandra/


2
Kabuk erişimim olmadığı için bunu paylaşımlı barındırma hizmetimle yapıyorum. Önemli bir şey yapan bir PHP sayfası yazın ve ardından periyodik olarak wget veya lynx kullanarak sayfayı yükleyen bir cron işi yapın. Bu, tam da bu durumda işe yarayacak olan şeylerin türüne benziyor ve son derece basit, şu anda işlerin yapılma şeklini değiştirmek zor.
Ricket

Ne kadar basit bir çözüm. Kendi projem için henüz düşünmediğim bile fikir üretti. Ayrıca mevcut kod tabanınıza tam erişime sahipsiniz. Sadece çözüme bir konsol projesi ekleyin ve mevcut projeleri referans alın.
Tim Murphy

10

Cron + Web Uygulaması

Bu, web grubunuzla birlikte yatay olarak ölçeklenen ve zaten bildiğiniz web teknolojisi yığınını kullanmanızı sağlayan, savaşta test edilmiş bir tasarımdır .

İşte nasıl çalışıyor:

  1. Zamanlanmış arka plan görevlerini yerine getirmek için web uygulamanızda bir denetleyici / işlem oluşturun. Kongre ile genellikle benimkini çağırırım http://mydomain.com/system/cron.
  2. Güvenlik için, bu işlem yalnızca yerel ağdaki kimliği doğrulanmış IP adreslerine kilitlenmelidir.
  3. Ayrı bir makinede, Wget'ı yükleyin ve wget'ın 1. adımdaki kaynağı almasını sağlamak için Zamanlanmış Görev ayarlayın . Görevin istediğiniz sıklıkta çalışmasını sağlayabilirsiniz (genellikle 30 saniye seçerim). Web sitenize doğrulamak için uygun çerez bağımsız değişkenini Wget'a iletmeyi unutmayın.
  4. Artıklık için, ikinci bir makineye ikinci zamanlanmış bir wget da yükleyebilirsiniz.

Yaşasın! Şimdi her 30 saniyede bir çağrılacak olan bir rotanız var. İsteğin işleme koyulması 5 dakika sürerse, hiç kimse umursamaz, çünkü bu bir kullanıcının sayfa isteğinin bir parçası değildir.

cronEylem çok basit görünümlü biter: o belirli frekansta yürütülecek yöntemlerinin bir listesi vardır. Bir istek geldiğinde, yürütülmesi gereken bir yöntem olup olmadığını görür ve uygun yöntemi çağırır. Bu , muhtemelen siteniz için birçok önemli yapılandırma verisine sahip olduğunuz zaman çizelgesini veritabanınızdaki kontrol edebileceğiniz anlamına gelir .

Daha da önemlisi (sizin için), bu, işlerinizin sabit bir programda çağrılması gerekmediği anlamına gelir. Bir yöntemin ne zaman yürütüleceğini belirlemek için istediğiniz herhangi bir mantığı yazabilirsiniz.

Lehte ve aleyhte olanlar

Artıları
  • ASP.NET MVC kodunu yazmakta zaten çok iyisiniz, bu nedenle arka plan görevlerinizi , çözümünüzün geri kalanını yazdığınız aynı platformda yazmanıza olanak tanır .
  • Görevler web uygulamanızla aynı bağlamda çalışır, böylece önbelleği paylaşabilir ve zaten mevcut olan yardımcı yöntemleri kullanabilirsiniz .
  • Wget yük dengeli bir URI getirdiyseniz, arka plan görevleriniz de artık yük dengelidir.
  • Eşzamanlı dağıtım - web uygulamanızı arka plan görev mantığınızla senkronize etmekten endişelenmenize gerek yok, çünkü hepsi aynı dağıtımda.
Eksileri
  • Yıllar boyunca, birkaç kişi bana bu tasarımın “son derece eşleşmiş” olduğunu söyledi, ancak basıldığında bunun neden kötü bir şey olduğunu açıkça söyleyemediler.

Not: Herhangi bir sorunuz veya endişeniz varsa, lütfen bir yorum ekleyin . Detaylandırmaktan mutluyum.


7

Mevcut başvurumda bunu yapmanın hemen hemen her yolunu denedim ve kullandım. Şu anda yaptığınız şeyi yapmaya başladım, verileri doldurmak için bir kullanıcı isteğinde bulunmaya başladım ve ileriye doğru önbelleğe aldım. Bunun da kötü bir fikir olduğunu fark ettim (özellikle birden fazla web sunucusuna ölçeklediğinizde daha fazla kullanıcı dikkat çekiyor).

Ayrıca ASP.NET uygulamasında bir URL'ye hitap eden zamanlanmış bir işim oldu - bu iyi bir çözüm ama 1 web sunucusunu geçtiğiniz dakikayı bozmaya başladı.

Şu anda, ikisi de harika bir kütüphane olan Quartz.NET kullanarak iki farklı yöntem kullanıyorum. İlki, ASP.NET ile işlem halinde olan Quartz.NET'tir, global.asax'ta kurulur ve her birkaç dakikada bir çalışır. Bunu ASP.NET önbelleğini, ASP.NET'in bir parçası olarak çalıştırılmasının tek nedeni olan bant dışı güncellemek için kullanıyorum.

İkincisi, Quartz.NET'i DaemonMaster adında sarmalamak için bir kütüphane yazmamdı - bir DLL dosyasını bir dizine bırakıp Windows hizmetinde çalıştırmasını kolaylaştırır. Windows Hizmeti ile çalışmanın can sıkıcı kısımlarından kaçınmaya yardımcı olduğunu ve aynı zamanda bazı Quartz.NET api'leri temizlediğini gördüm. DaemonMaster'dan geçen hizmetler iki farklı tada sahiptir; ilki, her gece veya her X aşağısında çalıştırılması gereken işler. Diğer işler, ASP.NET uygulamasından gelen verilere göre bir sıradan çıkar. ASP.NET uygulaması, JSM nesnelerini RabbitMQ üzerine bırakır ve servisler RabbitMQ anketini ardından verileri işler.

Buna dayanarak, bir Windows servisine gitmenizi (ve DaemonMaster'a göz atmanızı) öneririm ve gerekirse verileri ASP.NET uygulamasından servislere aktarmak için RabbitMQ gibi bir sıra kullanın - tüm bu çözümlerden en iyi şekilde yararlandı. . Eğer önbellek yüklüyorsanız ASP.NET'te çalıştırmanız mantıklı olur, aksi halde yapmayı sanmıyorum.


6

Doğru şekilde yaparım ve çalışan bir "sıra" izleyen bir Windows hizmeti var. "Kuyruk" diyorum, çünkü w / MSMQ programlama, gözeneklerinize sıcak deliciler takmaya benzer.

Gecikmeli :: Rails in Job'un sadeliğine aşık oldum ve benzer bir şey kolayca .NET'te yapılabilirdi.

Temel olarak, herhangi bir tür eklersiniz SomethingOperation( Perform()yöntemi olan bir şey ). Ardından ilgili parametreleri serileştirin, öncelik verin, bir tür varsayılan yeniden deneme davranışı yapın ve veritabanına yerleştirin.

Servisiniz sadece bunu izler ve sıradaki işleri yapardı.


İlgili parametrelerin seri hale getirilmesi gerçekten bir "adil" değil, neredeyse "hepsi" dir. Ayrı süreç yaklaşımı hakkındaki en büyük çekincelerimden biri ...
Kevin Montrose

Evet, kullandığım çözümün aynısı, ancak tüm nesneyi veritabanına bir ikili olarak seri hale getirdim ve yürütmek için çıkardım. Kalıcı depolama alanım olarak Cassandra'yı ve görevleri yürütecek komut satırı uygulaması için CRON zamanlayıcım olarak Görev Zamanlayıcı'yı kullandım.
Nick Berardi

Mesaja basit bir veri parçası ekleyerek ve tüm nesneyi fırlatıp bitirerek başladık. Hala harika çalıştı. Ayrımı diğer yararları da olduğu için düşünürdüm.
Nathan Palmer

@Kevin - Keşke birçok seri hale getirme geçmişine sahip birileri olsaydı ....
Marc Gravell

4

Servis Veri Yolu / Mesaj Kuyruğu / Servis yaklaşımı ile oldukça mutluyuz. Temel mimari budur.

Web sitesi kuyruğa mesaj gönderir

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

Windows hizmeti mesajı kendi zamanında alır ve işler.

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

Avantaj, kullanıcıların da bağlı olduğu ön uç hizmet için gecikme olmamasıdır. Windows hizmeti kapatılabilir ve ana siteye kesintisiz olarak yükseltilebilir. Ayrıca son derece hızlı .

Tüm verilerinizi mesaj içinde saklayamıyorsanız, her zaman saklayabilir ve daha sonra alabilirsiniz. Aşağıdakileri gibi bir belge depolama mekanizması kullanmanızı öneririm: RavenDB veya MongoDB , sınıflarınızı değişiklik yapmadan kaydetmenin çok kolay olduğu bir yer.

Web sitesi kuyruğa mesaj gönderir

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

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

Windows hizmeti mesajı kendi zamanında alır ve işler.

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

Kolaylaştırmak için kullandığımız şeyler: Rhino ESB ve Topshelf . Yapılandırma son derece basittir ve bunu mevcut bir uygulama için uygulamaya koymak çok az zaman aldı.


Neyse, CQRS ile servis aracını kullanarak ölçeklenebilirlik geliştirmek için iyi bir yoldur daima
thinkbeforecoding

3

Neden ikisinin kombinasyonunun uygun bir seçenek olmadığını merak ediyorum. Şu anda sayfa görünümlerinde işleri tetikliyorsunuz, bazı şanssız saplar sayfanın ortaya çıkması için 10 saniye beklemekte. En azından şu anki yöntemini anladım.

Bununla birlikte, bu işler, site büyüdükçe daha uzun ve daha uzun sürüyor ve sitedeki kullanıcı deneyimini raydan çıkarmak istemiyorsunuz. Birkaç gün boyunca (veya belki de çok sayıda) şanssız kullanıcılar için bile olsa, şimdi arka planda işlerin planlanmasını düşünüyorsunuz.

Arka planda çalışan bir işin düzenli aralıklarla neden ziyaretçiyi taklit edemediğini anlamıyorum. Şimdi bir Windows programcısı değilim, ama Linux dünyasında düzenli aralıklarla çalışan bir cron işi kurardım ve 2 satırlık bir kod satırı olurdu.

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

Her iki sistemin de artılarını birleştiriyor. Arka planda yapılır. Kullanıcıları etkilemez. Hala işi başlatmak için sayfa görünümü kullanıyor. Daha önce kullanılan bu yaklaşımı gördüm. Basit eski yöntemlerle yoldan çıkan daha karmaşık yolların arasındaki orta yol olma eğilimindedir.

Güncelleme

İş koşucularını web sunucularında çalıştırarak yük dengeleme sorununu çözebileceğinizi düşünüyorum. İş çalıştırıcı, bir URL'yi iş kuyruğundan çıkarır ve şöyle çalıştırır:

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

İş / mesajlaşma kuyruklarının doğası gereği, işler iş yapanlar arasında eşit bir şekilde dağılmış olacak, bu da specially_crafted_url sonunda web sunucularınız arasında dağıtılmış demektir.


Bunu zaten tahmin edilebilir aralıklarla çalışan her şey için yapıyoruz, geride bıraktığımız şey önceden çok önceden tahmin edilemeyecek şeyler. Örneğin, "ilgili sorular bloğu" yalnızca son zamanlarda görüntülenen sorular üzerinde güncellenir. Etiketli soru listeleri de aynı şekilde ancak eğer birisi bu etiketleri kontrol etmeyi önemserse önbelleğe alınır. Bir milyonun üzerinde soru olduğumuz ve 25 k etiketine yaklaştığımız için, tüm ilişkili görevleri (ve sadece 2 örnek) çalıştıramıyoruz.
Kevin Montrose

SO birden fazla sunucuya bölündüğü için yük dengesi sorunları da vardır. Temel olarak, stackoverflow.com 'a giderseniz, daima aynı sunucuya ulaşırsınız. Wget yaklaşımı bizi tüm işleri tek bir sunucuya (veya yük dengeleme kurulumumuzu gerçekten elden geçirecek şekilde) atlatmaya zorlardı, bu gerçekten acı verici olurdu.
Kevin Montrose

İşler düzenli aralıklarla yapılırsa kibar olun, ha? Ne dediğini anlıyorum ama yukarıda belirtilen metodoloji (ve birkaç kişi tarafından da bahsettiğimi düşünüyorum) değişmiyor. Bir sayfa görünümünde "bu işi çalıştırmanın zamanı geldi" dediğinde, işi bir mesaj kuyruğuna sokarsınız. Uzun süre çalışan bir arka plan işi bulduğu işleri çalıştırır. Bu durumda, işler talep edilmesi gereken URL’lerden başka bir şey değildir. hehe Muhtemelen bunu 20 $ 'lık ayda paylaşılan bir sunucuya kurabilirsiniz, çünkü kod tabanınızın çalışması gerekmez. Kullanımı kolay bir mesajlaşma servisi için Amazon SQS'a bir göz atın.
mellowsoon,

Yük dengesi sorunları ile ilgili olarak. Bir iradenin olduğu yerde, bir yol var! Stackoverflow.com isteğinde bulunmak yerine, IP adresini kullanarak bir sunucuya rastgele basabilirsiniz. Yük dengeleyici çerezleri boru isteklerine göre kontrol ederse, çerezleri sahte yapabilirsiniz. IP adresini kontrol ederse, muhtemelen (sunucudan gelen yanıtı umursamadığınızdan) bile sahte olabilirsiniz.
mellowsoon,

Yük dengelemenin bunu yapmamak için bir sebep olmaması gerektiğine karar verdi. İsteği specially_crafted_urlbilinen bir IP'den geldiğinden, yük dengeleyicinize yalnızca o IP'den gelen istekler için round-robin yapmak için bir kural ekleyebilirsiniz.
Portman

2

Sanırım saf hizmet anlayışıyla birlikte, hizmete dağılmış ve çekirdek uygulamadan uzakta kodunuz olduğunu düşünüyorum.

İşte kodunuzu bir arada tutan ve hizmeti basitleştiren, zamana duyarlı olmayan büyük arkaplan işleriyle yaptığımız şey:

  1. Bir iş kuyruğu oluşturun (iş içi türleri için bellekte veya DB'de ne olursa olsun gerekli olan)
  2. Sıraya alınan işleri yürütecek bir web servisi oluşturun
  3. Web servisini belirli bir aralıkta çağıran ölü basit servis uygulaması, tüm karmaşık işleri (iş alımı ve yürütme) ana kod tabanınızda web servisine bırakın.

Daha da basit, aramayı yalnızca bir konsol uygulamasında yapın ve bir "hizmete" dönüştürmek için Görev Zamanlayıcı'yı veya VisualCron'u kullanın.


1
İşte tam da bunu iş yerindeki önemli bir uygulamada gördüm - aralıklarla web uygulamasını tetikleyen bir Windows Hizmeti. Web uygulaması durumsuz kalır ve gerektiğinde veritabanından durumu çeker. Bir tedavi çalışır.
Bevan,

1

TopShelf'i beğendim. Sadeliği koruyor, ancak yine de bir Windows Hizmeti olarak çalışmanın doğru yolunu yapıyor. Temel olarak bir Konsol Uygulaması oluşturun, yaklaşık 15-20 kod satırı ekleyin, ardından bir hizmet olarak yüklenir.

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


1

Web sunucusunda çalışan ve periyodik olarak çeşitli görevlerinizi yerine getiren bir bakım URL'sine basan çok basit bir Windows hizmetine ne dersiniz? Herhangi bir talepte ne kadar iş yaptığını kısırlaştırın.


1

Burada göze çarpan eğilimi yakalayacağım ve IIS içi model için de devam edeceğim. Kendim kullandım ve gerçekten iyi çalışıyor. İyi bir iş parçacığı havuzu sınıfı uygulamak gerçekten zor değil (yıllar geçtikçe, iş parçacığı havuzu sınıfımı dinamik olarak oluşturma ve yok etmeyi, işleri yeniden denemeyi ve benzeri şeyleri desteklemek için genişlettim). Avantajlar:

  • İzlenecek harici servis yok
  • Uygulama kolaylığı: Çapraz süreç marşalizasyonu yok, gelişmiş iş takibi yok
  • Hala IIS işleminizin içindesiniz, bu nedenle her zamanki günlük işlemlerinizi ve benzeri işlemleri yapabilirsiniz (birden fazla günlük dosyasına gerek yoktur)
  • Oldukça basitleştirilmiş dağıtım (bir servisi güncellediğinizde, servisi durdurmanız, dosyaları kopyalamanız, servisi başlatmanız gerekir - bu, web sitesi kodundaki genel güncellemelerinizin yanı sıra)

Bence, bir IIS içi çözüm, çalışmayı rasgele sayfa görünümlerine sokmaktan sadece "bir sonraki adımdır".


1

Resque çok hoş. Veya tamamlandıktan sonra elde edilen değerden haberdar edilmeniz gerekiyorsa Kthxbye bile .

Her iki Redis / Ruby tabanlı tho.

Dürüst olmak gerekirse, hizmete dayalı bir yaklaşım uyguluyorsanız, bunun bir artı olduğunu düşündüğüm mevcut platformunuzla gerçekten entegre olması gerekmez. İnşallah, bir tür unutma ve çalıştırma sistemi (bir tür izlemeyle) ve işleri tamamlardı. Veritabanının güncellenmesi / güncellenmesinden bu yana aynı platformda çalıştırılması gerektiğinden emin değilim.

Bu işin ayrı bir varlık olarak yapılmasını sağladığınızdan çok daha az parayla daha fazlasını alabileceğinize emin olabilirsiniz, özellikle de iş parçacığı sorunlarıyla ilgileniyorsunuz gibi görünüyor. Hem Resque hem de Kthxbye , işletim sisteminin eşzamanlılığı işlemesini sağlamak için işlemleri ayrı işlemlere taşır.

resque

kthxbye


Ben sadece Kthxbye'yi denemeliyim, eğer sadece büyük ismi yüzünden!
Nathan Palmer

hemen hemen harika. sonraki ORLY olacak? kütüphane. Muhtemelen bir çeşit istatistikleri izlemek için ...;)
Lukas

0

Bir MSMQ Kuyruğu dinleyen bir WAS barındırılan WCF servisi kullanırdım.

Pro'nun

  • Web uygulamasından gelen tek yönlü mesajları ateşleyin ve unutun

  • MSMQ / WCF azaltma ve yeniden deneme

  • Garantili teslimat; D

  • Ölü Mektup yönetimi

  • Dağıtılmış işlem

  • WAS / MSMQ aktivasyonu

Eksileri

  • MSMQ (ölmedi ... Henüz)

WCF'deki MSMQ özellikleri MSMQ'yu kullanmayı gerçekten çok güzel kılıyor. Evet, konfigürasyonda kan kaybedeceksiniz, ancak faydalar fedakarlığa ağır basacak


0

Web uygulamaları geliştirirken bunu birkaç kez denedim. Görevi gerçekleştiren bir Windows konsol uygulaması oluşturarak ve bu görevi gerçekten yapmak için her zaman çalışan bir zamanlanmış görev oluşturarak çözüyoruz.


0

Çalışmaları, Rx ve aşağıdakine benzer bir şey kullanarak bir arka plan iş parçacığına (ya da birçok arka plan iş parçacığına) ekleyebilirsiniz.

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

Kullanmak:

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

Sadece bir tanesine sahip olan bir sınıf içinde her şeyi barındırın (yani, bir singleton, ancak doğru yapın - yaşam tarzınızı belirlemek için sizi IoC konteynerini kullanın).

Iş parçacığı havuzu vb boyutunu (tek bir iş parçacığı çalıştıran) EventLoopScheduler yerine bir özel zamanlayıcı yazarak denetleyebilirsiniz.


0

Bu tür bir şeyi birkaç kez uyguladım. Pencerelerde, çeşitli zamanlarda bir şeyler yapan bir python komut satırı programı kurdum. Bu program aynı zamanda bir bağlantı noktasında bir xmlrpc arabirimini gösterir. Sonra zamanlanmış bir görev işi her dakika çalışır ve xmlrpc arabirimlerini sorgular. Eğer hazır değillerse, onları fırlatmaya çalışır. Olmazsa, bana e-posta gönderir.

Avantaj, çalışan işin cron veya zamanlamaya bağlı olmamasıdır. Her saniye çalışan bir işlem işim var, ancak yeni bir işe başlamak arasında yapacak işi olup olmadığına bağlı olarak daha uzun süre bekleyecek. Ayrıca, sonucu temel alarak akıllıca hareket etmek için kullanılabilir. 500 hatası mı var? Gerçekten uzun bir gecikme var mı? Başka bir şey yap. Başka bir servisi bilgilendirin. Vb.

Aynı sistem unix üzerinde küçük değişikliklerle çalışır.


0

Sana kendim bir cevabım yok, ama sorun bir zil çaldı - Bir zamanlar bir podcast üzerinde tartışan bazı rastgele adamları hatırlıyorum .

Spolsky: Blogda sorduğunuz sorulardan birinin genel olarak bakımda tekrar eden görevleri nasıl yerine getirmeniz gerektiği olduğunu fark ettim.

Atwood: Evet.

Spolsky: Bu adil bir karakterizasyon mu? Her web sitesinin, bir web sayfasının yüklendiği sırada yürütmek istemediğiniz bazı görevleri vardır, ancak bir tür yinelenme ile çalıştırmak istiyorsunuz.

Atwood: Ya, arkaplan işleri bir nevi şey.

Spolsky: Ya, peki sen ne anladın?

Atwood: Aslında Twitter'dan sordum çünkü hafif bir şey istiyorum. Gerçekten bir windows servisi yazmak istemedim. Bunun grup kodunun dışında olduğunu hissettim. Ayrıca, işi gerçekten yapan kod aslında bir web sayfasıdır, çünkü benim için bir web sitesindeki mantıksal bir çalışma birimi bir web sayfasıdır. Bu yüzden aslında web sitesine geri dönüyoruz, tıpkı web sitesindeki başka bir istek gibi, bu yüzden satır içi kalması gereken bir şey olarak gördüm ve geldiğim küçük bir yaklaşımı Twitter'da önerdim Temelde sabit bir son kullanma tarihi olan uygulama önbelleğine bir şey eklemek oldu, o zaman bir geri arama yaptığınız için, bu sürenin bitiminde işi yapan belirli bir işlevi çağırdıktan sonra tekrar aynı son kullanma tarihine sahip önbelleğe ekleyin.


1
Evet, bu StackOverflow'un olduğundan daha küçük siteler için işe yarar. Ölçek maalesef burada büyük bir sorundur (neyse, nasıl baktığınıza bağlı olarak).
Kevin Montrose

@Kevin Montrose, burada tam bir alan bilgisizliği rica ediyorum. Lütfen gizli bir web sayfasının neden işi (belki küçük birimlerde) gerçekleştirdiğini ve başka bir yerde canlandırılabilir bir sayfa / cron işi tarafından ölçeklendirilemediğini açıklayabilir misiniz? Haklı olduğundan şüphem yok ama öğrenmeyi çok isterim.
Tuhaf,

Özel öneri (önbellek sona ermesi), tüm önbellek sona erme süresi (ASP.NET'te) tek bir iş parçacığı çalıştırdığından (bu, daha önce kullanılan SO gibi daha küçük siteler için akıllıca bir hack) ölçeklenmez. Bir cron görevi ölçeklenmiyor, çünkü tek bir sunucuyu geride bıraktık (SO şu anda 3 ve hala büyüyor) ve herhangi bir cron görevi tek bir sunucuya çarpıyor olacak (en azından, bu değişmezi değiştirmek yükümüzle gerçekten acı verici olacaktı. bakiye ayarı). Bir cron görevi de sık sık çalışmak zorunda kalacaktı, çünkü bu görevler dakikalarca tekrarlanıyordu.
Kevin Montrose

Daha az sıklıkta, sabit aralık, zaten görevler, rozet bağışları ve günlük e-posta bildirimleri gibi şeyler için "cron tarzı" zamanlamayı kullandığımızı belirtmekte fayda var.
Kevin Montrose

0

Görev Sırası Java API'sine Genel Bakış

Görev Kavramları
App Engine arka plan işlemesinde, görev küçük bir çalışma biriminin tam bir açıklamasıdır. Bu açıklama iki bölümden oluşmaktadır:

  • Görevi parametreleyen bir veri yükü.
  • Görevi uygulayan kod.

Çevrimdışı Web Hooks Olarak Görevleri
Neyse ki, Internet zaten bir HTTP isteği ve yanıtı şeklinde böyle bir çözüm sağlar. Veri yükü, web form değişkenleri, XML, JSON veya kodlanmış ikili veri gibi HTTP isteğinin içeriğidir. Kod referansı URL'nin kendisidir; Asıl kod, sunucunun cevabı hazırlarken yürüttüğü mantıktır.


GAE görev sırası api'sini kullanmanızı önermiyorum, ancak modellerini takip ediyorum. Bir süredir bunu düşündüler ve bunun bir uygulamasını yazdılar.
antony.trupe

0

İkisinide yap

Kullanıcı isteklerinde şu anda piggyback olan işi yapan soru yoluna isteğe bağlı bir parametre ekleyin:

Arka planda görevlerin büyük bir sitede yapılması

Her sunucuda çalışan ve IIS günlüğü paylaşılan ikili dosyasını açan ve dosyanın geçerli sonuna kadar okuyan bir konsol uygulaması oluşturun. IIS günlüğü temizlerken güncellemeleri toplamak için ileri okumak için bir dosya sistemi denetleyicisi veya zamanlanmış bir aralık kullanın.

Hangi sayfaların görüntülendiğini belirlemek için bu bilgileri kullanın.

Bir webclient nesnesi ile localhost'taki url'nin "extrastuff" versiyonunu çağırmak için ayrıştırılmış logdaki sayfa url'lerini kullanın.

Her günlük döneminin sonunda dosyaları değiştirmek için bazı kodlar ekleyin veya her günlük dönemindeki işlemi yeniden başlatın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.