给Asp.Net Core写一个结束进程的中间件
起因
在Asp.Net Core中,更新dll无法像原先在Asp.Net中直接覆盖dll的方法,更新项目.这里是通过在中间件中,监视dll变化.简单粗暴的结束dotnet进程来实现.至于为什么使用结束进程的来实现.是因为还没发现更好的方法. 其实用中间件实现非常不好,只是学习使用中间件.在正常项目中一般会通过IIS/Jexus将请求转发到Kestrel(Asp.Net Core宿主),这样即使Asp.Net Core项目在使用过程出现进程崩溃.也可以在很短的时间内由IIS/Jexus重新拉起.达到守护进程的效果. 下面要实现的中间件结束进程,在由IIS/Jexus拉起,实现覆盖dll时,更新项目的效果.
实现中间件有两种方法:
1. 通过中间件构造函数获取RequestDelegate 类型参数, 实现Invoke函数,参数为HttpContext类型,返回Task
2. 中间件实现IMiddleware接口,实现InvokeAsync函数,参数为HttpContext和RequestDelegate
第一种代码实现
public static class UpdateFileMiddlewareExtensions
{
/// <summary>
/// 监视dll文件变化的时候,结束当前进程
/// </summary>
/// <param name="builder"></param>
/// <returns></returns>
public static IApplicationBuilder UseUpdateFile(this IApplicationBuilder builder)
{
return builder.UseMiddleware<UpdateFileMiddleware>();
}
}
public class UpdateFileMiddleware
{
private readonly RequestDelegate _next;
/// <summary>
/// 监测文件变化
/// </summary>
private static FileSystemWatcher fileSystemWatcher = null;
public UpdateFileMiddleware(RequestDelegate next)
{
_next = next;
}
public Task Invoke(HttpContext context)
{
string dir = Directory.GetCurrentDirectory(); //获取项目所在的根目录
if (fileSystemWatcher == null)
{
fileSystemWatcher = new FileSystemWatcher(dir, "*.dll");
fileSystemWatcher.Changed += FileSystemWatcher_Changed;
fileSystemWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size;
fileSystemWatcher.EnableRaisingEvents = true;
fileSystemWatcher.IncludeSubdirectories = true;
}
return this._next(context);
}
private void FileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
{
fileSystemWatcher.EnableRaisingEvents = false;
if (e.ChangeType == WatcherChangeTypes.Changed)
{
Process.GetCurrentProcess().Kill(); //结束当前进程
}
fileSystemWatcher.EnableRaisingEvents = true;
}
}
使用
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseUpdateFile(); //使用该中间件
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
}
第二种 代码实现
public class CustomMiddleware : IMiddleware
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
//请求处理
//.....
await next(context);
}
}
public static class CustomMiddlewareExtensions
{
/// <summary>
/// UseCustomMiddleware 实现xxxx功能
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
public static IApplicationBuilder UseCustomMiddleware(this IApplicationBuilder app)
{
return app.UseMiddleware<CustomMiddleware>();
}
}
在Configure方法中,调用UseCustomMiddleware
秋风
2019-04-27