Owin 是什么东东,这里不做累述,有兴趣的可以去这里了解。
最近有需求,有一个比较复杂的运算处理,如果放到IIS,可能会对IIS上其他的应用有影响,因此不能放到现有的IIS。另外,这个需求比较独立,可能随着运算流量的加大,随时需要移植扩展,但是这个运算可以是无界面的。
之前有对OWIN有点了解,基于以上需求特性,于是最终方式是基于.net core + owin 开发一个独立运行的控制台程序,作为自宿主来运行自己的webapi应用,未来如果只是在win server系列的服务器中转移扩展,基本将一个独立运行目录直接拿走,在任何服务上就可以独立运行,不需要任何的IIS服务配置步骤(管理的web应用多了,每个应用独立的iis配置好费时间)。如果需要移动到非win server的服务器,也可以发布成对应的控制台程序然后在控制台启动(没实测,vs code的命令行里调试过)。
好了,接下来步骤:
1.添加引用:
Owin
Microsoft.Owin 既然是基于OWIN的应用,这个包是必须的,可以通过Nuget安装(过程略…)
Microsoft.Owin.Cors 开发的是WebApi,涉及到跨域问题,就引入了这个,这个不是必须的;
System.Web.Http.SelfHost 自宿主必须的
System.Web.Http.Owin 上一个的依赖
Microsoft.Owin.Hosting 服务的一些主要接口和方法在这里
Microsoft.Owin.Host.HttpListener 这里提供是http监听的东东,例如监听某个端口和主机名,需要这个~
Newtonsoft.Json
2.Owin的主要入口定义和接口实现:
根据默认名定义一个Startup类,我们基本这一个应用就跑这一个玩意基本默认就够了。这里是可以自己改名字和自定义的。可以参考其他资料
public class Startup
{
public void Configuration(IAppBuilder app)
{
//创建一个HTTP的实例配置
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
//映射路由
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}"
//defaults: new { action = "get" }
);
config.Formatters.Remove(config.Formatters.XmlFormatter);
config.Formatters.Add(config.Formatters.JsonFormatter);
// 对 JSON 数据使用混合大小写。
//config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
//使用跟属性名相同的大小写输出
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new DefaultContractResolver();
//启用跨域支持
app.UseCors(CorsOptions.AllowAll);
//这里是用的System.Web.Http.Owin里面提供处理方法,也可以自己实现
app.UseWebApi(config);
//这里是可以根据规则实现自己的响应处理方法
//app.Map("/api/*", map =>
//{
// map.UseCors(CorsOptions.AllowAll);
// map.UseWebApi(config);
//});
}
}
一个支持简单应用的启动类如上就可以了(开始我也写的很复杂,实际跑的时候,如果没有其他要求,就是如此简单)
如上,app.Map里面定义的是可以按照一定的规则来对请求做不同的响应处理,
比如,如果在webapi里面除了webapi,还有几个需要访问的静态html,也可以在这里定义规则,如果遇到访问静态html的资源,就直接做返回
3.命令行启动类和对应方法:
class Program
{
static void Main(string[] args)
{
Start:
Console.WriteLine("请输入服务主机,如:localhost:8080");
string host = Console.ReadLine();
string url = String.Format("http://{0}/", host);
try
{
using (WebApp.Start<Startup>(url))
{
Console.WriteLine("服务已经启动,服务地址:" + url);
Console.ReadLine();
}
}
catch (Exception e)
{
Console.WriteLine(e.Message + "\r\n" + e.Source);
//goto Start;
}
}
}
这里是启动命令行程序,大家应该都熟悉,这里我简单做了一下输入配置方便win下的直接启动,在win下,可以直接双击启动,然后敲入形如:localhost:8080 的启动参数。
程序就会监听指定的主机名和端口,如果不指定端口,默认会监听80端口,访问方式这里就不重复了。
4.接下来就是webapi的Controller开发
这接下来的开发,就不在写了,跟之前做webapi没什么区别,只是这里,我做了一个基类,用于收集客户端的请求记录,并输出到控制台,自己的api都继承这个基类。
public class BaseController: ApiController
{
protected override void Initialize(HttpControllerContext controllerContext)
{
string url = controllerContext.Request.RequestUri.AbsoluteUri;
string time = DateTime.Now.ToString();
System.Console.WriteLine("[{0}] {1}:{2}",time, controllerContext.Request.Method.ToString(), url);
base.Initialize(controllerContext);
}
}
留意这一行 ,这根在IIS跑的webapi比,有点特殊,控制台自宿主,可以用这个方法在任何时候,向控制台输出内容,后面的实际应用,为了调试方便,请求过程中的Tack、Debug信息等,都根需要都打印到控制台了,异常信息也是打印出来了,特别是调试webapi,看着控制台输出运行js真的方便。
System.Console.WriteLine("[{0}] {1}:{2}",time, controllerContext.Request.Method.ToString(), url);
最后运行效果如下,这个东东在实际生产环境也跑了几天了,基本还算稳定,处理复杂的图片运算,基本不会崩溃,之前放在IIS里面,实在麻烦,图形运算要用到好多图形库,部署配置都麻烦,还影响IIS的其他的应用
。