為何要用中間件來實現音頻處理的監聽服務 當然也可以使用Startup來進行服務的自啟動,或者也可以使用quartz定時調度任務來啟動音頻服務,大家隨意。 筆者認為使用中間件的目的,是為了分離應用和服務,也是一種解耦手段。 我們知道,在NETCORE中的中間件,有點類似像AOP的一種實現形式,他的調用 ...
為何要用中間件來實現音頻處理的監聽服務
當然也可以使用Startup來進行服務的自啟動,或者也可以使用quartz定時調度任務來啟動音頻服務,大家隨意。
筆者認為使用中間件的目的,是為了分離應用和服務,也是一種解耦手段。
我們知道,在NETCORE中的中間件,有點類似像AOP的一種實現形式,他的調用方式是通過Request=>Middleware=>next=>custom logic=>Response。我們可以用來做日誌記錄、許可權驗證、事物處理,多個中間件形成一個處理管道,甚至可以實現自定義的MVC和依賴註入。
創建一個中間件
為了便於區分,我們擴展一個名為“MediaHandlers”的IApplicationBuilder
1 public static class MediaHandlers 2 { 3 public static IApplicationBuilder UseMediaAudioHandlerMiddleware(this IApplicationBuilder builder, 4 MediaAudioOptions options) 5 { 6 if (builder == null) 7 throw new ArgumentNullException(nameof(builder)); 8 9 return builder.UseMiddleware<MediaAudioMiddleware>(options); 10 } 11 }
再創建一個名為“MediaAudioMiddleware”的中間件,其實就是一個實現類,但需要傳遞對象RequestDelegate做請求代理。
並且,我們將在中間件中實現依賴註入,而中間件的依賴註入卻無法通過構造函數的方式進行註入,需要通過Invoke來實現依賴註入,完整代碼如下:
1 public async Task Invoke(HttpContext context, 2 IDataOpService iDataOpService, 3 ICacheAsyncService iCacheAsyncService, 4 IMsgBusService imsgBusService, 5 IHostingEnvironment iHostingEnvironment) 6 { 7 _dataOpService = iDataOpService; 8 _iMsgBusService = imsgBusService; 9 _iCacheAsyncService = iCacheAsyncService; 10 _ihostingEnvironment = iHostingEnvironment; 11 12 await _next(context); 13 }
跟之前的控制器註入的內容類型是一樣的。然後我們再來看看構造函數中需要實現的一些事情:
public MediaAudioMiddleware(RequestDelegate next, MediaAudioOptions options) { _next = next; Task.Factory.StartNew(() => { Thread.Sleep(3 * 1000); //...需要自定義啟動的方法 }); }
構造函數中預設必須傳遞RequestDelegate類型參數,用於委托執行Request之後Response之前的代理。
將需要啟動的服務已子任務(子線程)的方式交給Task工廠進行自行管理,再次分離了主管道請求應用。
但是,預設這個中間件是不會自動啟動的。。。因為沒有建立一個請求管道。
強制建立一個請求管道
筆者的思路是,通過httpclient請求主管道中的一個任意的API介面(比如你自定義實現的伺服器信息介面),從而強制實現該請求管道的所有事情,比如迴圈,比如監聽等等。參考如下:
1 using (var httpClient = new HttpClient()) 2 { 3 httpClient.BaseAddress = new Uri($"{General.LocalHostUrl}/Info"); 4 var r = httpClient.GetAsync(httpClient.BaseAddress).Result; 5 if (!r.ToString().Contains("200")) return; 6 Console.WriteLine("MediaAudioMiddleware Running"); 7 var mediaHandler = new AudioHandlerWorkUnit(iDataOpService: _dataOpService, 8 iCacheAsyncService: _iCacheAsyncService, 9 imsgBusService: _iMsgBusService, 10 iHostingEnvironment: _ihostingEnvironment, 11 millsSeconds: options.MillsSeconds 12 ); 13 mediaHandler.DoStart(); 14 }
當然,需要在命令參數中(或前置參數中約束該管道只建立一次),也許筆者的實現方式欠妥,如果你有更好的方法,歡迎交流。
感謝閱讀