宙斯网关技术

2019-06-09  本文已影响0人  过去今天和未来

1、API网关

伴随着业务数据爆炸式的增长和无解开放的思维盛行,ISV(开发者包括合作伙伴、开发者、中小型商家)需要接入大量的业务场景,以此来完成他们的订单发货、商品上下架、售后服务、物流跟踪等整个电商流程。为了应对不同类型的服务接口调用,API网关承载着京东内部系统和外界连接的桥梁来完成一些非业务逻辑处理包括白名单控制、流量控制、权限校验、入参处理(解析、校验、加解密、封装)、缓存数据、协议转化、请求路由、返回参数处理、日志收集,最终将相应结果返回给ISV。

2、网关技术

网关系统每天都在承载的十几亿的有效调用,618和双十一更是能达到二十多亿的调用,为了保证每个接口平稳有效的调用。开放网关不仅需要几十台机器抗量,同时还需要很多技术手段来完成整个调用过程。
  线程池隔离
  当整个网关的中,如果因为单个服务响应延迟差,那么容器中整个线程数会持续增加直到整个机器的CPU飙升,对外整个不可用。这时候为了整个网关稳定性,需要对特有的业务场景单独分配固定的线程池,和其他线程池隔离,这样即使其中一个接口延迟高占用线程数当线程数达到阈值后采用拒绝策略,但是对于核心服务有单独的线程池可以继续处理保证调用正常。
  采用ConcurrentHashMap存储线程池,key为API接口名,值为每个API对应的线程池ThreadPool。对于Netflix API网关每天使用线程隔离处理100亿,每个API都默认分配40多个线程池,每个线程池有5-20个线程处理。
  缓存技术
  对于网关获取应用信息、接口文档信息、授权信息等,不会重度依赖RPC接口服务,所以必须采用多级缓存技术来取数据。主要包括本地缓存(Map和GuavaCache)和分布式缓存Redis。
  缓存命中率(请求到缓存数/总的请求数),当命中率高这样减少了每次调用RPC服务的网络请求时间和查库的时间。
  在使用缓存时会设置缓存的存活时间,保证数据在一定时间后进行更新。有时也会对数据持久化,但是采用redis中hset方式存储时间戳,进行逻辑过期来定期更新数据,这样做的好处即使当服务异常时,也可以从缓存中获取老数据,保证数据的可用性。在使用缓存的时候,同时需要考虑缓存穿透、缓存雪崩、热点数据失效等问题。
  热更新:当数据发生变化的为了获取最新的数据,采用PRC方式轮训请求网关来更新缓存数据。在SPI网关中采用Zookeeper监听方式保证缓存数据动态更新。这样达到动态更新数据,从而不需要重启服务器。
  异步化调用
  为了使用少量的机器接入更多的服务,需要使用异步调用来处理,保证整个网关的吞吐量。
  在接受客户端请求,采用Tomcat8的NIO机制+servlet3的异步,
  首先servlet3的异步流程主要在收到request请求,由tomcat工作线程从HttpServletRequest中获取AsyncContext对象,然后tomcat的工作线程将AsyncContext对象传递给业务工作线程,当传递后Tomcat工作线程归还到Tomcat线程池中继续下一个请求的接受,当业务线程处理完成后asyncContext.getResponse().getWriter()接受响应结果,使用asyncContext.complete()完成整个异步请求。
  Tomcat8的NIO则为IO的一种模型,主要是面向inputstream和outputstream流。使得tomcat容器使用较少的线程处理大量的连接请求,达到一个线程无需负责整个请求过程。
  全异步网关
  上面描述的是网关接受客户端请求部分的异步化操作,网关作为统一开放平台,当请求到各业务线的RPC服务接口或者http请求,同样可以使用异步支持请求。达到少量的线程处理更多的请求。

全异步流程.jpg
  流量控制
  在整个网关设计中,会基于API服务、Appkey维度按照每分钟/每小时/每天进行限流调用。比如说存在某个appkey每天调用的流量包,当超过这个流量包大小则限制住;当某个API接口性能比较差时,同样可以限制调用量。
   限流手段主要采用Redis来实现,包括set()、ttl()、incr()、expire()方法来实现逻辑处理
  除了分布式限流还采用Guava的令牌桶去做单机限流,这样做主要对单机进行保护措施,保证不会因为某块耗CPU的逻辑将整个机器拖垮。比如在ISV打包过程中,使用令牌桶保证每分钟只能处理多少请求。
   统一监控
   监控是网关非常重要的部分,有了报警使得我们能快速发现调用异常情况。当出现异常时,我们会第一时间接受通知,最大限度保证用户对异常的无感知。主要包含以下监控
  硬件监控:机器CPU、机器磁盘使用情况、机器内存等
   接口性能监控:对每个接口配置自定义监控,当接口出现可用率下降情况,能够快速发现
  jvm监控:对机器jvm的GC情况进行监控,当出现频繁的GC会导致整个机器反应迟钝。
  自定义报警:配置每个appkey调用阈值,当超过后第一时间通知,我们按照实际情况进行调整或者进行限制。
  Oauth协议验证
  Oauth是一个授权的开放网络标准,在这种标准下允许用户让第三方应用访问该用户在网站上的私密的资源。为了保证用户数据安全与隐私,用户需要进行授权操作,主要是在客户端和服务提供者设置了一个授权层,客户端通过完成Oauth授权,将京东用户(商城用户、商家用户、供应商等)和客户端区分开来。用户完成Oauth协议流程后,可以获取授权中心的令牌和有效期限。
  API网关采用的正式服务器端授权模式,主要分为两个步骤 授权流程.jpg

1)拼接授权URL进行请求,完成用户密码登录授权。这一过程主要通过应用标识(appkey)和回调地址(redirect_url)获取授权码code。code码在获取令牌信息中只能使用一次,即使因为黑客拦截到code码也是无效的。
2)通过应用标识、授权码、签名等信息获取访问令牌token,最终可以根据应用标识(appkey)、应用签名(app_secret)、应用令牌(app_token)可以有效、安全的调用API网关。
   其中如果授权账号修改密码或者重置签名则授权令牌随之失效,这样即使授权信息泄露,也会通过重置密码等措施导致令牌失效间接的保证授权信息安全性。具体操作步骤可参照
   管道链式处理
  在API网关中由于不涉及到任何业务操作,但是在请求各个业务层面数据之前,网关会进行一些处理,包括白名单限制、流控限制、参数校验、请求路由等。所以为了进行解耦操作引入管道的概念,类似于责任链模式,这样可以根据API接口动态化配置管道信息。
  管道链处理如下图:

管道链示意图.jpg

当请求过来后,根据管理端配置的管道的先后顺序进行执行。请求在管道实现信息传递之前,会根据请求标识信息(appkey)获取授权信息、API接口信息然后封装为pipeInput公共类完成信息传递,当一个管道验证失败则进行统一异常处理。
   泛化调用
  在调用RPC服务大部分情况下会采用同步调用,有时为了增加调用吞吐量也会采用异步调用。但是都需要在消费端xml配置文件中配置RPC接口信息(RPC服务接口、别名信息等),但是对于网关这种上千的接口不会依次添加所有RPC配置信息,直接根据接口名、参数类型和参数值发送给服务端,服务端则判断是泛化调用自动解析请求调用服务端,完成一次RPC调用。

3. 其他场景

在网关里大的品牌商扮演的重要的角色,他们会将自己的应用搭建在京东云服务器,然后我们在京东App端或者京麦端提供流量入口,同时也会限制只能在端内打开。由于请求量巨大和处理逻辑简单所以使用nginx+lua来搭建统一接入层。这里主要涉及到的时签名验证、域名绑定验证、云主机路由请求等操作,最终将请求转发到品牌商的云主机上,完成整个限制操作。


统一接入层.jpg
上一篇 下一篇

猜你喜欢

热点阅读