基于Nginx dyups模块的站点动态上下线并实现简单服务治理

今天主要讨论一下,对于分布式服务,站点如何平滑的上下线问题。 nginx

在分布式服务下,咱们会用nginx作负载均衡, 业务站点访问某服务站点的时候, 统一走nginx, 而后nginx根据必定的轮询策略,将请求路由到后端一台指定的服务器上。 
 
这样的架构是没有问题的, 可是咱们这里考虑几个问题, 
1. 网站上下线问题:咱们网站平时更新站点的时候是直接覆盖文件,而后重启, 那这样会形成一些请求中断,若是是非核心逻辑那还好, 若是是核心逻辑,那请求中断,会影响一些数据一致性,好比资金, 交易,订单等。  
 2. 动态加减机器,好比某个站点访问量大,要新增机器,那就须要修改nginx的配置,而后reload, 这样会中断链接。 虽然reload很快,可是仍是会有一瞬间的请求中断。 
 
对于第一个问题,咱们能够在请求量少的时候去更新, 可是这种在一些服务稳定的公司可用, 对于互联网企业,可能2-3天就一个版本, 并且须要马上上线, 若是每次都要等到凌晨4点去更新, 可能整个的开发节奏都被带慢了。 
对于第二个问题, 对于能够预见的流量,好比大促来临,能够提早3天放在请求量少的时候更新。 
 
最近几年,随着SOA的普及和微服务的出现,特别是dubbo的出现,服务治理的概念被提出来。 服务治理是一个很宏大的概念,包括 服务注册,服务自动发现,服务路由,服务依赖,集群容错,服务降级,服务监测,服务审批等,固然不是每一个服务中心都必须实现这些东西, 公司能够根据本身的实际需求来定制实现。 
基于以上这些状况, 我计划实现一个工具,这个工具首先解决站点上下线和动态扩容问题,也就是说在不须要重启nginx的状况下,而且在保证请求不丢失的状况下来更新站点。 同时带有部分服务治理功能。 
 
 
服务上线
1. 在一个新服务上线的时候,通常会提早申请几台机器, 运维会在nginx上新增server,并新增server对应的upstream ,正常状况下upstream应该配置是后端服务器的IP,可是这里不配置(若是容许,甚至这一步均可以省略)。 
2. 服务部署好并启动,在启动的时候,向注册中心注册自身的服务信息,包括IP和端口。 
3. 注册中心收到请求后,会对服务进行健康检测,确保提供的服务没有问题,则将服务状态标示为 预上线状态。 
4. 在后台管理中心,就能够将 预上线的服务设置为 上线,服务管理中心会调用nginx的上线接口,将服务IP新增或者更新到upstream中,服务就能够提供访问。   
 
服务更新
假如咱们如今有一个服务须要更新,则执行如下步骤:
1. 在后台管理中心,将一个服务设为 下线,此时服务中心会调用nginx的下线接口,将指定服务器的IP设置为下线。 
2. 在等待1分钟后,确保没有新链接连过来,则能够开始更新服务站点。
3. 更新完毕后,再手动设为 上线,此时服务中心会调用nginx的上线接口,将指定服务器的IP设置为上线。固然对于成熟的服务,这些均可以自动化,有些公司会有一些自动化发布工具, 与自动化发布工具集成,能够一键下线,更新并上线。 
 
服务运行期间
在服务运行过程当中,会有一个健康检测的服务对全部提供服务的站点进行健康检测,一旦检测到有问题,就执行 下线逻辑。 直到问题被解决,最后执行 上线流程。 
 
动态加减机器
在服务运行过程当中,可能由于某些缘由,服务请求飙高(前提是这些请求都是合法的),超过了当前集群的承载能力,当系统检测到这些状况后,能够动态扩充机器,好比如今流行的docker,在启动容器的时候,同时启动应用,应用在启动的时候,将自身信息注册给注册中心,注册中心再将这些信息同步到nginx,应用就能够提供访问,总体上就能够实现弹性计算。 
 
为何不实现服务动态发现?
   这里能够看到图中已经有一个服务注册中心。 既然有了服务注册中心了, 那可让业务站点链接服务注册中心来获取真实的服务IP,而后绕过nginx来链接服务,这里之因此没有这样作,是由于:
    1.  实现服务动态发现,这个须要和RPC框架配合,并且须要作服务的软负载,失败重连,限流等,整个项目设计就上升了一个复杂度, 考虑到有些项目还未使用RPC,而且不想对原有的项目有过多的侵入, 因此这里不作实现。 可是并不意味没有这些功能,服务的负载, 失败重连, 限流,其实这些功能在nginx中一样也有,能够直接使用,因此没有必要从新再开发。 
    2.  实现服务动态发现,获取到真实的服务IP,而后直连,这些通常是在流量特别大,nginx上出现短板的时候使用,但实际状况,通常不多会耗尽nginx的性能,即便有,也能够经过ngxin水平扩展来实现,因此这里依然使用nginx做为负载均衡。 
 
这里讲一下这个项目的关键点:
1. 服务的注册和健康检测这个没有技术难点,这里不作解释。
2. 关于操做nginx上下线,这里的确是一个难点,由于nginx自己并无提供这些上下线API,须要openresty并配合一些第三方扩展来实现。 这里主要用到了两个扩展模块: ngx_http_dyups_module  lua-upstream-nginx-module
   ngx_http_dyups_module( https://github.com/yzprofile/ngx_http_dyups_module)提供了粗粒度的upstream管理方法,能够对整个upstream进行新增,删除。 
  lua-upstream-nginx-module( https://github.com/openresty/lua-upstream-nginx-module) ,则提供了细粒度的管理方式,能够对某一个服务IP进行管理,其中提供的set_peer_down方法,能够对upstream中的某个ip进行上下线。
3. 也可使用 ngx_dynamic_upstream( https://github.com/cubicdaiya/ngx_dynamic_upstream)
这些插件有一个共同点,那就是在不须要重启nginx的基础上, 动态修改nginx的配置。 
1. 最后我想请大伙讨论一下,大家公司是怎么上下线的, 是直接覆盖,仍是有其余策略。 欢迎在评论区讨论。
相关文章
相关标签/搜索