美文网首页.NET
方法即服务 — 2. 解耦服务器宿主

方法即服务 — 2. 解耦服务器宿主

作者: 冰麟轻武 | 来源:发表于2017-04-12 01:28 被阅读45次

    传送门

    方法即服务 — 1. 思考

    既然希望业务代码在不同的服务器宿主环境下执行,那么就需要抽象不同服务器宿主之间的行为差异,解耦服务器宿主与业务代码之间的关系

    概要设计

    无论是任何服务器宿主host)与客户端client)的交互都摆脱不了

    Request → Process → Response

    的套路,区别在于不同的 Host 产生的 Request 不同,需要返回的 Response 也不一样;

    至于Process,在.NET中无非就是

    Instance + Properties + Arguments + Method + Result

    例如:

    var method = FindMethod();
    var instance = CreateInstance(method.ReflectedType);
    var props = GetProperties();
    instance.SetProps(props);
    var arguments = GetArguments();
    var result = method.invoke(instance,arguments);
    

    所以我需要一个对象用于获得 Process 五件套参数,我决定抽象一个 IRequest 对象,IRequest对象就包含了刚才例子中的 FindMethod,GetProperties,GetArguments几个方法;
    这样我就可以简单的实现一个通用的 Process 方法了

    public object Process(IRequest request)
    {
        var request = GetRequest();
        var method = request.FindMethod();
        var instance = Activator.CreateInstance(method.ReflectedType);
        var props = request.GetProperties();
        foreach(var prop in props)
        {
            method.ReflectedType.GetProperty(prop.Name).SetValue(instance, prop.Value);
        }
        var arguments = request.GetArguments();
        var result = method.invoke(instance, arguments);
        return result;
    }
    

    好吧,我知道这代码看起来容错性非常差,但不必在意,就当这只是在画草图。

    有了这样一个通用的 Process 方法,那么只需要在不同的服务器宿主环境下构建一个 IRequest 就可以了,把这个工作交给适配器Adapter)去做,所以这个流程看上去就这样的:

    WebRequest → WebAdapter → IRequest → Process → Result → WebAdapter → WebResponse

    或是

    RpcRequest → RpcAdapter → IRequest → Process → Result → RpcAdapter → RpcResponse

    服务器宿主接收到请求之后,通过特定 Adapter 将原本的 Request 转为刚刚自定义的 IRequest 对象,然后通过 Process 方法执行请求,得到返回值之后再次经过 Adapter 的处理,将 object Result 转为指定类型的 Response 返回给客户端;

    在MVC下代码大致就是这样的:

    internal class MisRouteHandler : IHttpHandler, IRouteHandler
    {
        private MvcAdapter _adapter;
    
        public MisRouteHandler(string urlTemplate)
        {
            _adapter = new MvcAdapter(urlTemplate);
        }
    
        public bool IsReusable => true;
    
        public void ProcessRequest(HttpContext httpContext)
        {
            try
            {
                var request = _adapter.CreateRequest(httpContext);
                var result = Mis.Process(request);
                var response = _adapter.ConvertToResponse(result);
                httpContext.Response.StatusCode = response.StatusCode;
                httpContext.Response.ContentType = response.ContentType;
                foreach (var header in response.headers)
                {
                    httpContext.Response.Headers.Set(header.name, header.value);
                }
                if (response.content != null)
                {
                    httpContext.Response.BinaryWrite(response.content);
                }
            }
            catch (Exception e)
            {
                httpContext.Response.ContentType = "text/plain;charset=utf-8";
                httpContext.Response.StatusCode = 500;
                httpContext.Response.BinaryWrite(Encoding.UTF8.GetBytes(e.ToString()));
            }
        }
    
        IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext) => this;
    }
    

    流程图

    未完待续……

    相关文章

      网友评论

      • 夫礼者:从这张流程图里我看到了tomcat的影子。突然感觉对tomcat的理解更深了一些。👍

      本文标题:方法即服务 — 2. 解耦服务器宿主

      本文链接:https://www.haomeiwen.com/subject/cddpattx.html