简介

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

分布式服务

在分布式服务下,我们会用nginx做负载均衡, 业务站点访问某服务站点的时候, 统一走nginx, 然后nginx根据一定的轮询策略,将请求路由到后端一台指定的服务器上。 
 
这样的架构是没有问题的, 但是我们这里考虑几个问题, 
1. 网站上下线问题:我们网站平时更新站点的时候是直接覆盖文件,然后重启, 那这样会造成一些请求中断,如果是非核心逻辑那还好, 如果是核心逻辑,那请求中断,会影响一些数据一致性,比如资金, 交易,订单等。  
 2. 动态加减机器,比如某个站点访问量大,要新增机器,那就需要修改nginx的配置,然后reload, 这样会中断连接。 虽然reload很快,但是还是会有一瞬间的请求中断。 
 
对于第一个问题,我们可以在请求量少的时候去更新, 但是这种在一些服务稳定的公司可用, 对于互联网企业,可能2-3天就一个版本, 而且需要立刻上线, 如果每次都要等到凌晨4点去更新, 可能整个的开发节奏都被带慢了。 
对于第二个问题, 对于可以预见的流量,比如大促来临,可以提前3天放在请求量少的时候更新。 
 
最近几年,随着SOA的普及和微服务的出现,特别是dubbo的出现,服务治理的概念被提出来。 服务治理是一个很宏大的概念,包括服务注册,服务自动发现,服务路由,服务依赖,集群容错,服务降级,服务监测,服务审批等,当然不是每个服务中心都必须实现这些东西, 公司可以根据自己的实际需求来定制实现。 

基于Nginx dyups模块的动态上下线

基于以上这些情况, 我计划实现一个工具,这个工具首先解决站点上下线和动态扩容问题,也就是说在不需要重启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. 最后我想请大伙讨论一下,你们公司是怎么上下线的, 是直接覆盖,还是有其他策略。 欢迎在评论区讨论。

基于Nginx dyups模块的站点动态上下线并实现简单服务治理的更多相关文章

  1. CentOS 环境下基于 Nginx uwsgi 搭建 Django 站点

    因为我的个人网站 restran.net 已经启用,博客园的内容已经不再更新.请访问我的个人网站获取这篇文章的最新内容,CentOS 环境下基于 Nginx uwsgi 搭建 Django 站点 以下 ...

  2. ZooKeeper之服务器动态上下线案例

    需求 某分布式系统中,主节点可以有多台,可以动态上下线,任意一台客户端都能实时感知到主节点服务器的上下线. 需求分析 具体实现 先在集群上创建/servers节点 create /servers &q ...

  3. 基于nginx实现上游服务器动态自动上下线——不需reload

    网上关于nginx的介绍有很多,这里讲述的是上游服务(如下图的Java1服务)在没有"网关"的情况下,如何通过nginx做到动态上下线. 传统的做法是,手动修改nginx的upst ...

  4. 基于nginx+lua+redis高性能api应用实践

    基于nginx+lua+redis高性能api应用实践 前言 比较传统的服务端程序(PHP.FAST CGI等),大多都是通过每产生一个请求,都会有一个进程与之相对应,请求处理完毕后相关进程自动释放. ...

  5. 学习笔记:Zookeeper 应用案例(上下线动态感知)

    1.Zookeeper 应用案例(上下线动态感知) 8.1 案例1--服务器上下线动态感知 8.1.1 需求描述 某分布式系统中,主节点可以有多台,可以动态上下线 任意一台客户端都能实时感知到主节点服 ...

  6. 基于nginx + lua实现的反向代理动态更新

    大家都知道,nginx是当前应用非常广泛的web服务器,热度因为他的高并发高性能高可靠性,且轻量级!牛逼的不行,不多说这些. 今天要介绍的是,如何基于nginx和lua脚本,也就是在openresty ...

  7. 【转载】【JAVA秒会技术之图片上传】基于Nginx及FastDFS,完成图片的上传及展示

    基于Nginx及FastDFS,完成商品图片的上传及展示 一.传统图片存储及展示方式 存在问题: 1)大并发量上传访问图片时,需要对web应用做负载均衡,但是会存在图片共享问题 2)web应用服务器的 ...

  8. Docker实战 | 第三篇:Docker安装Nginx,实现基于vue-element-admin框架构建的项目线上部署

    一. 前言 在上一文中 点击跳转 通过IDEA集成Docker插件实现微服务的一键部署,但 youlai-mall 是前后端分离的项目,除了后端微服务的部署之外,当然还少不了前端工程的部署.所以本篇讲 ...

  9. 在微信框架模块中,基于Vue&Element前端,通过动态构建投票选项,实现单选、复选的投票操作

    最近把微信框架的前端改造一下,在原来基于Bootstrap框架基础上的微信后台管理,增加一套Vue&Element的前端,毕竟Vue的双向绑定开发起来也还是很方便的,而且Element本身也提 ...

随机推荐

  1. ArcSDE安装注意事项(二)

    上次安装的arcsde9.3后尝试往本机sde数据库中导入一个区局的数据库,但是每次都是导到一半就卡死不动,也没有报任何的错误,因此安装了arcsde9.3 sp2补丁,安装补丁后连接sde(非直连方 ...

  2. SharePoint 2013 入门教程之创建及修改母版页

    在SharePoint 2013中,微软提供了根据HTML页面转换Master页的方法,并支持单项同步,但是这样的更新,并不完善,会使一些功能造成丢失,所以,了解Master结构的人,尽量直接去修改M ...

  3. Android Home键监听

    Android Back Home键监听 Back键的监听 对于Back键的监听比较容易,可以在多个系统回调处拦截,比如在activity的下列方法中都可以收到Back键按下的事件: @Overrid ...

  4. xCode5 在ios7模拟器中出现__cxa_throw _pthread_exit错误

    xCode5 在ios7模拟器中出现__cxa_throw _pthread_exit错误 2013年10月28日 ⁄ 综合 ⁄ 共 233字 ⁄ 字号 小 中 大 ⁄ 评论关闭   在项目中用模拟器 ...

  5. Android开发--异步加载

    因为移动端软件开发思维模式或者说是开发的架构其实是不分平台和编程语言的,就拿安卓和IOS来说,他们都是移动前端app开发展示数据和用户交互数据的数据终端,移动架构的几个大模块:UI界面展示.本地数据可 ...

  6. IOS-WebViewJavascriptBridge使用说明

    下面来说一下WebViewJavascriptBridge在ios端怎么样使用. 首先确保一份已经配好功能的html文件. 1.初始化一个webview(viewdidload) UIWebView* ...

  7. MS SQL 统计信息浅析上篇

    统计信息概念 统计信息是一些对象,这些对象包含在表或索引视图中一列或多列中的数据分布有关的统计信息.数据库查询优化器使用这些统计信息来估计查询结果中的基数或行数. 通过这些基数估计,查询优化器可以生成 ...

  8. javascript - 享元模式

    享元模式笔记  运用共享技术有效的支持大量的细粒度对象,避免对象间拥有相同内容造成多余的开销  享元模式主要还是对其数据.方法共享分离,它将数据和方法分成内部数据.内部方法和外部数据.外部方法.  内 ...

  9. WINDOWS登录系统之前(欢迎界面)运行指定程序脚本服务

    方法一:创建可在系统登录之前运行的服务 PS:需要用到两个程序—Srvany和Instsrv,点击 http://pan.baidu.com/share/link?shareid=4111024491 ...

  10. WPF 显示文件列表中使用 ListBox 变到ListView 最后使用DataGrid

    WPF 显示文件列表中使用 ListBox 变到ListView 最后使用DataGrid 故事背景: 需要检索某目录下文件,并列出来,提供选择和其他功能. 第一版需求: 列出文件供选择即可,代码如下 ...