• 1
  • 2
  • 3
  • 4
  • 5
阿里云应用开发 首 页  »  帮助中心  »  云服务器  »  阿里云应用开发
PaaS 7层动态路由的若干实现
发布日期:2016-7-8 16:7:18

  随着Docker的出现,PaaS、CaaS(Container As A Service)、甚至DCOS(DataCenter OS)呈现了爆发式的发展。而在PaaS中,由于实例一般默认为动态IP,对于7层调用(比如http请求),需7层动态路由获取应用域名(或虚IP)和后端实例的映射关系,以提供7层服务;而对于4层调用(比如rpc调用),可通过动态LVS或名字服务(或基于zookeeper/etcd等实现的服务注册和发现工具)进行调用。

  

  简单举例,开发者在PaaS里创建了一个APP,包含若干个实例,然后为APP绑定某个域名。用户对APP发出请求,需经过后端实例的处理才能够正确返回。那么作为7层动态路由,核心就是获取域名(或虚IP)与后端实例的对应关系并作为反向代理完成请求转发。这里简单讨论下7层动态路由的若干实现。由于nginx是一个高性能的反向代理服务器,以是不是基于nginx实现7层动态路由,可将这些实现大概分为两大类。

  第一类,不依赖nginx,项目自身实现了反向代理的功能。

  CloudFoundry可以说是第一代的开源PaaS项目,其模块gorouter即为一个动态路由实现(同时支持4层和7层)。以 CloudFoundry (release v164)为例,使用nats作为消息总线,对各模块调用和消息传递进行解耦。可看下gorouter (tag 45ca951297)的代码,registry/registry.go里实现了相应逻辑代码,以获取域名和后端实例的对应关系。其大概流程为:

  实例启动后向nats发布消息,gorouter则会订阅这些消息,从而获取应用域名和后端实例的对应关系;同时gorouter使用goroutine实现了高性能的请求处理和转发,支持4层和7层调用。Docker出现后,基于Docker的轻量级PaaS纷纷涌现,大家也许会把实例信息(如IP信息等)存储在redis(或者其它数据存储)。开源项目DINP基本就是这样的实现,dinp-router fork自CloudFoundry的gorouter (tag 45ca951297),更改了部分代码,以获取应用域名和redis中存储的后端实例的对应关系,从而实现了7层动态路由的功能。类似的,dotCloud的hipache则是利用nodejs的http库实现了请求转发,后端实例信息则可以存储在redis中。

  当然,很多工程师在7层的选型上还是更信赖nginx,毕竟nginx在性能、稳定性、扩展性上都是不二之选。基于nginx来实现7层动态路由,大概又有两种实现思路。

  其一,基于名字服务(或者基于zookeeper/etcd等实现的服务注册和发现工具),通过watch或者定时调度,将注册的后端实例更新到 nginx配置文件的upstream中,从而实现后端的(准)实时变化。这方面也有如confd等的开源工具。confd基于golang的 template库,将nginx配置文件作为模板;支持consul/etcd/redis/zookeeper等诸多后端存储,通过watch或者定时调度从这些后端获取实例信息,并更新到nginx配置文件模板,从而实现(准)实时的7层动态路由。这种实现逻辑简单,稳定性高,但是在大规模应用的时候 nginx也许会较频繁的reload。

  其二,基于nginx-lua实现。每次用户请求到达相应upstream的时候,通过nginx-lua从redis等数据存储中获得后端实例信息,从而实现请求的转发。nginx获取redis数据需要进行一次网络请求,同机房的时延一般是毫秒级,但是在大访问量的时候也许存在一定问题,因此可使用 lua-shared-dict作为系统缓存。

  参考:

  https://github.com/openresty/lua-nginx-module

  http://segmentfault.com/a/1190000004128807?luicode=10000359&luicode=10000359