當前項目中有這樣一個需求:由前端用戶的一個操作,需要觸發到不同設備的消息推送。由於推送這個具體功能,我們采用了第三方的服務。而這個服務調用有時候可能會有延時,為此,我們希望將消息推送與用戶前端操作實現異步執行,就是希望在後台自動執行,不阻塞前端用戶的操作,而且最好能實現失敗重試等功能。
經過一些研究比較,我們發現使用Hangfire這個組件可以較好地實現這個需求。為了給大家做一個演示,我這裡簡化了代碼,做一個范例程序。
我在這裡不准備詳細介紹Hangfire的基本用法,有興趣的同學們可以參考官方網站 http://hangfire.io/ 和文檔 http://docs.hangfire.io/en/latest/
打開Nuget Package Manager Console
首先安裝Hangfire組件(Core,MemoryStorage),注意,因為後者是依賴前者的,所以我們只需要運行下面的命令即可
Storage就是存儲的意思,Hangfire的後台任務是需要一個地方保存起來,它默認支持SQL Server Storage和MemoryStorage。采用MemoryStorage無疑是最簡單的(不需要有任何外部的依賴)。當然,最大的問題就是,因為是放在內存中的,萬一網站出現問題重啟,那麼沒有執行完的任務是會消失的。
如果要使用SQL Server的話,可以參考 http://docs.hangfire.io/en/latest/configuration/using-sql-server.html ,甚至還可以結合MSMQ來提高可用性 http://docs.hangfire.io/en/latest/configuration/using-sql-server-with-msmq.html
接下來為當前項目啟用Owin的支持。關於什麼是OWin,我這裡也不准備多做說明,有興趣的同學可以參考 : http://www.cnblogs.com/dudu/p/what-is-owin.html 和 http://owin.org/ 還有 http://www.asp.net/aspnet/overview/owin-and-katana/an-overview-of-project-katana
修改Startup.cs為下面這樣的代碼
using Hangfire; using Hangfire.MemoryStorage; using Microsoft.Owin; using Owin; [assembly: OwinStartup(typeof(WebApplicationWebApiHangfireSample.Startup))] namespace WebApplicationWebApiHangfireSample { /// <summary> /// 演示Hangfire的配置 /// 作者:陳希章 /// </summary> public class Startup { public void Configuration(IAppBuilder app) { // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888 //指定Hangfire使用內存存儲後台任務信息 GlobalConfiguration.Configuration.UseMemoryStorage(); //啟用HangfireServer這個中間件(它會自動釋放) app.UseHangfireServer(); //啟用Hangfire的儀表盤(可以看到任務的狀態,進度等信息) app.UseHangfireDashboard(); } } }
using Hangfire; using System; using System.Diagnostics; using System.Web.Http; namespace WebApplicationWebApiHangfireSample.Controllers { /// <summary> /// 用來公開給前端用戶調用的API /// 作者:陳希章 /// </summary> public class MessageController : ApiController { /// <summary> /// 這個是用來發送消息的靜態方法 /// </summary> /// <param name="message"></param> public static void Send(string message) { EventLog.WriteEntry("EventSystem", string.Format("這是由Hangfire後台任務發送的消息:{0},時間為:{1}", message, DateTime.Now)); } public IHttpActionResult Post(string content) { //這裡可以做一些業務判斷或操作 //然後需要推送的時候,調用下面的方法即可 BackgroundJob.Enqueue(() => Send(content)); //最後返回(這裡是立即返回,不會阻塞) return Ok(); } } }
我使用Fiddler來模擬客戶端調用
我們可以很容易地發起大量的請求,例如下面這樣
很快就在Dashboard中看到任務狀態(有1000個任務)
但是很快(不到1秒鐘的時間),這些任務就全部處理完了
我們可以在Windows事件日志中看到消息
以上就是我的簡單演示例子。當然,如果還想要實現失敗重試,或者更加有意思的一些功能(例如定時發送),可以繼續參考官方文檔。
這個范例代碼可以通過這裡下載 http://files.cnblogs.com/files/chenxizhang/WebApplicationWebApiHangfireSample.zip