Cách tốt nhất để chạy các tác vụ theo lịch trình [đóng]


229

Hôm nay chúng tôi đã xây dựng một ứng dụng giao diện điều khiển để chạy các tác vụ theo lịch trình cho trang web ASP.NET của chúng tôi. Nhưng tôi nghĩ cách tiếp cận này hơi dễ bị lỗi và khó bảo trì. Làm thế nào để bạn thực hiện tác vụ theo lịch trình của mình (trong môi trường windows / IIS / ASP.NET)

Cập nhật:

Ví dụ về các nhiệm vụ:

  • Gửi email từ hàng đợi email trong cơ sở dữ liệu
  • Loại bỏ các đối tượng lỗi thời khỏi cơ sở dữ liệu
  • Lấy số liệu thống kê từ Google AdWords và điền vào bảng trong cơ sở dữ liệu.

Ví dụ về các nhiệm vụ bạn đang chạy là gì?
JeffO

4
Bạn cần kiểm tra atrigger.com
Kousha

Nếu bạn có Plesk, bạn có thể viết một vbs và quảng cáo nó lên Trình lập lịch tác vụ: net24.co.nz/kb/article/AA-00213/13/Shared-hosting/ASP-ASP.NET/
HasanG

Câu trả lời:


74

Tất cả các nhiệm vụ của tôi (cần được lên lịch) cho một trang web được giữ trong trang web và được gọi từ một trang đặc biệt. Sau đó tôi đã viết một dịch vụ Windows đơn giản gọi trang này thường xuyên. Khi trang chạy nó sẽ trả về một giá trị. Nếu tôi biết còn nhiều việc phải làm, tôi sẽ chạy lại trang, ngay lập tức, nếu không tôi sẽ chạy nó trong chốc lát. Điều này đã làm việc rất tốt cho tôi và giữ tất cả logic nhiệm vụ của tôi với mã web. Trước khi viết dịch vụ Windows đơn giản, tôi đã sử dụng bộ lập lịch Windows để gọi trang mỗi x phút.

Một cách thuận tiện khác để chạy này là sử dụng dịch vụ giám sát như Pingdom . Trỏ kiểm tra http của họ đến trang chạy mã dịch vụ của bạn. Có trang trả về kết quả mà sau đó có thể được sử dụng để kích hoạt Pingdom để gửi tin nhắn cảnh báo khi có gì đó không đúng.


3
Đây là giải pháp tôi đã kết thúc. Thay vì một dịch vụ web tùy chỉnh, tôi sử dụng windows calendaruler + curl. Lợi ích của việc sử dụng dịch vụ windows là gì.
Niels Bosma

16
Bạn đã xem kỹ thuật hết hạn Cache Item chưa? Tôi nghĩ bạn sẽ thấy rằng đó là một triển khai lý tưởng hơn nhiều của một dịch vụ theo lịch trình: codeproject.com/KB/aspnet/ASPNETService.aspx
Richard Clayton

10
Điều gì để ngăn người dùng độc hại (hoặc nhện công cụ tìm kiếm) gọi trang này và do đó khiến các tác vụ theo lịch trình của bạn chạy?
UpTheCux

8
Bạn có thể dừng các cuộc gọi độc hại bằng cách lưu trữ dấu thời gian tĩnh trong ứng dụng web và chỉ chạy nếu dấu thời gian chưa được đặt (cuộc gọi đầu tiên) hoặc thời gian chính xác đã hết hạn kể từ cuộc gọi cuối cùng.
Rob Kent

5
Tôi dừng các cuộc gọi độc hại đến url của mình bằng cách kiểm tra xem địa chỉ IP có phải là địa chỉ nội bộ hay không. Nó không trả về gì và không làm gì nếu nó không nằm trong tổ chức của chúng tôi.
dùng1408767

128

Kỹ thuật này của Jeff Atwood cho Stackoverflow là phương pháp đơn giản nhất mà tôi đã gặp. Nó dựa vào cơ chế gọi lại "đã xóa bộ nhớ cache" vào hệ thống bộ đệm của ASP.NET

Cập nhật: Stackoverflow đã vượt xa phương thức này. Nó chỉ hoạt động trong khi trang web đang chạy nhưng đó là một kỹ thuật rất đơn giản, hữu ích cho nhiều người.

Ngoài ra hãy kiểm tra Quartz.NET


12
Vậy chuyện gì sẽ xảy ra nếu ứng dụng không chạy, nhưng tác vụ theo lịch trình cần phải xảy ra?
MichaelGG

2
Điều này cũng có thể làm chậm trải nghiệm người dùng nếu tác vụ xảy ra mất một thời gian để chạy lần này. Tôi không muốn người dùng sinh ra bảo trì / nhiệm vụ cho tôi.
Brettski

5
Điều này thật đáng sợ như địa ngục! Bất cứ điều gì cũng có thể khiến ứng dụng ngừng chạy và có lẽ nó chỉ khởi động lại theo yêu cầu người dùng tiếp theo. Trong khoảng thời gian đó, nhiệm vụ của bạn không chạy!
teedyay

43
Một cái gì đó tôi nhận thấy ngày hôm nay trong các bình luận cho bài viết trên blog ban đầu: No, we’ve switched to a dedicated task. We definitely outgrew this technique. I do think it’s fine for small sites though!- Jeff Atwood
Joel Coehoorn

3
-1 Có một lỗ hổng lớn với phương pháp này. Bất cứ khi nào ứng dụng được tái chế, sự kiện 'CacheItemRemond' sẽ kích hoạt và tác vụ theo lịch trình của bạn sẽ chạy. Trên các trang web sản xuất điều này có thể xảy ra một vài lần một ngày. Không tốt lắm nếu bạn muốn nhiệm vụ chạy hàng tuần.
Steven de Salas

30

Tạo một dịch vụ Windows tùy chỉnh .

Tôi đã có một số nhiệm vụ quan trọng được thiết lập như các ứng dụng bảng điều khiển theo lịch trình và thấy chúng khó bảo trì. Tôi đã tạo một Dịch vụ Windows với "nhịp tim" sẽ kiểm tra lịch biểu trong DB của tôi cứ sau vài phút. Nó hoạt động rất tốt.

Có nói rằng, tôi vẫn sử dụng các ứng dụng bảng điều khiển theo lịch trình cho hầu hết các nhiệm vụ bảo trì không quan trọng của mình. Nếu nó không bị hỏng, đừng sửa nó.


7
FYI liên kết bây giờ đã chết.
Charles Burns

1
@CharlesBurns, bạn luôn có thể duyệt các liên kết chết với archive.org: web.archive.org/web/20090919131944/http://www.dotheweb.net/
Nikolay Kostov

17

Tôi thấy điều này dễ dàng cho tất cả những người liên quan:

  • Tạo một phương thức dịch vụ web như DoSuchAndSuchProcess
  • Tạo một ứng dụng giao diện điều khiển gọi webmethod này.
  • Lịch trình ứng dụng giao diện điều khiển trong lịch trình tác vụ.

Sử dụng phương pháp này, tất cả logic nghiệp vụ được chứa trong ứng dụng web của bạn, nhưng bạn có độ tin cậy của trình quản lý tác vụ windows hoặc bất kỳ trình quản lý tác vụ thương mại nào khác để khởi động và ghi lại bất kỳ thông tin trả về nào như báo cáo thực hiện. Sử dụng dịch vụ web thay vì đăng lên trang có một chút lợi thế vì việc lấy dữ liệu trả về từ dịch vụ web sẽ dễ dàng hơn.


10

Tại sao phải phát minh lại bánh xe, sử dụng lớp Threading và Timer.

    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
Bạn không cần phải tạo ra một chuỗi để bắt đầu hẹn giờ ...
Zyo

4
Tôi cũng không nghĩ rằng đó là một giải pháp lý tưởng.
Shechter Idan

12
@IdanShechter sẽ tốt hơn nếu nói lý do tại sao bạn coi đây không phải là một giải pháp lý tưởng
Omu

2
Chủ đề có thể có vấn đề, bởi vì nó không phải là httpRequest, một số dữ liệu liên quan đến HttpRequest có thể là null. Ví dụ: httpRequest .ApplicationPath. Nếu tác vụ được viết đúng, nó sẽ hoạt động. Một vấn đề khác là khởi động lại nhóm ứng dụng. Nếu hồ bơi khởi động lại quá thường xuyên (rò rỉ bộ nhớ ...), công nhân sẽ không bao giờ chạy.
Tomas Kubes

2
Trong trường hợp bạn có một vài trường hợp đang chạy (ví dụ: cân bằng tải) - có thể bạn sẽ không muốn giải pháp này (một số tác vụ làm tương tự)
Illidan

8

Sử dụng Bộ lập lịch Windows để chạy một trang web.

Để ngăn người dùng xấu hoặc trình tìm kiếm công cụ tìm kiếm chạy nó, khi bạn thiết lập tác vụ theo lịch trình, chỉ cần gọi trang web bằng chuỗi truy vấn, ví dụ: mypage.aspx? From = lên lịch

Sau đó, trong tải trang, chỉ cần sử dụng một điều kiện: if (Request.Query chuỗi ["từ"] == "lên lịch") {// execetask}

Bằng cách này, không có công cụ tìm kiếm nhện hoặc người dùng độc hại nào có thể thực hiện tác vụ theo lịch trình của bạn.


5
Tốt hơn hết, hãy sử dụng thuật toán băm muối thực sự xác minh chuỗi truy vấn có bảo mật hơn một chút so với cụm từ ma thuật. Req sẽ giống như mypage.aspx? Salt = foo & hash = 1223523jbhdgu13t1. Bạn chỉ cần có cùng một thuật toán băm trên cả máy chủ và máy khách. Cũng thêm một giới hạn cứng trên máy chủ; lưu lại khi nó được thực thi và ngăn không cho thực thi quá nhanh. Tôi có thể bị hoang tưởng mặc dù.
Nenotlep

14
Thậm chí an toàn hơn, hãy sử dụng Bộ lập lịch Windows để chạy một trang web kiểm tra xem yêu cầu có đến từ chính máy chủ không: Request.IsLocal>> chỉ bản thân máy chủ mới có thể chạy các tác vụ theo lịch trình, không ai khác.
Âm mưu

Bạn có nhiều kinh nghiệm từ cách tiếp cận của bạn? Tôi sẽ phát triển loại dịch vụ tương tự của ứng dụng của chúng tôi và bây giờ tôi không thể quyết định liệu có nên gọi một trang với tác vụ hoặc cron theo lịch trình hay không, hoặc sử dụng hệ thống bộ đệm.
JayDee


3

Ngoài ra, nếu ứng dụng của bạn sử dụng SQL SERVER, bạn có thể sử dụng Tác nhân SQL để lên lịch cho các tác vụ của mình. Đây là nơi chúng ta thường đặt mã xuất hiện lại được điều khiển dữ liệu (nhắc nhở email, bảo trì theo lịch trình, thanh trừng, v.v ...). Một tính năng tuyệt vời được tích hợp với Tác nhân SQL là các tùy chọn thông báo lỗi, có thể cảnh báo bạn nếu một tác vụ quan trọng thất bại.


2

Tôi không chắc loại nhiệm vụ theo lịch trình của bạn là gì. Nếu bạn có nghĩa là những thứ như các tác vụ loại "mỗi giờ, hãy làm mới foo.xml", thì hãy sử dụng hệ thống Nhiệm vụ theo lịch trình của Windows. (Lệnh "at" hoặc thông qua bộ điều khiển.) Yêu cầu chạy ứng dụng bảng điều khiển hoặc yêu cầu một trang đặc biệt khởi động quy trình.

Chỉnh sửa: Tôi nên thêm, đây là một cách OK để ứng dụng IIS của bạn chạy tại các điểm đã lên lịch. Vì vậy, giả sử bạn muốn kiểm tra DB của mình sau mỗi 30 phút và gửi email nhắc nhở cho người dùng về một số dữ liệu, bạn có thể sử dụng các tác vụ theo lịch trình để yêu cầu trang này và từ đó nhận được xử lý IIS.

Nếu nhu cầu của bạn phức tạp hơn, bạn có thể xem xét việc tạo một Dịch vụ Windows và để nó chạy một vòng lặp để thực hiện bất kỳ xử lý nào bạn cần. Điều này cũng có lợi ích của việc tách mã cho các mục đích mở rộng hoặc quản lý. Về nhược điểm, bạn cần phải đối phó với các dịch vụ Windows.


2

Nếu bạn sở hữu máy chủ, bạn nên sử dụng bộ lập lịch tác vụ của windows. Sử dụng AT /? từ dòng lệnh để xem các tùy chọn.

Mặt khác, từ một môi trường dựa trên web, bạn có thể phải làm một cái gì đó khó chịu như thiết lập một máy khác để thực hiện các yêu cầu đến một trang nhất định trong một khoảng thời gian.


2

Tôi đã sử dụng Abidar thành công trong một dự án ASP.NET (đây là một số thông tin cơ bản ).

Vấn đề duy nhất với phương pháp này là các tác vụ sẽ không chạy nếu ứng dụng web ASP.NET không được tải khỏi bộ nhớ (nghĩa là do sử dụng thấp). Một điều tôi đã cố gắng là tạo ra một nhiệm vụ để tấn công ứng dụng web cứ sau 5 phút, giữ cho nó tồn tại, nhưng điều này dường như không hoạt động đáng tin cậy, vì vậy bây giờ tôi đang sử dụng trình lập lịch Windows và ứng dụng bảng điều khiển cơ bản để thực hiện việc này thay thế.

Giải pháp lý tưởng là tạo một dịch vụ Windows, mặc dù điều này có thể không thực hiện được (ví dụ: nếu bạn đang sử dụng môi trường lưu trữ được chia sẻ). Nó cũng làm cho mọi thứ dễ dàng hơn một chút từ góc độ bảo trì để giữ mọi thứ trong ứng dụng web.


1

Đây là một cách khác:

1) Tạo tập lệnh web "heartbeat" chịu trách nhiệm khởi chạy các tác vụ nếu chúng bị DUE hoặc quá hạn để khởi chạy.

2) Tạo một quy trình được lên lịch ở đâu đó (tốt nhất là trên cùng một máy chủ web) truy cập vào webscript và buộc nó chạy ở một khoảng thời gian thông thường. (vd

Việc mã tác vụ được chứa trong tập lệnh web hoàn toàn là vì mục đích giữ mã trong cơ sở mã ứng dụng web (giả định là cả hai đều phụ thuộc vào nhau), điều này sẽ giúp các nhà phát triển web dễ quản lý hơn .

Cách tiếp cận thay thế là tạo ra một kịch bản / chương trình máy chủ thực thi, thực hiện tất cả lịch biểu hoạt động và tự chạy thực thi như một tác vụ theo lịch trình. Điều này có thể cho phép tách rời cơ bản giữa ứng dụng web và tác vụ theo lịch trình. Do đó, nếu bạn cần các tác vụ theo lịch trình của mình để chạy ngay cả khi ứng dụng / cơ sở dữ liệu web có thể bị hỏng hoặc không thể truy cập, bạn nên thực hiện theo phương pháp này.


1
@Matias, Tại sao không chỉ có quá trình theo lịch trình làm công việc thực sự thay thế?
LukeH

1

Bạn có thể dễ dàng tạo một Dịch vụ Windows chạy mã theo chu kỳ bằng phương thức 'ThreadPool.RegisterWaitForSingleObject'. Nó thực sự trơn tru và khá dễ dàng để thiết lập. Phương pháp này là một cách tiếp cận hợp lý hơn sau đó để sử dụng bất kỳ Timers nào trong Khung.

Hãy nhìn vào liên kết dưới đây để biết thêm thông tin:

Chạy một quy trình định kỳ trong .NET bằng dịch vụ Windows: http://allen-conway-dotnet.blogspot.com/2009/12/rucky- periodic- process-in-net-
US.html


0

Chúng tôi cũng sử dụng các ứng dụng giao diện điều khiển. Nếu bạn sử dụng các công cụ ghi nhật ký như Log4net, bạn có thể theo dõi chính xác việc thực hiện của chúng. Ngoài ra, tôi không chắc làm thế nào chúng khó bảo trì hơn một trang web, do bạn có thể đang chia sẻ một số thư viện mã giống nhau giữa hai trang nếu nó được thiết kế đúng.

Nếu bạn chống lại việc các tác vụ đó chạy trên cơ sở thời gian, bạn có thể có một trang web trong phần quản trị của trang web hoạt động như một hàng đợi. Người dùng đưa ra yêu cầu để chạy tác vụ, đến lượt nó sẽ chèn một bản ghi dữ liệu trống trên bảng MyProcessQueue và tác vụ theo lịch trình của bạn sẽ kiểm tra mỗi X phút cho một bản ghi mới trong MyProcessQueue. Bằng cách đó, nó chỉ chạy khi khách hàng muốn nó chạy.

Mong những gợi ý đó giúp.


0

Một tùy chọn sẽ là thiết lập một dịch vụ windows và nhận điều đó để gọi tác vụ theo lịch trình của bạn.

Trong winforms tôi đã sử dụng Timers không nghĩ rằng nó sẽ hoạt động tốt trong ASP.NET


-1

Một thư viện lớp lập lịch tác vụ mới cho .NET

Lưu ý: Vì thư viện này đã được tạo, Microsoft đã giới thiệu một trình lập lịch tác vụ mới (Trình lập lịch tác vụ 2.0) cho Windows Vista. Thư viện này là một trình bao bọc cho giao diện Trình lập lịch tác vụ 1.0, vẫn có sẵn trong Vista và tương thích với Windows XP, Windows Server 2003 và Windows 2000.

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


Hãy xóa. Nó đã được trả lời dưới đây. Bản sao
Fandango68
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.