Zamanlanmış görevleri çalıştırmanın en iyi yolu [kapalı]


229

Bugün ASP.NET web sitemiz için zamanlanmış görevleri çalıştırmak için bir konsol uygulaması oluşturduk. Ancak bu yaklaşımın biraz hataya yatkın olduğunu ve sürdürülmesinin zor olduğunu düşünüyorum. Zamanlanmış görevinizi nasıl yürütürsünüz (bir windows / IIS / ASP.NET ortamında)

Güncelleme:

Görev örnekleri:

  • Veritabanındaki bir e-posta kuyruğundan e-posta gönderme
  • Eski nesneleri veritabanından kaldırma
  • İstatistikleri Google AdWords'ten almak ve veritabanındaki bir tabloyu doldurmak.

Yürüttüğünüz görevlere örnek nedir?
JeffO


Plesk'iniz varsa, bir vbs yazıp Görev Zamanlayıcı'ya reklam verebilirsiniz: net24.co.nz/kb/article/AA-00213/13/Shared-Hosting/ASP-ASP.NET/…
HasanG

Yanıtlar:


74

Bir web sitesi için tüm görevlerim (planlanması gereken) web sitesinde tutulur ve özel bir sayfadan çağrılır. Daha sonra bu sayfayı sık sık çağıran basit bir Windows hizmeti yazdım. Sayfa çalıştıktan sonra bir değer döndürür. Yapacak daha çok iş olduğunu bilirsem, sayfayı tekrar çalıştırırım, aksi takdirde kısa bir süre sonra çalıştırırım. Bu benim için gerçekten iyi çalıştı ve tüm görev mantığımı web kodu ile birlikte saklıyor. Basit Windows hizmetini yazmadan önce, sayfayı her x dakikada bir aramak için Windows zamanlayıcısını kullandım.

Bunu çalıştırmanın bir başka uygun yolu da Pingdom gibi bir izleme hizmetini kullanmaktır . Http denetimlerini hizmet kodunuzu çalıştıran sayfaya yönlendirin. Daha sonra bir şey doğru olmadığında uyarı mesajları göndermek için Pingdom'u tetiklemek için kullanılabilecek sayfa döndürme sonuçlarına sahip olun.


3
Sonunda bulduğum çözüm bu. Özel bir web servisi yerine windows scheduler + curl kullanıyorum. Windows hizmeti kullanmanın faydası nedir?
Niels Bosma

16
Önbellek Öğesinin sona erme tekniğine baktınız mı? Bence planlanmış bir hizmetin çok daha ideal bir uygulaması olduğunu göreceksiniz
Richard Clayton

10
Kötü amaçlı bir kullanıcının (veya bir arama motoru örümceğinin) bu sayfayı çağırmasını ve böylece zamanlanan görevlerinizin çalışmasına neden olmasını ne engeller?
UpTheCreek

8
Web uygulamasında statik bir zaman damgası depolayarak ve yalnızca zaman damgası ayarlanmadıysa (ilk arama) veya son aramadan bu yana doğru süre geçtiyse çalışarak kötü amaçlı aramaları durdurabilirsiniz.
Rob Kent

5
IP adresimin dahili bir adres olup olmadığını kontrol ederek url'ime kötü amaçlı çağrıları durduruyorum. Kuruluşumuzun içinde değilse hiçbir şey döndürmez ve hiçbir şey yapmaz.
user1408767

128

Stackoverflow için Jeff Atwood'un bu tekniği karşılaştığım en basit yöntem. ASP.NET'in önbellek sistemine yapılan "önbellek kaldırıldı" geri çağrı mekanizmasına dayanır

Güncelleme: Stackoverflow bu yöntemi aştı. Sadece web sitesi çalışırken çalışır, ancak birçok kişi için yararlı olan çok basit bir tekniktir.

Ayrıca Quartz.NET'e de göz atın


12
Uygulama çalışmıyorsa, ancak zamanlanan görevin gerçekleşmesi gerekiyorsa ne olur?
MichaelGG

2
Bu, görevin bu zamanı çalıştırmak için biraz zaman alması durumunda kullanıcı deneyimini yavaşlatabilir. Kullanıcının bakımlarımı / görevlerimi benim için yaratmamasını tercih ederim.
Brettski

5
Bu cehennem kadar korkutucu! Her şey uygulamanın çalışmasının durmasına neden olabilir ve muhtemelen yalnızca bir sonraki kullanıcı isteğinde yeniden başlatılır. O zamanlar arasında görevleriniz çalışmaz!
teedyay

43
Bugün orijinal blog No, we’ve switched to a dedicated task. We definitely outgrew this technique. I do think it’s fine for small sites though!
yazısına

3
-1 Bu yaklaşımla büyük bir kusur var. Uygulama geri dönüştürüldüğünde 'CacheItemRemoved' olayı başlar ve zamanlanan göreviniz çalışır. Üretim sahalarında bu günde birkaç kez olabilir. Görevin haftalık olarak çalışmasını istiyorsanız o kadar iyi değil.
Steven de Salas

30

Bir oluşturun özel bir Windows Servisi .

Zamanlanmış konsol uygulamaları olarak ayarlanmış bazı kritik görevlerim vardı ve bunların bakımını zor buldum. Her iki dakikada bir DB'mde bir programı kontrol eden bir 'kalp atışı' ile bir Windows Hizmeti oluşturdum. Gerçekten iyi çalıştı.

Bunu söyledikten sonra, kritik olmayan bakım görevlerimin çoğu için hala planlanmış konsol uygulamaları kullanıyorum. Eğer kırılmazsa, tamir etmeyin.


7
Bağlantı şimdi öldü.
Charles Burns

1
@CharlesBurns, her zaman archive.org ile ölü bağlantılara göz atabilirsiniz: web.archive.org/web/20090919131944/http://www.dotheweb.net/…
Nikolay Kostov

17

Bunu ilgili herkes için kolay buldum:

  • DoSuchAndSuchProcess gibi bir web hizmeti yöntemi oluşturun
  • Bu web yöntemini çağıran bir konsol uygulaması oluşturun.
  • Konsol uygulamasını görev zamanlayıcıda zamanlayın.

Bu metodolojiyi kullanarak tüm iş mantığı web uygulamanızda bulunur, ancak Windows görev yöneticisinin veya başka bir ticari görev yöneticisinin güvenilirliğini sağlayın ve yürütme raporu gibi iade bilgilerini kaydedin. Bir web hizmetinden geri dönüş verisi almak daha kolay olduğundan, bir sayfaya göndermek yerine bir web hizmeti kullanmak bir avantaj sağlar.


10

Neden tekerleği yeniden icat ediyorsanız, Diş Açma ve Zamanlayıcı sınıfını kullanın.

    protected void Application_Start()
    {
        Thread thread = new Thread(new ThreadStart(ThreadFunc));
        thread.IsBackground = true;
        thread.Name = "ThreadFunc";
        thread.Start();
    }

    protected void ThreadFunc()
    {
        System.Timers.Timer t = new System.Timers.Timer();
        t.Elapsed += new System.Timers.ElapsedEventHandler(TimerWorker);
        t.Interval = 10000;
        t.Enabled = true;
        t.AutoReset = true;
        t.Start();
    }

    protected void TimerWorker(object sender, System.Timers.ElapsedEventArgs e)
    {
        //work args
    }

7
Bir zamanlayıcı başlatmak için bir iş parçacığı oluşturmanıza gerek yok ...
Zyo

4
Ben de bunun ideal bir çözüm olduğunu düşünmüyorum.
Idan Shechter

12
@IdanShechter, bunun neden ideal bir çözüm olmadığını düşündüğünüzü açıklamak iyi olur
Omu

2
İş parçacığı sorunlu olabilir, çünkü HttpRequest olmadığından, HttpRequest'i içeren bazı veriler boş olabilir. Örneğin, HttpRequest .ApplicationPath. Görev düzgün bir şekilde yazılırsa çalışır. Başka bir sorun, uygulama havuzunun yeniden başlatılmasıdır. Havuz çok sık yeniden başlatılıyorsa (bellek sızıyor ...), işçi asla çalışmaz.
Tomas Kubes

2
Çalışan birden fazla örneğiniz varsa (örneğin yük dengeleme) - muhtemelen bu çözümü istemezsiniz (aynı işi yapan birkaç görev)
Illidan

8

Bir web sayfasını çalıştırmak için Windows Zamanlayıcı'yı kullanın.

Kötü niyetli kullanıcının veya arama motoru örümceklerinin çalışmasını önlemek için, zamanlanmış görevi ayarladığınızda, web sayfasını bir sorgu dizesiyle arayın, yani: mypage.aspx? From = schedtask

Ardından sayfa yüklemesinde bir koşul kullanın: if (Request.Querystring ["from"] == "zamanlanan görev") {// executetask}

Bu şekilde hiçbir arama motoru örümceği veya kötü amaçlı kullanıcı zamanlanmış görevinizi yürütemez.


5
Daha da iyisi, aslında sorgu dizesini sihirli bir ifadeden biraz daha fazla güvenlikle doğrulayan tuzlanmış bir karma algoritması kullanın. Req mypage.aspx? Salt = foo & hash = 1223523jbhdgu13t1 gibi bir şey olurdu. Hem sunucuda hem de istemcide aynı karma algoritmaya sahip olmanız gerekir. Ayrıca sunucuya sabit bir sınır ekleyin; yürütüldüğünde kaydedin ve çok hızlı yürütülmesini önleyin. Yine de paranoyak olabilirim.
Nenotlep

14
Daha da güvenli, isteğin sunucunun kendisinden gelip gelmediğini kontrol eden bir web sayfası çalıştırmak için Windows Zamanlayıcı'yı kullanın: Request.IsLocal>> yalnızca sunucunun kendisi zamanlanmış görevleri çalıştırabilir, başka hiç kimse.
Komplo

Yaklaşımınızdan daha fazla deneyiminiz mi var? Uygulamamızın benzer bir hizmet türünü geliştirecektim ve şimdi zamanlanmış görev veya cron içeren bir sayfayı çağırmanın daha iyi olup olmadığına veya önbellek sisteminin kullanılıp kullanılmayacağına karar veremiyorum.
JayDee


3

Ayrıca, uygulamanız SQL SERVER kullanıyorsa, görevlerinizi zamanlamak için SQL Agent'ı kullanabilirsiniz. Bu, genellikle veri odaklı (e-posta hatırlatıcıları, planlanmış bakım, temizleme, vb.) Yeniden oluşan kodu koyduğumuz yerdir. SQL Agent ile yerleşik olan harika bir özellik, kritik bir görev başarısız olursa sizi uyaran hata bildirim seçenekleridir.


2

Ne tür zamanlanmış görevler demek istediğinizden emin değilim. "Her saat, foo.xml dosyasını yenileyin" türü görevler gibi şeyleri kastediyorsanız, Windows Zamanlanmış Görevler sistemini kullanın. ("At" komutu veya denetleyici üzerinden.) Bir konsol uygulaması çalıştırmasını veya işlemi başlatan özel bir sayfa istemesini sağlayın.

Düzenleme: Eklemeliyim, bu, IIS uygulamanızı zamanlanmış noktalarda da çalıştırmanın iyi bir yoludur. DB'nizi her 30 dakikada bir kontrol etmek ve kullanıcılara bazı veriler hakkında e-posta hatırlatmaları yapmak istediğinizi varsayalım, bu sayfayı istemek ve böylece IIS işlemlerini almak için zamanlanmış görevleri kullanabilirsiniz.

İhtiyaçlarınız daha karmaşıksa, bir Windows Hizmeti oluşturmayı ve ihtiyacınız olan işlemleri yapmak için bir döngü çalıştırmasını düşünebilirsiniz. Bu aynı zamanda ölçeklendirme veya yönetim amacıyla kodu ayırma avantajına da sahiptir. Olumsuz tarafı, Windows hizmetleriyle uğraşmanız gerekir.


2

Sunucunuz varsa, windows görev zamanlayıcısını kullanmalısınız. AT /? komut satırından seçenekleri görebilirsiniz.

Aksi takdirde, web tabanlı bir ortamda, belirli bir sayfaya belirli bir süre için istekte bulunmak için farklı bir makine kurmak gibi kötü bir şey yapmanız gerekebilir.


2

Abidar'ı bir ASP.NET projesinde başarıyla kullandım (işte bazı arka plan bilgileri ).

Bu yöntemle ilgili tek sorun, ASP.NET web uygulaması bellekten kaldırılırsa (yani düşük kullanım nedeniyle) görevlerin çalışmamasıdır. Denediğim bir şey, her 5 dakikada bir web uygulamasını vurmak, hayatta tutmak için bir görev oluşturmaktır, ancak bu güvenilir bir şekilde çalışmadı, bu yüzden şimdi bunun yerine Windows zamanlayıcı ve temel konsol uygulamasını kullanıyorum.

İdeal çözüm bir Windows hizmeti oluşturmaktır, ancak bu mümkün olmayabilir (yani paylaşılan bir barındırma ortamı kullanıyorsanız). Ayrıca, işleri web uygulamasında tutmak için bakım açısından işleri biraz daha kolaylaştırır.


1

İşte başka bir yol:

1) DUE veya gecikmiş olarak başlatılması gerekiyorsa görevleri başlatmaktan sorumlu bir "kalp atışı" web komut dosyası oluşturun.

2) Web komut dosyasına çarpan ve düzenli aralıklarla çalışmaya zorlayan bir yerde (tercihen aynı web sunucusunda) zamanlanmış bir işlem oluşturun. (örn. Windows, IE veya whathaveyou kullanarak ısı atışı komut dosyasını sessizce başlatan görevi zamanlar)

Görev kodunun bir web betiği içinde yer alması, yalnızca kodu web uygulaması kod tabanı içinde tutmak içindir (varsayım, her ikisinin de birbirine bağlı olduğu varsayımıdır), bu da web geliştiricilerinin yönetmesi daha kolay olacaktır .

Alternatif yaklaşım, tüm zamanlamanın kendisini çalıştırabilen ve yürütülebilir dosyayı zamanlanmış görev olarak çalıştıran yürütülebilir bir sunucu komut dosyası / programı oluşturmaktır. Bu, web uygulaması ile zamanlanan görev arasında temel ayrıştırmaya izin verebilir. Bu nedenle, web uygulaması / veritabanı kapalı veya erişilemese bile, zamanlanmış görevlerinizin çalıştırılması gerekiyorsa, bu yaklaşımla devam etmelisiniz.


1
@Matias, Neden sadece planlanan süreç gerçek işi yapmıyor?
LukeH

1

'ThreadPool.RegisterWaitForSingleObject' yöntemini kullanarak kodu aralıklarla çalıştıran bir Windows Hizmeti kolayca oluşturabilirsiniz. Gerçekten kaygan ve kurulumu oldukça kolaydır. Bu yöntem, Çerçeve'deki Zamanlayıcılardan herhangi birini kullanmaktan daha akıcı bir yaklaşımdır.

Daha fazla bilgi için aşağıdaki bağlantıya göz atın:

Windows Hizmetini Kullanarak .NET'te Periyodik İşlem Çalıştırma:
http://allen-conway-dotnet.blogspot.com/2009/12/running-periodic-process-in-net-using.html


0

Konsol uygulamalarını da kullanıyoruz. Log4net gibi günlük araçları kullanıyorsanız, bunların yürütülmesini düzgün bir şekilde izleyebilirsiniz. Ayrıca, düzgün tasarlanmışsa, ikisi arasında aynı kod kitaplıklarından bazılarını paylaşabileceğiniz göz önüne alındığında, bir web sayfasından daha zor nasıl korunacağından emin değilim.

Bu görevlerin zamana göre yürütülmesine karşıysanız, web sitenizin yönetim bölümünde bir kuyruk görevi gören bir web sayfanız olabilir. Kullanıcı görevi çalıştırmak için bir istekte bulunur, bu da MyProcessQueue tablosuna boş bir tarih damgası kaydı ekler ve zamanlanmış göreviniz MyProcessQueue'da yeni bir kayıt olup olmadığını her X dakikada bir kontrol eder. Bu şekilde, yalnızca müşteri çalışmasını istediğinde çalışır.

Umarım bu öneriler yardımcı olur.


0

Seçeneklerden biri, bir Windows hizmeti ayarlamak ve bunu zamanlanan görevinizi çağırmaktır.

Ben kullandım Winforms zamanlayıcılar koymak bu ASP.NET iyi çalışır sanmıyorum


-1

.NET için Yeni Görev Zamanlayıcı Sınıf Kitaplığı

Not: Bu kitaplık oluşturulduğundan beri Microsoft, Windows Vista için yeni bir görev zamanlayıcı (Görev Zamanlayıcı 2.0) başlattı. Bu kitaplık, Vista'da hala kullanılabilen ve Windows XP, Windows Server 2003 ve Windows 2000 ile uyumlu olan Görev Zamanlayıcı 1.0 arabirimi için bir sarıcıdır.

http://www.codeproject.com/KB/cs/tsnewlib.aspx


Lütfen sil. Aşağıda cevaplanmıştır. Kopyala
Fandango68
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.