服务框架之接口路由(路由接口 子接口)

小编:魅力 更新时间:2022-04-21

前言

无论是web server框架还是rpc框架,接口作为服务的对外入口,其背后可能包含复杂的后端流程,不限于业务逻辑处理、数据处理&操作、基础能力调用等。所以接口和“后端流程”之间必然存在着映射交付关系。

原理

路由机制
以下均以web框架为例,rpc框架相比web更为直接,即指定方法调用

http api 请求 和 rpc调用本质上都是通过网络完成通信双方交互。我们不局限在业内常见的平台化、微服务化中对两者的应用,其实可以这样泛化理解所有“交互”有如下要素:

  • 协议

通信双方约定好的通信规则。
统一的通信规则能够保证通信的准确性,避免二义性;
根据交互场景和限制条件选择合适的协议,例如app中前后端交互常用http/https,IoT场景中就可能使用MQTT/CoAP,可以提高通信效率,减低通信成本;

  • 通信内容

通信的任务就是传递信息,无非就是数据,结构化数据、非结构化数据都有相应的表示形式,辅之以众多协议,能够有效地被组织起来进行传输。例如,最常见的http请求get参数、json格式参数、rpc protobuf等

  • 通信目标

数据送达至何处。
这也是接口概念的关键,在计算机网络中能够定位到网络中确定主机和进程,如何将网络请求交付处理呢?那么接口就是网络请求对号入座的入口,常见框架中路由匹配规则也都大同小异。

路由注册

路由注册实现接口到控制器的映射,以此为基础完成后续处理流程
同时还可以注册中间件,构建请求处理过程的执行链路
路由注册方式多种,原理上归纳为以下几种:

基于配置(静态)

  • 解析配置文件

// For example, PHP framework register controller with Array class ActionControllerConfig extends ActionBaseConfig { public static ControllerConfig => array ( array( 'action_id' => 'action_name' // action唯一标识,后续用作router map key 'pattern' => '/^\/rest\/2\.0\/module\/operation/?params'// 框架规则不尽相同,本例为正则表达式 + 请求参数组合匹配 'path' => 'controller class path' 'controller_class' => 'controller1.class.php' ), ... ) }

  • 手动注册路由

// 代码来源 https://github.com/go-chi/chi r.Route("/parent/pattern", func(r Router) { r.Use(middleware2.SetContextUser) // 设置中间件 r.Mount("/xxx1", NewXxx1Router()) r.Mount("/xxx2", NewXxx2Router(boot)) r.Mount("/xxx3", NewXxx3Router(boot)) r.Mount("/xxx4", NewXxx4Router(boot)) r.Mount("/xxx5", NewXxx5Router(boot)) })

基于反射、注解、动态代理(动态)

  • 再次理解“反射”:
    golang / java 此类编译型语言,编译结束后具体实现均已存在,但是程序如何得知呢?利用反射能够在运行时获得具体Type&Value
  • 工作过程:
    新建路由实例
    coding阶段配置handler到Router
    服务启动时初始化注册,反射获取Router.Type&Router.Value(方式多样,不限于此)
    整理得到“路由器”持有的“路由表”,路由表本质是url <—> 处理函数地址的映射表
  • 常见框架路由注册case:SpringMVC 注解Go Web 框架

路由匹配规则

精确匹配

模式匹配

参数辅助匹配


路由维护

最终路由注册产出结果主要如下两种形式(求见多识广的小伙伴补充~)

路由表

路由树

常用最左前缀匹配