# 介绍

相对 0.x 版本,对代码进行了重构。插件化设计:将各功能点拆分成了插件,同时支持自定义插件,满足不同业务团队(当然也适合大规模团队定制化开发)。同时还增加更多CI工具完善了测试用例

# 它是如何工作的

  1. 每个请求会根据请求 url 获取到请求对应的路由配置,如无法匹配则创建默认路由。路由配置包括插件配置、参数配置,请求协议等
     -- gateway/app/core/ctx.lua
    
     -- 从上下文中获取dispatcher
     function _M.get_dispatcher()
         local ngx_ctx = ngx.ctx
         local ctx_dispatcher = ngx_ctx.dispatcher
         if not ctx_dispatcher then
             local route = route_store.get_route_by_uri(ngx.var.uri)
             if not route then
                 route = {
                     prefix = ngx.var.uri,
                     status = 1,
                     service_name = "default",
                     protocol = "http",
                     plugins = {
                         "default"
                     }
                 }
             end
    
             local dispatcher_plugins = {}
             for _, plugin_name in pairs(route.plugins) do
                 dispatcher_plugins[plugin_name] = plugins[plugin_name]
             end
             ctx_dispatcher = dispatcher:new(dispatcher_plugins, route)
             ngx_ctx.dispatcher = ctx_dispatcher
         end
         return ctx_dispatcher
     end
    
  2. 根据路由配置创建 dispatcher 实例,同时会放到 ngx.ctx 上下文中
  3. dispatcher 实例在每个 ngx 执行阶段中都会执行回应钩子函数
     -- gateway/app/init.lua
    
     function _M.http_init()
         -- 加载配置文件
         local config_file = os.getenv("config.file") or "conf/app.json"
         config:init(config_file)
    
         require("app.core.ctx").init()
     end
    
     function _M.http_init_worker()
         local ctx = require("app.core.ctx")
         local worker_id = ngx.worker.id()
         log.info("init worker: ", worker_id)
    
         ctx.init_worker()
     end
    
     function _M.http_rewrite()
         local dispatcher = require("app.core.ctx").get_dispatcher()
         dispatcher:do_in_rewrite()
     end
    
     function _M.http_access()
         local dispatcher = require("app.core.ctx").get_dispatcher()
         dispatcher:do_in_access()
     end
    
     function _M.http_content()
         local dispatcher = require("app.core.ctx").get_dispatcher()
         dispatcher:do_in_content()
     end
    
     function _M.http_balancer()
         local dispatcher = require("app.core.ctx").get_dispatcher()
         dispatcher:do_in_balancer()
     end
    
     function _M.http_header_filter()
         local dispatcher = require("app.core.ctx").get_dispatcher()
         dispatcher:do_in_header_filter()
     end
    
     function _M.http_body_filter()
         local dispatcher = require("app.core.ctx").get_dispatcher()
         dispatcher:do_in_body_filter()
     end
    
     function _M.http_log()
         local dispatcher = require("app.core.ctx").get_dispatcher()
         dispatcher:do_in_log()
     end
    
  4. dispatcher 各阶段的钩子函数会执行对应插件的钩子函数
  5. 整个请求的处理逻辑,完全由每个插件各阶段的执行逻辑决定

参考:https://moonbingbing.gitbooks.io/openresty-best-practices/content/ngx_lua/phase.html

# 路由

路由是整个网关流量分发的基础,网关会根据路由匹配获取路由配置,通过配置将插件加载到请求上下文中,并在每个阶段执行对应插件处理逻辑。

+--------+     +---------+     +------------+      
| 请求URL |+--->| 匹配路由 |+--->| 执行插件逻辑 |
+--------+     +---------+     +------------+      

路由匹配完全由lua-resty-radixtree实现,具体匹配规则参考:https://github.com/api7/lua-resty-radixtree

# 插件

  • discovery 插件:根据请求url路由到上游服务节点,支持 http 和 grpc 协议
  • rewrite 插件:重写请求url,将网关 url 转换成实际上游服务 url
  • tracing 插件:为每个请求生成 trace-id,通过 header 传递,同时会输出到accesslog,方便做链路跟踪

# FAQ