@自嗨的江江

爱生活爱叽歪

基于OWIN开发自宿主,命令行独立运行的WebApi服务端

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的其他的应用

不允许评论