• 微信公众号:美女很有趣。 工作之余,放松一下,关注即送10G+美女照片!

网关现有架构及优化

互联网 diligentman 2周前 (02-21) 11次浏览

网关技术实现如图:
网关现有架构及优化

网关初始化时,从redis获取配置,包括路由信息,机构的密钥(用于业务数据加解密),平台对机构的公私钥(用于签名验签),机构可访问api的权限,机构黑白名单。并将这些配置信息保存至内存。这些信息在管理端配置。
通过redis对配置变动进行监听,如果有变动则更新内存或重建路由
路由信息包括后端对接方式,后端地址,按照api名称和版本进行断言
与后端对接方式目前有三种:

  • http:常规的gateway转发功能
  • lb:gatewa转发到注册至eureka的服务,应用场景为适配器,如果网关输出的参数格式和后端需要的不相符,需要裁剪参数
  • mq:异步调用

http的支持:

  • 添加path断言,暴露同一对外入口
  • 添加apiName和apiVersion断言,找到需要转发的后台路由,进入对应过滤器
  • 重写path,改为自定义的后台服务地址。如果通过一系列过滤器,则转发至相应服务

lb的支持:

  • 添加path断言,暴露同一对外入口
  • 添加apiName和apiVersion断言,找到需要转发的后台路由,进入对应过滤器
  • 后台地址命名规则为/service-name/url,解析后台地址,设置route的uri为service-name即注册至eureka的服务名称,rewritepath为url,即实际调用的后台地址。
  • addRequestHeader添加请求头,设置密码,标记为gateway转发来的请求。Lb的后台服务对header进行校验。

mq的支持:

  • 添加path断言,暴露同一对外入口
  • 添加apiName和apiVersion断言,找到需要转发的后台路由,进入对应过滤器
  • 配置后端scheme为mq
  • 定义全局过滤器:如果scheme为mq,则为mq类的路由。

    • 新建uuid,将(uuid, rsp)放入map中,然后将包含uuid的请求发送至mq。网关收到mq响应时,同样会得到uuid,再从map中获取rsp进行响应。
    • 将(uuid, rsp)放入map的同时,也会将(uuid,curenttime)放入exceedMap中,网关会定时检查mq类的交易是否超时。(exceedMap改造为linkedHashMap)
    • mqfilter的isAlready。。由于是全局路由,处理mq/http协议的最后的filter;对于http,避免走了nettyroute又走forward

技术演进:

  • 最开始只有互联网网关,对接的是外部机构,需要对参数进行加解密,签名验签。后续有了新的需求:
  • 开发内部网关:公司内部的系统做为调用方,走的内网不需要加密,只进行md5验证即可。互联网网关和内部网关有共用的filter,也有各自独有的filter。与后端的对接方式也有所不同,内部网关没有lb的对接形式。

    • 提取公共filter,定义个性filter,可自由组合filter和predicate进而构建网关
  • 按需配置:有时需要在内网环境部署网关进行功能测试,只需要配置一条http路由即可,没必要部署redis和mq,因此配置信息应支持从配置文件中读取,并且不去监听配置的变动。路由信息的读取也应按对接方式分为http,lb和mq类,根据网关需要按需配置。

    • 路由配置化移除对redis的依赖
    • 网关功能按需组合
  • 全局与局部filter:原架构filter均为全局filter,由map决定交易是否走这个路由。现改为局部路由,创建路由addCommonFilter的时候添加。(未实现,因为需要改路由模型,比较麻烦)

对于同一类网关,断言方式和公共过滤器是相同的,而不同的对接形式有各自的filter。为了实现filter的复用及灵活配置,定义了GatewayRouteDynamicService类,其中RouteUpdate方法创建一类路由的流程模板:

  1. 从数据源获取路由信息apiPlan
  2. 添加网关公共断言(实现addCommonPredicate接口)
  3. 添加公共过滤器(实现addCommonFilter)
  4. 添加特定断言/过滤器(实现addSpecificDynamicRoute)
  5. 发布路由

扩展性的实现:

  • 不同的网关实现各自的addCommonPredicate,addCommonFilter接口,可添加该类网关的共有断言及接口。
  • 如果token校验,加解密有不同的实现方式,重写filter添加到CommonFIlter里即可
  • 不同的路由类型实现addSpecificDynamicRoute接口,如http,mq,lb
  • 数据源可选redis和配置文件
  • 可选是否监听数据源的变动,如果监听,需要使用redis
  • 后续数据源和监听支持选择zk等中间件
  • 目前断言为apiName+version对应一条路由。也支持根据传入的机构号,银行号进行路由,继承predicateFactory类,实现addCommonPredicate即可。

gateway几大功能模块:

  • 加载并初始化路由:

    • 主要是按与后端的对接方式划分,如果有新的对接方式,实现addSpecificDynamicRoute接口
  • 如果有mq的路由:

    • 配置mq响应监听:由于有多个gateway实例,同一交易的请求和响应应该由同一个gateway处理。不同gateway的请求queue地址一样,但响应queue不同。响应queue地址在请求交易jms信息的reply字段,因此后台服务只需配置请求queue,响应queue包含在请求的jms信息中。这里响应queue地址为service_name + docker.slot(1, 2, 3…)。这样服务每次重启时,响应queue地址不会变动。如果gateway弹性扩展,slot+1,不用改动配置文件,实现自动扩容。如果响应queue为docker容器虚拟ip,服务每次都会新建queue,会十分混乱。
    • 超时mq消息处理:在exceedMap中检查是否有超时交易
  • 读取配置:

    • 去除对redis的依赖,可选择从redis或者配置文件。注入redis或配置文件的实现类。实现配置的获取和实现的分离,配置修改监听和配置获取的分离
  • 监听配置修改:

    • 可以选择不去监听,或者通过redis,zk监听
    • 监听新的配置,如某个api的限流大小,监听某个key如change,如果变动值为value,就从spring中找到名字为value的bean,调用run方法。
    • 如果增加新配置,不用再if else或switch地改动代码,新建类即可,实现对扩展开放,修改关闭。

优势:

  • 更加抽象,扩展性更强,

劣势:

  • 架构更加复杂,调试不便,学习曲线陡峭

网关搭建好之后,需要完善对网关交易的监控功能。我们需要实时(准实时)掌握交易情况和网关的运转情况,如:

  • 交易监控统计:

    • 交易总比数随时间的变化
    • 过去一段时间哪些机构调用哪个银行的哪些api,哪些api被调用的次数最多
    • 有没有异常交易,如超时,后台服务挂掉等引起的失败交易
  • 交易告警:

    • 配置告警规则,如果有异常交易,及时发出通知
  • 交易链路日志查看:

    • 通过流水号查看网关链路的日志
  • 出报表:

    • 过去一段时间机构,银行,api级别的调用统计情况,便于统计收费
  • 网关服务监控:

    • 过去一段时间网关内存使用,gc,活跃线程数等jvm信息,如果有异常及时告警

异常处理:

  • 网关转发请求到后台的异常:

    • 无法连接后台
    • 连接超时
  • 自定义异常:

    • filter未通过的异常,如参数校验失败,token校验失败,加解密失败等;
    • 断言异常,网关未匹配到路由
  • 未知异常:

    • 运行时异常等

这些异常在统一的地方由handler处理。
对于mq类交易异常,一般只有响应超时异常,由守护线程AutoGcFlux处理。


程序员灯塔
转载请注明原文链接:网关现有架构及优化
喜欢 (0)