架构

架构

京东咚咚架构演进

运维技术koyo 发表了文章 • 0 个评论 • 1348 次浏览 • 2016-08-24 22:26 • 来自相关话题

咚咚是什么?咚咚之于京东相当于旺旺之于淘宝,它们都是服务于买家和卖家的沟通。 自从京东开始为第三方卖家提供入驻平台服务后,咚咚也就随之诞生了。 我们首先看看它诞生之初是什么样的。
 

1.0 诞生(2010 - 2011)​

为了业务的快速上线,1.0 版本的技术架构实现是非常直接且简单粗暴的。 如何简单粗暴法?请看架构图,如下:




1.0 的功能十分简单,实现了一个 IM 的基本功能,接入、互通消息和状态。 另外还有客服功能,就是顾客接入咨询时的客服分配,按轮询方式把顾客分配给在线的客服接待。 用开源 Mina 框架实现了 TCP 的长连接接入,用 Tomcat Comet 机制实现了 HTTP 的长轮询服务。 而消息投递的实现是一端发送的消息临时存放在 Redis 中,另一端拉取的生产消费模型。

这个模型的做法导致需要以一种高频率的方式来轮询 Redis 遍历属于自己连接的关联会话消息。 这个模型很简单,简单包括多个层面的意思:理解起来简单;开发起来简单;部署起来也简单。 只需要一个 Tomcat 应用依赖一个共享的 Redis,简单的实现核心业务功能,并支持业务快速上线。

但这个简单的模型也有些严重的缺陷,主要是效率和扩展问题。 轮询的频率间隔大小基本决定了消息的延时,轮询越快延时越低,但轮询越快消耗也越高。 这个模型实际上是一个高功耗低效能的模型,因为不活跃的连接在那做高频率的无意义轮询。 高频有多高呢,基本在 100 ms 以内,你不能让轮询太慢,比如超过 2 秒轮一次,人就会在聊天过程中感受到明显的会话延迟。 随着在线人数增加,轮询的耗时也线性增长,因此这个模型导致了扩展能力和承载能力都不好,一定会随着在线人数的增长碰到性能瓶颈。

1.0 的时代背景正是京东技术平台从 .NET 向 Java 转型的年代,我也正是在这期间加入京东并参与了京东主站技术转型架构升级的过程。 之后开始接手了京东咚咚,并持续完善这个产品,进行了三次技术架构演进。
 

2.0 成长(2012)

我们刚接手时 1.0 已在线上运行并支持京东 POP(开放平台)业务,之后京东打算组建自营在线客服团队并落地在成都。 不管是自营还是 POP 客服咨询业务当时都起步不久,1.0 架构中的性能和效率缺陷问题还没有达到引爆的业务量级。 而自营客服当时还处于起步阶段,客服人数不足,服务能力不够,顾客咨询量远远超过客服的服务能力。 超出服务能力的顾客咨询,当时我们的系统统一返回提示客服繁忙,请稍后咨询。 这种状况导致高峰期大量顾客无论怎么刷新请求,都很可能无法接入客服,体验很差。 所以 2.0 重点放在了业务功能体验的提升上,如下图所示:




针对无法及时提供服务的顾客,可以排队或者留言。 针对纯文字沟通,提供了文件和图片等更丰富的表达方式。 另外支持了客服转接和快捷回复等方式来提升客服的接待效率。 总之,整个 2.0 就是围绕提升客服效率和用户体验。 而我们担心的效率问题在 2.0 高速发展业务的时期还没有出现,但业务量正在逐渐积累,我们知道它快要爆了。 到 2012 年末,度过双十一后开始了 3.0 的一次重大架构升级。
 

3.0 爆发(2013 - 2014)

经历了 2.0 时代一整年的业务高速发展,实际上代码规模膨胀的很快。 与代码一块膨胀的还有团队,从最初的 4 个人到近 30 人。 团队大了后,一个系统多人开发,开发人员层次不一,规范难统一,系统模块耦合重,改动沟通和依赖多,上线风险难以控制。 一个单独 tomcat 应用多实例部署模型终于走到头了,这个版本架构升级的主题就是服务化。

服务化的第一个问题如何把一个大的应用系统切分成子服务系统。 当时的背景是京东的部署还在半自动化年代,自动部署系统刚起步,子服务系统若按业务划分太细太多,部署工作量很大且难管理。 所以当时我们不是按业务功能分区服务的,而是按业务重要性级别划分了 0、1、2 三个级别不同的子业务服务系统。 另外就是独立了一组接入服务,针对不同渠道和通信方式的接入端,见下图。




更细化的应用服务和架构分层方式可见下图:




这次大的架构升级,主要考虑了三个方面:稳定性、效率和容量。 做了下面这些事情:
业务分级、核心、非核心业务隔离多机房部署,流量分流、容灾冗余、峰值应对冗余读库多源,失败自动转移写库主备,短暂有损服务容忍下的快速切换外部接口,失败转移或快速断路Redis 主备,失败转移大表迁移,MongoDB 取代 MySQL 存储消息记录改进消息投递模型
 
前 6 条基本属于考虑系统稳定性、可用性方面的改进升级。 这一块属于陆续迭代完成的,承载很多失败转移的配置和控制功能在上面图中是由管控中心提供的。 第 7 条主要是随着业务量的上升,单日消息量越来越大后,使用了 MongoDB 来单独存储量最大的聊天记录。 第 8 条是针对 1.0 版本消息轮询效率低的改进,改进后的投递方式如下图所示:




不再是轮询了,而是让终端每次建立连接后注册接入点位置,消息投递前定位连接所在接入点位置再推送过去。 这样投递效率就是恒定的了,而且很容易扩展,在线人数越多则连接数越多,只需要扩展接入点即可。 其实,这个模型依然还有些小问题,主要出在离线消息的处理上,可以先思考下,我们最后再讲。

3.0 经过了两年的迭代式升级,单纯从业务量上来说还可以继续支撑很长时间的增长。 但实际上到 2014 年底我们面对的不再是业务量的问题,而是业务模式的变化。 这直接导致了一个全新时代的到来。
 

4.0 涅槃(2015 至今 )

2014 年京东的组织架构发生了很大变化,从一个公司变成了一个集团,下设多个子公司。 原来的商城成为了其中一个子公司,新成立的子公司包括京东金融、京东智能、京东到家、拍拍、海外事业部等。 各自业务范围不同,业务模式也不同,但不管什么业务总是需要客服服务。 如何复用原来为商城量身订做的咚咚客服系统并支持其他子公司业务快速接入成为我们新的课题。

最早要求接入的是拍拍网,它是从腾讯收购的,所以是完全不同的账户和订单交易体系。 由于时间紧迫,我们把为商城订做的部分剥离,基于 3.0 架构对接拍拍又单独订做了一套,并独立部署,像下面这样。




虽然在业务要求的时间点前完成了上线,但这样做也带来了明显的问题:
复制工程,定制业务开发,多套源码维护成本高独立部署,至少双机房主备外加一个灰度集群,资源浪费大
 
以前我们都是面向业务去架构系统,如今新的业务变化形势下我们开始考虑面向平台去架构,在统一平台上跑多套业务,统一源码,统一部署,统一维护。 把业务服务继续拆分,剥离出最基础的 IM 服务,IM 通用服务,客服通用服务,而针对不同的业务特殊需求做最小化的定制服务开发。 部署方式则以平台形式部署,不同的业务方的服务跑在同一个平台上,但数据互相隔离。 服务继续被拆分的更微粒化,形成了一组服务矩阵(见下图)




而部署方式,只需要在双机房建立两套对等集群,并另外建一个较小的灰度发布集群即可,所有不同业务都运行在统一平台集群上,如下图:




更细粒度的服务意味着每个服务的开发更简单,代码量更小,依赖更少,隔离稳定性更高。 但更细粒度的服务也意味着更繁琐的运维监控管理,直到今年公司内部弹性私有云、缓存云、消息队列、部署、监控、日志等基础系统日趋完善, 使得实施这类细粒度划分的微服务架构成为可能,运维成本可控。 而从当初 1.0 的 1 种应用进程,到 3.0 的 6、7 种应用进程,再到 4.0 的 50+ 更细粒度的不同种应用进程。 每种进程再根据承载业务流量不同分配不同的实例数,真正的实例进程数会过千。 为了更好的监控和管理这些进程,为此专门定制了一套面向服务的运维管理系统,见下图:




统一服务运维提供了实用的内部工具和库来帮助开发更健壮的微服务。 包括中心配置管理,流量埋点监控,数据库和缓存访问,运行时隔离,如下图所示是一个运行隔离的图示:




细粒度的微服务做到了进程间隔离,严格的开发规范和工具库帮助实现了异步消息和异步 HTTP 来避免多个跨进程的同步长调用链。 进程内部通过切面方式引入了服务增强容器 Armor 来隔离线程, 并支持进程内的单独业务降级和同步转异步化执行。而所有这些工具和库服务都是为了两个目标:
让服务进程运行时状态可见让服务进程运行时状态可被管理和改变

最后我们回到前文留下的一个悬念,就是关于消息投递模型的缺陷。 一开始我们在接入层检测到终端连接断开后,消息无法投递,再将消息缓存下来,等终端重连接上来再拉取离线消息。 这个模型在移动时代表现的很不好,因为移动网络的不稳定性,导致经常断链后重连。 而准确的检测网络连接断开是依赖一个网络超时的,导致检测可能不准确,引发消息假投递成功。 新的模型如下图所示,它不再依赖准确的网络连接检测,投递前待确认消息 id 被缓存,而消息体被持久存储。 等到终端接收确认返回后,该消息才算投妥,未确认的消息 id 再重新登陆后或重连接后作为离线消息推送。 这个模型不会产生消息假投妥导致的丢失,但可能导致消息重复,只需由客户终端按消息 id 去重即可。




京东咚咚诞生之初正是京东技术转型到 Java 之时,经历这些年的发展,取得了很大的进步。 从草根走向专业,从弱小走向规模,从分散走向统一,从杂乱走向规范。 本文主要重心放在了几年来咚咚架构演进的过程,技术架构单独拿出来看我认为没有绝对的好与不好, 技术架构总是要放在彼时的背景下来看,要考虑业务的时效价值、团队的规模和能力、环境基础设施等等方面。 架构演进的生命周期适时匹配好业务的生命周期,才可能发挥最好的效果。
分享阅读原文:http://www.cnblogs.com/mindwind/p/5017591.html  查看全部
dongdong.png

咚咚是什么?咚咚之于京东相当于旺旺之于淘宝,它们都是服务于买家和卖家的沟通。 自从京东开始为第三方卖家提供入驻平台服务后,咚咚也就随之诞生了。 我们首先看看它诞生之初是什么样的。
 


1.0 诞生(2010 - 2011)​


为了业务的快速上线,1.0 版本的技术架构实现是非常直接且简单粗暴的。 如何简单粗暴法?请看架构图,如下:
Arch1.png

1.0 的功能十分简单,实现了一个 IM 的基本功能,接入、互通消息和状态。 另外还有客服功能,就是顾客接入咨询时的客服分配,按轮询方式把顾客分配给在线的客服接待。 用开源 Mina 框架实现了 TCP 的长连接接入,用 Tomcat Comet 机制实现了 HTTP 的长轮询服务。 而消息投递的实现是一端发送的消息临时存放在 Redis 中,另一端拉取的生产消费模型。

这个模型的做法导致需要以一种高频率的方式来轮询 Redis 遍历属于自己连接的关联会话消息。 这个模型很简单,简单包括多个层面的意思:理解起来简单;开发起来简单;部署起来也简单。 只需要一个 Tomcat 应用依赖一个共享的 Redis,简单的实现核心业务功能,并支持业务快速上线。

但这个简单的模型也有些严重的缺陷,主要是效率和扩展问题。 轮询的频率间隔大小基本决定了消息的延时,轮询越快延时越低,但轮询越快消耗也越高。 这个模型实际上是一个高功耗低效能的模型,因为不活跃的连接在那做高频率的无意义轮询。 高频有多高呢,基本在 100 ms 以内,你不能让轮询太慢,比如超过 2 秒轮一次,人就会在聊天过程中感受到明显的会话延迟。 随着在线人数增加,轮询的耗时也线性增长,因此这个模型导致了扩展能力和承载能力都不好,一定会随着在线人数的增长碰到性能瓶颈。

1.0 的时代背景正是京东技术平台从 .NET 向 Java 转型的年代,我也正是在这期间加入京东并参与了京东主站技术转型架构升级的过程。 之后开始接手了京东咚咚,并持续完善这个产品,进行了三次技术架构演进。
 


2.0 成长(2012)


我们刚接手时 1.0 已在线上运行并支持京东 POP(开放平台)业务,之后京东打算组建自营在线客服团队并落地在成都。 不管是自营还是 POP 客服咨询业务当时都起步不久,1.0 架构中的性能和效率缺陷问题还没有达到引爆的业务量级。 而自营客服当时还处于起步阶段,客服人数不足,服务能力不够,顾客咨询量远远超过客服的服务能力。 超出服务能力的顾客咨询,当时我们的系统统一返回提示客服繁忙,请稍后咨询。 这种状况导致高峰期大量顾客无论怎么刷新请求,都很可能无法接入客服,体验很差。 所以 2.0 重点放在了业务功能体验的提升上,如下图所示:
Arch2.png

针对无法及时提供服务的顾客,可以排队或者留言。 针对纯文字沟通,提供了文件和图片等更丰富的表达方式。 另外支持了客服转接和快捷回复等方式来提升客服的接待效率。 总之,整个 2.0 就是围绕提升客服效率和用户体验。 而我们担心的效率问题在 2.0 高速发展业务的时期还没有出现,但业务量正在逐渐积累,我们知道它快要爆了。 到 2012 年末,度过双十一后开始了 3.0 的一次重大架构升级。
 


3.0 爆发(2013 - 2014)


经历了 2.0 时代一整年的业务高速发展,实际上代码规模膨胀的很快。 与代码一块膨胀的还有团队,从最初的 4 个人到近 30 人。 团队大了后,一个系统多人开发,开发人员层次不一,规范难统一,系统模块耦合重,改动沟通和依赖多,上线风险难以控制。 一个单独 tomcat 应用多实例部署模型终于走到头了,这个版本架构升级的主题就是服务化。

服务化的第一个问题如何把一个大的应用系统切分成子服务系统。 当时的背景是京东的部署还在半自动化年代,自动部署系统刚起步,子服务系统若按业务划分太细太多,部署工作量很大且难管理。 所以当时我们不是按业务功能分区服务的,而是按业务重要性级别划分了 0、1、2 三个级别不同的子业务服务系统。 另外就是独立了一组接入服务,针对不同渠道和通信方式的接入端,见下图。
Arch3.png

更细化的应用服务和架构分层方式可见下图:
Arch4.png

这次大的架构升级,主要考虑了三个方面:稳定性、效率和容量。 做了下面这些事情:
  1. 业务分级、核心、非核心业务隔离
  2. 多机房部署,流量分流、容灾冗余、峰值应对冗余
  3. 读库多源,失败自动转移
  4. 写库主备,短暂有损服务容忍下的快速切换
  5. 外部接口,失败转移或快速断路
  6. Redis 主备,失败转移
  7. 大表迁移,MongoDB 取代 MySQL 存储消息记录
  8. 改进消息投递模型

 
前 6 条基本属于考虑系统稳定性、可用性方面的改进升级。 这一块属于陆续迭代完成的,承载很多失败转移的配置和控制功能在上面图中是由管控中心提供的。 第 7 条主要是随着业务量的上升,单日消息量越来越大后,使用了 MongoDB 来单独存储量最大的聊天记录。 第 8 条是针对 1.0 版本消息轮询效率低的改进,改进后的投递方式如下图所示:
Arch5.png

不再是轮询了,而是让终端每次建立连接后注册接入点位置,消息投递前定位连接所在接入点位置再推送过去。 这样投递效率就是恒定的了,而且很容易扩展,在线人数越多则连接数越多,只需要扩展接入点即可。 其实,这个模型依然还有些小问题,主要出在离线消息的处理上,可以先思考下,我们最后再讲。

3.0 经过了两年的迭代式升级,单纯从业务量上来说还可以继续支撑很长时间的增长。 但实际上到 2014 年底我们面对的不再是业务量的问题,而是业务模式的变化。 这直接导致了一个全新时代的到来。
 


4.0 涅槃(2015 至今 )


2014 年京东的组织架构发生了很大变化,从一个公司变成了一个集团,下设多个子公司。 原来的商城成为了其中一个子公司,新成立的子公司包括京东金融、京东智能、京东到家、拍拍、海外事业部等。 各自业务范围不同,业务模式也不同,但不管什么业务总是需要客服服务。 如何复用原来为商城量身订做的咚咚客服系统并支持其他子公司业务快速接入成为我们新的课题。

最早要求接入的是拍拍网,它是从腾讯收购的,所以是完全不同的账户和订单交易体系。 由于时间紧迫,我们把为商城订做的部分剥离,基于 3.0 架构对接拍拍又单独订做了一套,并独立部署,像下面这样。
Arch6.png

虽然在业务要求的时间点前完成了上线,但这样做也带来了明显的问题:
  1. 复制工程,定制业务开发,多套源码维护成本高
  2. 独立部署,至少双机房主备外加一个灰度集群,资源浪费大

 
以前我们都是面向业务去架构系统,如今新的业务变化形势下我们开始考虑面向平台去架构,在统一平台上跑多套业务,统一源码,统一部署,统一维护。 把业务服务继续拆分,剥离出最基础的 IM 服务,IM 通用服务,客服通用服务,而针对不同的业务特殊需求做最小化的定制服务开发。 部署方式则以平台形式部署,不同的业务方的服务跑在同一个平台上,但数据互相隔离。 服务继续被拆分的更微粒化,形成了一组服务矩阵(见下图)
Arch7.png

而部署方式,只需要在双机房建立两套对等集群,并另外建一个较小的灰度发布集群即可,所有不同业务都运行在统一平台集群上,如下图:
Arch8.png

更细粒度的服务意味着每个服务的开发更简单,代码量更小,依赖更少,隔离稳定性更高。 但更细粒度的服务也意味着更繁琐的运维监控管理,直到今年公司内部弹性私有云、缓存云、消息队列、部署、监控、日志等基础系统日趋完善, 使得实施这类细粒度划分的微服务架构成为可能,运维成本可控。 而从当初 1.0 的 1 种应用进程,到 3.0 的 6、7 种应用进程,再到 4.0 的 50+ 更细粒度的不同种应用进程。 每种进程再根据承载业务流量不同分配不同的实例数,真正的实例进程数会过千。 为了更好的监控和管理这些进程,为此专门定制了一套面向服务的运维管理系统,见下图:
Arch9.png

统一服务运维提供了实用的内部工具和库来帮助开发更健壮的微服务。 包括中心配置管理,流量埋点监控,数据库和缓存访问,运行时隔离,如下图所示是一个运行隔离的图示:
Arch10.png

细粒度的微服务做到了进程间隔离,严格的开发规范和工具库帮助实现了异步消息和异步 HTTP 来避免多个跨进程的同步长调用链。 进程内部通过切面方式引入了服务增强容器 Armor 来隔离线程, 并支持进程内的单独业务降级和同步转异步化执行。而所有这些工具和库服务都是为了两个目标:
  1. 让服务进程运行时状态可见
  2. 让服务进程运行时状态可被管理和改变


最后我们回到前文留下的一个悬念,就是关于消息投递模型的缺陷。 一开始我们在接入层检测到终端连接断开后,消息无法投递,再将消息缓存下来,等终端重连接上来再拉取离线消息。 这个模型在移动时代表现的很不好,因为移动网络的不稳定性,导致经常断链后重连。 而准确的检测网络连接断开是依赖一个网络超时的,导致检测可能不准确,引发消息假投递成功。 新的模型如下图所示,它不再依赖准确的网络连接检测,投递前待确认消息 id 被缓存,而消息体被持久存储。 等到终端接收确认返回后,该消息才算投妥,未确认的消息 id 再重新登陆后或重连接后作为离线消息推送。 这个模型不会产生消息假投妥导致的丢失,但可能导致消息重复,只需由客户终端按消息 id 去重即可。
Arch11.png

京东咚咚诞生之初正是京东技术转型到 Java 之时,经历这些年的发展,取得了很大的进步。 从草根走向专业,从弱小走向规模,从分散走向统一,从杂乱走向规范。 本文主要重心放在了几年来咚咚架构演进的过程,技术架构单独拿出来看我认为没有绝对的好与不好, 技术架构总是要放在彼时的背景下来看,要考虑业务的时效价值、团队的规模和能力、环境基础设施等等方面。 架构演进的生命周期适时匹配好业务的生命周期,才可能发挥最好的效果。
分享阅读原文:http://www.cnblogs.com/mindwind/p/5017591.html 

蘑菇街运维体系及双十一关键技术分享

大数据/云计算being 发表了文章 • 0 个评论 • 1672 次浏览 • 2016-05-22 00:49 • 来自相关话题

关于蘑菇街:
中国最大的女性时尚社交电商平台。成立于2011年,总部位于浙江杭州, 目前(2015.Q3)拥有1.3亿注册用户,双十一日UV超2000万。2015.11.21日宣布完成D轮融资,并实施"一街双城"战略,杭州+北京,杭 州偏电商方向,北京偏社交媒体方向。 




蘑菇街业务架构-导购期(2011-2012)








运维早期情况 
早期阶段(2011-2012年)
      – 两位数机器、个位数网络设备
      – 没有运维,开发即运维,靠牛逼的脚本和一些开源工具搞定 
蘑菇街业务架构-转型期(2013)








运维的发展 
中间阶段(2013年-2014年)
           – 三位数服务器、两位数网络设备
           – 2-3名专职运维同学(主机&网络&DB&缓存&......) – 问题响应式的工作方式
– 工具化的运维平台
[]机器资源管理(CMDB的雏形)[/][] PHP发布系统[/][] 从指标维度监控系统(主机、QPS、RT、调用次数.... ) [/]
蘑菇街业务架构-社会化电商












我们应该怎么做 ​
思路:
[]建立以应用服务为核心的管理标准体系[/][]打造CMDB、流程申请、持续集成和监控为一体的自动化运维系统, 而不是孤立的单点系统[/][]把运维能力服务化(API),使运维的能力无处不在 [/]




关于应用服务管理 ​




案例介绍
让我们看一个从服务器管理—申请—代码发布—线上监控的案例 
关于应用服务器-Hestia服务和资源管理
[]从业务的维度来管理主机-CMDB的核心概念[/][]支持扩容、上下线、设备保障、权限等常规流程申请 [/]
[]自动化任务的配置和下发 [/]




关于应用服务管理-Mops流程申请系统




关于应用服务管理-发布系统
以trade_ordership_service为标示,进行代码发布 




关于应用服务管理-监控系统Sentry
通用+自定义监控,运维+开发可以时刻关注自己的服务状态和质量




运维的现状 ​
专业的运维团队 – 系统运维
– 应用运维 – DBA
– 运维开发

• 运维的能力向平台化和服务化发展(DevOps,依赖于能力而不是人) – CMDB服务化平台
– PHP+Java持续集成发布平台
– 统一的监控平台
– 全链路服务质量分析平台 – 稳定性平台
– 容量评估平台(待做)

• 工作方式的改变
– 从问题响应式,向整体解决方案提供方向发展 
双11技术保障,运维做了什么?




双11关键技术分享—全链路系统 
全链路背景
[]复杂的分布式系统,页面上的一次链接点击,在后端 可能会产生几十次的RPC调用,Web、服务化、缓存、 消息、DB.......都有可能涉及,如果出了问题,如何快 速定位到故障点要扩容,如何合理评估[/][]关键概念,全局唯一的TraceId [/]
全链路技术架构 




全链路应用-快速发现问题点和瓶颈点




全链路应用-调用合理性分析 
没有明显的瓶颈点,每一次调用RT也很正常,但是全链整体的RT却很高, 问题又出在哪里了呢? 








全链路使用后的收益和后续
使用全链路后的收益
– 提升问题的定位效率 – 准确的评估容量
 
后续
– Mogu-Watch,与前端打通,实现用户全链路的分析 – 压测做到平时,与容量评估平台和资源分配打通
– 引入云资源弹性扩容,避免应对峰值的批量机器采购 
压测之后,关键技术改造-ATS静态化方案
静态化方案背景和简介
– 主链路(首页-详情&活动-交易-支付),降低RT,提升容量

– 资源类的如图片、CSS、JS等的静态化方案都会采用CDN技术

– 对于页面内容类的数据,如商品名称、商品详情等都属于静态数据,而 商品的库存、优惠等则需要获取动态结果

– 对于活动页面、H5活动推广页面等,则可以完全静态化 




ATS(Apache Traffic Server)静态化技术方案-Cheetah 




ATS静态化案例-商品详情页 ​




ATS静态化使用后的收益和后续 ​
• 使用静态化后的收益 
–  详情页(全站流量的30%+)静态化在双11期间的命中率达到95%,换言之,减少了后端服务接近30%的流量压力
–  RT从原来200ms降低到50ms,用户体验大大提升
–  容量提升,减少了后端服务器的数量

• 后续
– 借助云资源搭建云上的ATS,更贴近用户 – ATS Cluster方案
– 支持HTTPS
– 回源流控和容灾控制 
限流&降级开关推送和WEB应急扩容方案
• 限流&降级开关
– 限流,Web层,防止被流量打垮
– 降级,App层(服务化),保障核心应用

• Web应急扩容方案
– 选择Docker 容器,批量生成效率高 – 启动速度快
– 资源利用率提升明显  查看全部
关于蘑菇街:
中国最大的女性时尚社交电商平台。成立于2011年,总部位于浙江杭州, 目前(2015.Q3)拥有1.3亿注册用户,双十一日UV超2000万。2015.11.21日宣布完成D轮融资,并实施"一街双城"战略,杭州+北京,杭 州偏电商方向,北京偏社交媒体方向。 
mogujie.png

蘑菇街业务架构-导购期(2011-2012)
dgq.png

dgq2.png

运维早期情况 
早期阶段(2011-2012年)
      – 两位数机器、个位数网络设备
      – 没有运维,开发即运维,靠牛逼的脚本和一些开源工具搞定 
蘑菇街业务架构-转型期(2013)
zxq.png

zxq2.png

运维的发展 
中间阶段(2013年-2014年)
           – 三位数服务器、两位数网络设备
           – 2-3名专职运维同学(主机&网络&DB&缓存&......) – 问题响应式的工作方式
– 工具化的运维平台
    []机器资源管理(CMDB的雏形)[/][] PHP发布系统[/][] 从指标维度监控系统(主机、QPS、RT、调用次数.... ) [/]

蘑菇街业务架构-社会化电商
ds.png

ds2.png

pro.png

我们应该怎么做 ​
思路:
    []建立以应用服务为核心的管理标准体系[/][]打造CMDB、流程申请、持续集成和监控为一体的自动化运维系统, 而不是孤立的单点系统[/][]把运维能力服务化(API),使运维的能力无处不在 [/]

cmdb.png

关于应用服务管理 ​
appserver.png

案例介绍
让我们看一个从服务器管理—申请—代码发布—线上监控的案例 
关于应用服务器-Hestia服务和资源管理
    []从业务的维度来管理主机-CMDB的核心概念[/][]支持扩容、上下线、设备保障、权限等常规流程申请 [/]

    []自动化任务的配置和下发 [/]

hestia.png

关于应用服务管理-Mops流程申请系统
Mops.png

关于应用服务管理-发布系统
以trade_ordership_service为标示,进行代码发布 
fb.png

关于应用服务管理-监控系统Sentry
通用+自定义监控,运维+开发可以时刻关注自己的服务状态和质量
sentry.png

运维的现状 ​
专业的运维团队 – 系统运维
– 应用运维 – DBA
– 运维开发

• 运维的能力向平台化和服务化发展(DevOps,依赖于能力而不是人) – CMDB服务化平台
– PHP+Java持续集成发布平台
– 统一的监控平台
– 全链路服务质量分析平台 – 稳定性平台
– 容量评估平台(待做)

• 工作方式的改变
– 从问题响应式,向整体解决方案提供方向发展 
双11技术保障,运维做了什么?
s11.png

双11关键技术分享—全链路系统 
全链路背景
    []复杂的分布式系统,页面上的一次链接点击,在后端 可能会产生几十次的RPC调用,Web、服务化、缓存、 消息、DB.......都有可能涉及,如果出了问题,如何快 速定位到故障点要扩容,如何合理评估[/][]关键概念,全局唯一的TraceId [/]

全链路技术架构 
qll.png

全链路应用-快速发现问题点和瓶颈点
wtd.png

全链路应用-调用合理性分析 
没有明显的瓶颈点,每一次调用RT也很正常,但是全链整体的RT却很高, 问题又出在哪里了呢? 
hlx.png

jiazhi.png

全链路使用后的收益和后续
使用全链路后的收益
– 提升问题的定位效率 – 准确的评估容量
 
后续
– Mogu-Watch,与前端打通,实现用户全链路的分析 – 压测做到平时,与容量评估平台和资源分配打通
– 引入云资源弹性扩容,避免应对峰值的批量机器采购 
压测之后,关键技术改造-ATS静态化方案
静态化方案背景和简介
– 主链路(首页-详情&活动-交易-支付),降低RT,提升容量

– 资源类的如图片、CSS、JS等的静态化方案都会采用CDN技术

– 对于页面内容类的数据,如商品名称、商品详情等都属于静态数据,而 商品的库存、优惠等则需要获取动态结果

– 对于活动页面、H5活动推广页面等,则可以完全静态化 
ATS.png

ATS(Apache Traffic Server)静态化技术方案-Cheetah 
cheetah.png

ATS静态化案例-商品详情页 ​
atsjh.png

ATS静态化使用后的收益和后续 ​
• 使用静态化后的收益 
–  详情页(全站流量的30%+)静态化在双11期间的命中率达到95%,换言之,减少了后端服务接近30%的流量压力
–  RT从原来200ms降低到50ms,用户体验大大提升
–  容量提升,减少了后端服务器的数量

• 后续
– 借助云资源搭建云上的ATS,更贴近用户 – ATS Cluster方案
– 支持HTTPS
– 回源流控和容灾控制 
限流&降级开关推送和WEB应急扩容方案
• 限流&降级开关
– 限流,Web层,防止被流量打垮
– 降级,App层(服务化),保障核心应用

• Web应急扩容方案
– 选择Docker 容器,批量生成效率高 – 启动速度快
– 资源利用率提升明显 

跨境电商Crazysales的高稳定性架构实践

运维技术cloudwise 发表了文章 • 0 个评论 • 1306 次浏览 • 2016-05-13 11:55 • 来自相关话题

Crazysales是一家典型的跨境电商企业,以澳洲和英国作为主要目标市场,产品大多数由国内供应商提供。Crazysales不但是Amazon、eBay等大型电商平台上的大卖家,同时在澳洲、新西兰建设有自营电商网站,为广大用户提供完整的网购服务。 
 






由于涉及跨国网络部署,不可避免地需要穿过“万里长城”,因此应用架构相对普通电商网站更加复杂,管理成本也自然提升,如何能够及时了解分布在中国、澳洲、英国等地不同业务系统的运行状态,是运维部门最关心的工作。

跨境电商的典型IT架构

Crazysales的核心业务系统及网店系统均搭建在Amazon的AWS平台之上,用Amazon CloudFront进行前端内容分发,而后端的数据维护平台因为供应商在国内,所以也在国内。 系统架构如下图:






目前,我们应用的技术都不是“高大上”的新技术,但稳定性得到很好的保证: 1.传统的PHP+LINUX+MYSQL,辅助数据的统计和分析应用mongoDB , 搜索引擎基于Solr。 系统架构做到前后低耦合,前端网站强依赖数据库转变成弱依赖。 2.MYSQL部署了两台slave 和定时静态备份数据,确保数据库的异地备份,和读写分离,为以后的无限扩展搭好基础。 3.通过每个应用层的监控,及时发现系统的瓶颈,针对性地优化。 整套系统都是我们团队经过多年合作开发逐步建立和维护的,所以很难保证统一的代码风格和代码水平,那是可遇不可求的。因此,必须建立合理的监控体系及时发现项目管理的漏洞、测试的漏洞、线上的性能瓶颈,这都让运维的工作在整个系统生命周期里更重要,这也是时下运维开发工程师的工作核心。

跨境电商的最佳监控解决方案

因为使用了Amazon的云服务,所以我们运维工程师不必花费大量时间维护基础硬件设施,而有更多的时间和精力来研究和优化我们的业务系统,其中监控体系是令我们为之骄傲的一部分。 






我们的自建监控系统能够及时、准确的发现部署在AWS上和国内的各个业务系统的运行状况,但对于通过CloudFront分发出去的前端内容,以及主要分布于英国、澳大利亚、新西兰等不同国家的用户的访问体验,则是自建监控系统很难准确感知的。另外我们的开发和运维团队主要在国内,因此需要一款既能准确感知海外用户访问Crazysales网站情况,又能通过手机短信、微信等手段给国内技术团队提供准确告警消息的监控工具。经过多方测试,我们最终采用云智慧的监控宝网站监控和网页性能监控功能,负责网站从CDN到前端浏览器环节的可用性监控。  





 
各个层级设不同的监控点

红色部分使用监控宝的监控系统,绿色是监控宝和自建监控系统混合使用 这是我们目前实施的监控架构: 通过脚本/自建监控系统 / 外部监控点(模拟真实客户访问) 多种实时监控数据来监测业务系统的运作状态,根据不同系统的特性来调整数据采样的频率,多维度的监控和及时的告警信息让维护人员及时知道系统的运作情况,保障系统的正常运作和提高异常处理的及时性,最终实现故障出现前预防和故障出现后及时解决的效果。 例如,我们的内部监控系统发现数据库在凌晨4点会出现服务很忙,同时监控宝监控数据显示前台出现等待时间过长(>10s),通过和我们的后台任务调度系统的运行时间进行对比,发现一个JOB需要大量SQL查询,导致数据库CPU占用过多,因此及时调整SQL的查询指向其它Slave,同时优化该SQL。 如下图,马上就看到优化后的效果了:  






监控宝遍布全球的分布式监测点能够模拟真实客户访问,及时了解客户遇到的问题,避免IT团队无法取到第一手材料导致丢失重现系统故障的机会,这是我们设置外部监控点的原因。如果自己购买服务器和节点进行部署的话,维护成本很高,也不专业。监控宝基于SaaS的服务和收费模式,很好的解决了成本和维护的问题,帮助我们掌握在澳洲,英国,中国大陆等地的访问速度,可用性等数据。 监控宝模拟客户端在各个监测点的数据采样频率最高可达到5分钟每次,不但能在第一时间发现故障并给予告警,而且能帮助我们掌握Web页面的性能表现,让开发人员可以针对性进行页面优化。而监控宝在全球范围内不断地增加的监测点数量,也和我们公司不断拓展英语国家业务的发展思路不谋而合。 最后说一下告警方式,众所周知,告警是监控的最后一步,大部分监控平台使用的是邮件和短信告警,但现在最流行的社交应用是微信,也是我们现在用得最多和最及时的平台。因此,我们将多种收集数据的介质通过监控宝转化到微信进行提示,基本上能做到故障发生半分钟内运维同事作出反应。 查看全部
Crazysales是一家典型的跨境电商企业,以澳洲和英国作为主要目标市场,产品大多数由国内供应商提供。Crazysales不但是Amazon、eBay等大型电商平台上的大卖家,同时在澳洲、新西兰建设有自营电商网站,为广大用户提供完整的网购服务。 
 
1.png



由于涉及跨国网络部署,不可避免地需要穿过“万里长城”,因此应用架构相对普通电商网站更加复杂,管理成本也自然提升,如何能够及时了解分布在中国、澳洲、英国等地不同业务系统的运行状态,是运维部门最关心的工作。

跨境电商的典型IT架构

Crazysales的核心业务系统及网店系统均搭建在Amazon的AWS平台之上,用Amazon CloudFront进行前端内容分发,而后端的数据维护平台因为供应商在国内,所以也在国内。 系统架构如下图:

2.png


目前,我们应用的技术都不是“高大上”的新技术,但稳定性得到很好的保证: 1.传统的PHP+LINUX+MYSQL,辅助数据的统计和分析应用mongoDB , 搜索引擎基于Solr。 系统架构做到前后低耦合,前端网站强依赖数据库转变成弱依赖。 2.MYSQL部署了两台slave 和定时静态备份数据,确保数据库的异地备份,和读写分离,为以后的无限扩展搭好基础。 3.通过每个应用层的监控,及时发现系统的瓶颈,针对性地优化。 整套系统都是我们团队经过多年合作开发逐步建立和维护的,所以很难保证统一的代码风格和代码水平,那是可遇不可求的。因此,必须建立合理的监控体系及时发现项目管理的漏洞、测试的漏洞、线上的性能瓶颈,这都让运维的工作在整个系统生命周期里更重要,这也是时下运维开发工程师的工作核心。

跨境电商的最佳监控解决方案

因为使用了Amazon的云服务,所以我们运维工程师不必花费大量时间维护基础硬件设施,而有更多的时间和精力来研究和优化我们的业务系统,其中监控体系是令我们为之骄傲的一部分。 

3.png


我们的自建监控系统能够及时、准确的发现部署在AWS上和国内的各个业务系统的运行状况,但对于通过CloudFront分发出去的前端内容,以及主要分布于英国、澳大利亚、新西兰等不同国家的用户的访问体验,则是自建监控系统很难准确感知的。另外我们的开发和运维团队主要在国内,因此需要一款既能准确感知海外用户访问Crazysales网站情况,又能通过手机短信、微信等手段给国内技术团队提供准确告警消息的监控工具。经过多方测试,我们最终采用云智慧的监控宝网站监控和网页性能监控功能,负责网站从CDN到前端浏览器环节的可用性监控。  

4.png

 
各个层级设不同的监控点

红色部分使用监控宝的监控系统,绿色是监控宝和自建监控系统混合使用 这是我们目前实施的监控架构: 通过脚本/自建监控系统 / 外部监控点(模拟真实客户访问) 多种实时监控数据来监测业务系统的运作状态,根据不同系统的特性来调整数据采样的频率,多维度的监控和及时的告警信息让维护人员及时知道系统的运作情况,保障系统的正常运作和提高异常处理的及时性,最终实现故障出现前预防和故障出现后及时解决的效果。 例如,我们的内部监控系统发现数据库在凌晨4点会出现服务很忙,同时监控宝监控数据显示前台出现等待时间过长(>10s),通过和我们的后台任务调度系统的运行时间进行对比,发现一个JOB需要大量SQL查询,导致数据库CPU占用过多,因此及时调整SQL的查询指向其它Slave,同时优化该SQL。 如下图,马上就看到优化后的效果了:  

5.png


监控宝遍布全球的分布式监测点能够模拟真实客户访问,及时了解客户遇到的问题,避免IT团队无法取到第一手材料导致丢失重现系统故障的机会,这是我们设置外部监控点的原因。如果自己购买服务器和节点进行部署的话,维护成本很高,也不专业。监控宝基于SaaS的服务和收费模式,很好的解决了成本和维护的问题,帮助我们掌握在澳洲,英国,中国大陆等地的访问速度,可用性等数据。 监控宝模拟客户端在各个监测点的数据采样频率最高可达到5分钟每次,不但能在第一时间发现故障并给予告警,而且能帮助我们掌握Web页面的性能表现,让开发人员可以针对性进行页面优化。而监控宝在全球范围内不断地增加的监测点数量,也和我们公司不断拓展英语国家业务的发展思路不谋而合。 最后说一下告警方式,众所周知,告警是监控的最后一步,大部分监控平台使用的是邮件和短信告警,但现在最流行的社交应用是微信,也是我们现在用得最多和最及时的平台。因此,我们将多种收集数据的介质通过监控宝转化到微信进行提示,基本上能做到故障发生半分钟内运维同事作出反应。

Nginx+Keepalived实现网站高可用方案

运维技术push 发表了文章 • 0 个评论 • 2583 次浏览 • 2015-10-31 17:00 • 来自相关话题

公司内部 OA 系统要做线上高可用,避免单点故障,所以计划使用2台虚拟机通过 Keepalived 工具来实现 nginx 的高可用(High Avaiability),达到一台nginx入口服务器宕机,另一台备机自动接管服务的效果。
 1. Keepalived介绍Keepalived是一个基于VRRP协议来实现的服务高可用方案,可以利用其来避免IP单点故障,类似的工具还有heartbeat、corosync、pacemaker。但是它一般不会单独出现,而是与其它负载均衡技术(如lvs、haproxy、nginx)一起工作来达到集群的高可用。

1.1 VRRP协议

VRRP全称 Virtual Router Redundancy Protocol,即 虚拟路由冗余协议。可以认为它是实现路由器高可用的容错协议,即将N台提供相同功能的路由器组成一个路由器组(Router Group),这个组里面有一个master和多个backup,但在外界看来就像一台一样,构成虚拟路由器,拥有一个虚拟IP(vip,也就是路由器所在局域网内其他机器的默认路由),占有这个IP的master实际负责ARP相应和转发IP数据包,组中的其它路由器作为备份的角色处于待命状态。master会发组播消息,当backup在超时时间内收不到vrrp包时就认为master宕掉了,这时就需要根据VRRP的优先级来选举一个backup当master,保证路由器的高可用。
 
在VRRP协议实现里,虚拟路由器使用 00-00-5E-00-01-XX 作为虚拟MAC地址,XX就是唯一的 VRID (Virtual Router IDentifier),这个地址同一时间只有一个物理路由器占用。在虚拟路由器里面的物理路由器组里面通过多播IP地址 224.0.0.18 来定时发送通告消息。每个Router都有一个 1-255 之间的优先级别,级别最高的(highest priority)将成为主控(master)路由器。通过降低master的优先权可以让处于backup状态的路由器抢占(pro-empt)主路由器的状态,两个backup优先级相同的IP地址较大者为master,接管虚拟IP。




与heartbeat/corosync等比较:Heartbeat、Corosync、Keepalived这三个集群组件我们到底选哪个好,首先我想说明的是,Heartbeat、Corosync是属于同一类型,Keepalived与Heartbeat、Corosync,根本不是同一类型的。Keepalived使用的vrrp协议方式,虚拟路由冗余协议 (Virtual Router Redundancy Protocol,简称VRRP);Heartbeat或Corosync是基于主机或网络服务的高可用方式;简单的说就是,Keepalived的目的是模拟路由器的高可用,Heartbeat或Corosync的目的是实现Service的高可用。

所以一般Keepalived是实现前端高可用,常用的前端高可用的组合有,就是我们常见的LVS+Keepalived、Nginx+Keepalived、HAproxy+Keepalived。而Heartbeat或Corosync是实现服务的高可用,常见的组合有Heartbeat v3(Corosync)+Pacemaker+NFS+Httpd 实现Web服务器的高可用、Heartbeat v3(Corosync)+Pacemaker+NFS+MySQL 实现MySQL服务器的高可用。总结一下,Keepalived中实现轻量级的高可用,一般用于前端高可用,且不需要共享存储,一般常用于两个节点的高可用。而Heartbeat(或Corosync)一般用于服务的高可用,且需要共享存储,一般用于多节点的高可用。这个问题我们说明白了。

又有博友会问了,那heartbaet与corosync我们又应该选择哪个好啊,我想说我们一般用corosync,因为corosync的运行机制更优于heartbeat,就连从heartbeat分离出来的pacemaker都说在以后的开发当中更倾向于corosync,所以现在corosync+pacemaker是最佳组合。

1.2 Keepalived + nginx

keepalived可以认为是VRRP协议在Linux上的实现,主要有三个模块,分别是core、check和vrrp。core模块为keepalived的核心,负责主进程的启动、维护以及全局配置文件的加载和解析。check负责健康检查,包括常见的各种检查方式。vrrp模块是来实现VRRP协议的。本文基于如下的拓扑图: +-------------+
| uplink |
+-------------+
|
+
MASTER keep|alived BACKUP
172.29.88.224 172.29.88.222 172.29.88.225
+-------------+ +-------------+ +-------------+
| nginx01 |----| virtualIP |----| nginx02 |
+-------------+ +-------------+ +-------------+
|
+------------------+------------------+
| | |
+-------------+ +-------------+ +-------------+
| web01 | | web02 | | web03 |
+-------------+ +-------------+ +-------------+2. keepalived实现nginx高可用

2.1安装

我的环境是CentOS 6.2 X86_64,直接通过yum方式安装最简单:# yum install -y keepalived
# keepalived -v
Keepalived v1.2.13 (03/19,2015)

2.2 nginx监控脚本

该脚本检测ngnix的运行状态,并在nginx进程不存在时尝试重新启动ngnix,如果启动失败则停止keepalived,准备让其它机器接管。/etc/keepalived/check_nginx.sh :#!/bin/bash
counter=$(ps -C nginx --no-heading|wc -l)
if [ "${counter}" = "0" ]; then
/usr/local/bin/nginx
sleep 2
counter=$(ps -C nginx --no-heading|wc -l)
if [ "${counter}" = "0" ]; then
/etc/init.d/keepalived stop
fi
fi你也可以根据自己的业务需求,总结出在什么情形下关闭keepalived,如 curl 主页连续2个5s没有响应则切换:#!/bin/bash
# curl -IL http://localhost/member/login.htm
# curl --data "memberName=fengkan&password=22" http://localhost/member/login.htm

count = 0
for (( k=0; k<2; k++ ))
do
check_code=$( curl --connect-timeout 3 -sL -w "%{http_code}\\n" http://localhost/login.html -o /dev/null )
if [ "$check_code" != "200" ]; then
count = count +1
continue
else
count = 0
break
fi
done
if [ "$count" != "0" ]; then
# /etc/init.d/keepalived stop
exit 1
else
exit 0
fi

2.3 keepalived.conf

! Configuration File for keepalived
global_defs {
notification_email {
zhouxiao@example.com
itsection@example.com
}
notification_email_from itsection@example.com
smtp_server mail.example.com
smtp_connect_timeout 30
router_id LVS_DEVEL
}

vrrp_script chk_nginx {
# script "killall -0 nginx"
script "/etc/keepalived/check_nginx.sh"
interval 2
weight -5
fall 3
rise 2
}

vrrp_instance VI_1 {
state MASTER
interface eth0
mcast_src_ip 172.29.88.224
virtual_router_id 51
priority 101
advert_int 2
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.29.88.222
}
track_script {
chk_nginx
}
}在其它备机BACKUP上,只需要改变 state MASTER -> state BACKUP,priority 101 -> priority 100,mcast_src_ip 172.29.88.224 -> mcast_src_ip 172.29.88.225即可。# service keepalived restart

2.4 配置选项说明

global_defs
[]notification_email : keepalived在发生诸如切换操作时需要发送email通知地址,后面的 smtp_server 相比也都知道是邮件服务器地址。也可以通过其它方式报警,毕竟邮件不是实时通知的。[/][]router_id : 机器标识,通常可设为hostname。故障发生时,邮件通知会用到[/]

vrrp_instance
[]state : 指定instance(Initial)的初始状态,就是说在配置好后,这台服务器的初始状态就是这里指定的,但这里指定的不算,还是得要通过竞选通过优先级来确定。如果这里设置为MASTER,但如若他的优先级不及另外一台,那么这台在发送通告时,会发送自己的优先级,另外一台发现优先级不如自己的高,那么他会就回抢占为MASTER[/][]interface : 实例绑定的网卡,因为在配置虚拟IP的时候必须是在已有的网卡上添加的[/][]mcast_src_ip : 发送多播数据包时的源IP地址,这里注意了,这里实际上就是在那个地址上发送VRRP通告,这个非常重要,一定要选择稳定的网卡端口来发送,这里相当于heartbeat的心跳端口,如果没有设置那么就用默认的绑定的网卡的IP,也就是interface指定的IP地址[/][]virtual_router_id : 这里设置VRID,这里非常重要,相同的VRID为一个组,他将决定多播的MAC地址[/][]priority : 设置本节点的优先级,优先级高的为master[/][]advert_int : 检查间隔,默认为1秒。这就是VRRP的定时器,MASTER每隔这样一个时间间隔,就会发送一个advertisement报文以通知组内其他路由器自己工作正常[/][]authentication : 定义认证方式和密码,主从必须一样[/][]virtual_ipaddress : 这里设置的就是VIP,也就是虚拟IP地址,他随着state的变化而增加删除,当state为master的时候就添加,当state为backup的时候删除,这里主要是有优先级来决定的,和state设置的值没有多大关系,这里可以设置多个IP地址[/][]track_script : 引用VRRP脚本,即在 vrrp_script 部分指定的名字。定期运行它们来改变优先级,并最终引发主备切换。[/]

vrrp_script
告诉 keepalived 在什么情况下切换,所以尤为重要。可以有多个 vrrp_script
[]script : 自己写的检测脚本。也可以是一行命令如killall -0 nginx[/][]interval 2 : 每2s检测一次[/][]weight -5 : 检测失败(脚本返回非0)则优先级 -5[/][]fall 2 : 检测连续 2 次失败才算确定是真失败。会用weight减少优先级(1-255之间)[/][]rise 1 : 检测 1 次成功就算成功。但不修改优先级[/]
 
这里要提示一下script一般有2种写法:
[]通过脚本执行的返回结果,改变优先级,keepalived继续发送通告消息,backup比较优先级再决定[/][]脚本里面检测到异常,直接关闭keepalived进程,backup机器接收不到advertisement会抢占IP[/]
 
上文 vrrp_script 配置部分,killall -0 nginx属于第1种情况,/etc/keepalived/check_nginx.sh属于第2种情况(脚本中关闭keepalived)。个人更倾向于通过shell脚本判断,但有异常时exit 1,正常退出exit 0,然后keepalived根据动态调整的 vrrp_instance 优先级选举决定是否抢占VIP:
[]如果脚本执行结果为0,并且weight配置的值大于0,则优先级相应的增加[/][]如果脚本执行结果非0,并且weight配置的值小于0,则优先级相应的减少[/]
其他情况,原本配置的优先级不变,即配置文件中priority对应的值。
提示:
[]优先级不会不断的提高或者降低[/][]可以编写多个检测脚本并为每个检测脚本设置不同的weight(在配置中列出就行)[/][]不管提高优先级还是降低优先级,最终优先级的范围是在[1,254],不会出现优先级小于等于0或者优先级大于等于255的情况[/][]在MASTER节点的 vrrp_instance 中 配置 nopreempt ,当它异常恢复后,即使它 prio 更高也不会抢占,这样可以避免正常情况下做无谓的切换[/]
以上可以做到利用脚本检测业务进程的状态,并动态调整优先级从而实现主备切换。
 
配置结束
在默认的keepalive.conf里面还有 virtual_server,real_server 这样的配置,我们这用不到,它是为lvs准备的。 notify 可以定义在切换成MASTER或BACKUP时执行的脚本,如有需求请自行google。

2.5 nginx配置

当然nginx没有什么可配置的,因为它与keepalived并没有联系。但记住,2台nginx服务器上的配置应该是完全一样的(rsync同步),这样才能做到对用户透明,nginx.conf 里面的 server_name 尽量使用域名来代替,然后dns解析这个域名到虚拟IP 172.29.88.222。
更多关于nginx内容配置请参考 这里

测试
根据上面的配置,初始化状态:172.29.88.224 (itoatest1,MASTER,101),172.29.88.222(itoatest2,BACKUP,100),nginx和keepalived都启动,虚拟IP 172.29.88.222 在 itoatest1 上:# 使用ip命令配置的地址,ifconfig查看不了
[root@itoatest1 nginx-1.6]# ip a|grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 172.29.88.224/24 brd 172.29.88.255 scope global eth0
inet 172.29.88.222/32 scope global eth0直接关闭 itoatest1 上的nginx:/usr/local/nginx-1.6/sbin/nginx -s stop:[root@localhost keepalived]# ip a|grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 172.29.88.224/24 brd 172.29.88.255 scope global eth0vip消失,漂移到 itoatest2:




同时可以看到两台服务器上 /var/log/messages:[size=16] itoatest1[/size]
Jun 5 16:44:01 itoatest1 Keepalived_vrrp[44875]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.29.88.222
Jun 5 16:44:06 itoatest1 Keepalived_vrrp[44875]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.29.88.222
Jun 5 16:44:46 itoatest1 Keepalived_vrrp[44875]: VRRP_Script(chk_nginx) failed
Jun 5 16:44:48 itoatest1 Keepalived_vrrp[44875]: VRRP_Instance(VI_1) Received higher prio advert
Jun 5 16:44:48 itoatest1 Keepalived_vrrp[44875]: VRRP_Instance(VI_1) Entering BACKUP STATE
Jun 5 16:44:48 itoatest1 Keepalived_vrrp[44875]: VRRP_Instance(VI_1) removing protocol VIPs.
Jun 5 16:44:48 itoatest1 Keepalived_healthcheckers[44874]: Netlink reflector reports IP 172.29.88.222 removed

[size=16] itoatest2[/size]
Jun 5 16:44:00 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Transition to MASTER STATE
Jun 5 16:44:00 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Received higher prio advert
Jun 5 16:44:00 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Entering BACKUP STATE
Jun 5 16:44:48 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) forcing a new MASTER election
Jun 5 16:44:48 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) forcing a new MASTER election
Jun 5 16:44:49 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Transition to MASTER STATE
Jun 5 16:44:50 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Entering MASTER STATE
Jun 5 16:44:50 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) setting protocol VIPs.
Jun 5 16:44:50 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.29.88.222
Jun 5 16:44:50 itoatest2 Keepalived_healthcheckers[35554]: Netlink reflector reports IP 172.29.88.222 added
Jun 5 16:44:55 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.29.88.222

你也可以通过在两台服务器上抓包来查看 优先级priority 的变化:[size=16] itoatest1 上[/size]
[size=16] 直接输出,或后加 -w itoatest-kl.cap存入文件用wireshark查看[/size]
# tcpdump -vvv -n -i eth0 dst 224.0.0.18 and src 172.29.88.224



参考
使用Keepalived实现Nginx高可用性
High Availability Support Based on keepalived
nginx+keepalived实现双机热备的高可用
LVS原理详解及部署之五:LVS+keepalived实现负载均衡&高可用
Keepalived双主模型中vrrp_script中权重改变故障排查
虚拟路由器冗余协议【原理篇】VRRP详解
Keepalived原理与实战精讲
原文分享地址:http://seanlook.com/2015/05/18/nginx-keepalived-ha/ 查看全部
公司内部 OA 系统要做线上高可用,避免单点故障,所以计划使用2台虚拟机通过 Keepalived 工具来实现 nginx 的高可用(High Avaiability),达到一台nginx入口服务器宕机,另一台备机自动接管服务的效果。
 1. Keepalived介绍
Keepalived是一个基于VRRP协议来实现的服务高可用方案,可以利用其来避免IP单点故障,类似的工具还有heartbeat、corosync、pacemaker。但是它一般不会单独出现,而是与其它负载均衡技术(如lvs、haproxy、nginx)一起工作来达到集群的高可用。


1.1 VRRP协议


VRRP全称 Virtual Router Redundancy Protocol,即 虚拟路由冗余协议。可以认为它是实现路由器高可用的容错协议,即将N台提供相同功能的路由器组成一个路由器组(Router Group),这个组里面有一个master和多个backup,但在外界看来就像一台一样,构成虚拟路由器,拥有一个虚拟IP(vip,也就是路由器所在局域网内其他机器的默认路由),占有这个IP的master实际负责ARP相应和转发IP数据包,组中的其它路由器作为备份的角色处于待命状态。master会发组播消息,当backup在超时时间内收不到vrrp包时就认为master宕掉了,这时就需要根据VRRP的优先级来选举一个backup当master,保证路由器的高可用。
 
在VRRP协议实现里,虚拟路由器使用 00-00-5E-00-01-XX 作为虚拟MAC地址,XX就是唯一的 VRID (Virtual Router IDentifier),这个地址同一时间只有一个物理路由器占用。在虚拟路由器里面的物理路由器组里面通过多播IP地址 224.0.0.18 来定时发送通告消息。每个Router都有一个 1-255 之间的优先级别,级别最高的(highest priority)将成为主控(master)路由器。通过降低master的优先权可以让处于backup状态的路由器抢占(pro-empt)主路由器的状态,两个backup优先级相同的IP地址较大者为master,接管虚拟IP。
nginx-keepalived-vrrp.jpg

与heartbeat/corosync等比较:
Heartbeat、Corosync、Keepalived这三个集群组件我们到底选哪个好,首先我想说明的是,Heartbeat、Corosync是属于同一类型,Keepalived与Heartbeat、Corosync,根本不是同一类型的。Keepalived使用的vrrp协议方式,虚拟路由冗余协议 (Virtual Router Redundancy Protocol,简称VRRP);Heartbeat或Corosync是基于主机或网络服务的高可用方式;简单的说就是,Keepalived的目的是模拟路由器的高可用,Heartbeat或Corosync的目的是实现Service的高可用。

所以一般Keepalived是实现前端高可用,常用的前端高可用的组合有,就是我们常见的LVS+Keepalived、Nginx+Keepalived、HAproxy+Keepalived。而Heartbeat或Corosync是实现服务的高可用,常见的组合有Heartbeat v3(Corosync)+Pacemaker+NFS+Httpd 实现Web服务器的高可用、Heartbeat v3(Corosync)+Pacemaker+NFS+MySQL 实现MySQL服务器的高可用。总结一下,Keepalived中实现轻量级的高可用,一般用于前端高可用,且不需要共享存储,一般常用于两个节点的高可用。而Heartbeat(或Corosync)一般用于服务的高可用,且需要共享存储,一般用于多节点的高可用。这个问题我们说明白了。

又有博友会问了,那heartbaet与corosync我们又应该选择哪个好啊,我想说我们一般用corosync,因为corosync的运行机制更优于heartbeat,就连从heartbeat分离出来的pacemaker都说在以后的开发当中更倾向于corosync,所以现在corosync+pacemaker是最佳组合。


1.2 Keepalived + nginx


keepalived可以认为是VRRP协议在Linux上的实现,主要有三个模块,分别是core、check和vrrp。core模块为keepalived的核心,负责主进程的启动、维护以及全局配置文件的加载和解析。check负责健康检查,包括常见的各种检查方式。vrrp模块是来实现VRRP协议的。本文基于如下的拓扑图:
                   +-------------+
| uplink |
+-------------+
|
+
MASTER keep|alived BACKUP
172.29.88.224 172.29.88.222 172.29.88.225
+-------------+ +-------------+ +-------------+
| nginx01 |----| virtualIP |----| nginx02 |
+-------------+ +-------------+ +-------------+
|
+------------------+------------------+
| | |
+-------------+ +-------------+ +-------------+
| web01 | | web02 | | web03 |
+-------------+ +-------------+ +-------------+
2. keepalived实现nginx高可用


2.1安装


我的环境是CentOS 6.2 X86_64,直接通过yum方式安装最简单:
# yum install -y keepalived
# keepalived -v
Keepalived v1.2.13 (03/19,2015)


2.2 nginx监控脚本


该脚本检测ngnix的运行状态,并在nginx进程不存在时尝试重新启动ngnix,如果启动失败则停止keepalived,准备让其它机器接管。
/etc/keepalived/check_nginx.sh :
#!/bin/bash
counter=$(ps -C nginx --no-heading|wc -l)
if [ "${counter}" = "0" ]; then
/usr/local/bin/nginx
sleep 2
counter=$(ps -C nginx --no-heading|wc -l)
if [ "${counter}" = "0" ]; then
/etc/init.d/keepalived stop
fi
fi
你也可以根据自己的业务需求,总结出在什么情形下关闭keepalived,如 curl 主页连续2个5s没有响应则切换:
#!/bin/bash
# curl -IL http://localhost/member/login.htm
# curl --data "memberName=fengkan&password=22" http://localhost/member/login.htm

count = 0
for (( k=0; k<2; k++ ))
do
check_code=$( curl --connect-timeout 3 -sL -w "%{http_code}\\n" http://localhost/login.html -o /dev/null )
if [ "$check_code" != "200" ]; then
count = count +1
continue
else
count = 0
break
fi
done
if [ "$count" != "0" ]; then
# /etc/init.d/keepalived stop
exit 1
else
exit 0
fi


2.3 keepalived.conf


! Configuration File for keepalived
global_defs {
notification_email {
zhouxiao@example.com
itsection@example.com
}
notification_email_from itsection@example.com
smtp_server mail.example.com
smtp_connect_timeout 30
router_id LVS_DEVEL
}

vrrp_script chk_nginx {
# script "killall -0 nginx"
script "/etc/keepalived/check_nginx.sh"
interval 2
weight -5
fall 3
rise 2
}

vrrp_instance VI_1 {
state MASTER
interface eth0
mcast_src_ip 172.29.88.224
virtual_router_id 51
priority 101
advert_int 2
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.29.88.222
}
track_script {
chk_nginx
}
}
在其它备机BACKUP上,只需要改变 state MASTER -> state BACKUP,priority 101 -> priority 100,mcast_src_ip 172.29.88.224 -> mcast_src_ip 172.29.88.225即可。
# service keepalived restart


2.4 配置选项说明


global_defs
    []notification_email : keepalived在发生诸如切换操作时需要发送email通知地址,后面的 smtp_server 相比也都知道是邮件服务器地址。也可以通过其它方式报警,毕竟邮件不是实时通知的。[/][]router_id : 机器标识,通常可设为hostname。故障发生时,邮件通知会用到[/]


vrrp_instance
    []state : 指定instance(Initial)的初始状态,就是说在配置好后,这台服务器的初始状态就是这里指定的,但这里指定的不算,还是得要通过竞选通过优先级来确定。如果这里设置为MASTER,但如若他的优先级不及另外一台,那么这台在发送通告时,会发送自己的优先级,另外一台发现优先级不如自己的高,那么他会就回抢占为MASTER[/][]interface : 实例绑定的网卡,因为在配置虚拟IP的时候必须是在已有的网卡上添加的[/][]mcast_src_ip : 发送多播数据包时的源IP地址,这里注意了,这里实际上就是在那个地址上发送VRRP通告,这个非常重要,一定要选择稳定的网卡端口来发送,这里相当于heartbeat的心跳端口,如果没有设置那么就用默认的绑定的网卡的IP,也就是interface指定的IP地址[/][]virtual_router_id : 这里设置VRID,这里非常重要,相同的VRID为一个组,他将决定多播的MAC地址[/][]priority : 设置本节点的优先级,优先级高的为master[/][]advert_int : 检查间隔,默认为1秒。这就是VRRP的定时器,MASTER每隔这样一个时间间隔,就会发送一个advertisement报文以通知组内其他路由器自己工作正常[/][]authentication : 定义认证方式和密码,主从必须一样[/][]virtual_ipaddress : 这里设置的就是VIP,也就是虚拟IP地址,他随着state的变化而增加删除,当state为master的时候就添加,当state为backup的时候删除,这里主要是有优先级来决定的,和state设置的值没有多大关系,这里可以设置多个IP地址[/][]track_script : 引用VRRP脚本,即在 vrrp_script 部分指定的名字。定期运行它们来改变优先级,并最终引发主备切换。[/]


vrrp_script
告诉 keepalived 在什么情况下切换,所以尤为重要。可以有多个 vrrp_script
    []script : 自己写的检测脚本。也可以是一行命令如killall -0 nginx[/][]interval 2 : 每2s检测一次[/][]weight -5 : 检测失败(脚本返回非0)则优先级 -5[/][]fall 2 : 检测连续 2 次失败才算确定是真失败。会用weight减少优先级(1-255之间)[/][]rise 1 : 检测 1 次成功就算成功。但不修改优先级[/]

 
这里要提示一下script一般有2种写法:
    []通过脚本执行的返回结果,改变优先级,keepalived继续发送通告消息,backup比较优先级再决定[/][]脚本里面检测到异常,直接关闭keepalived进程,backup机器接收不到advertisement会抢占IP[/]

 
上文 vrrp_script 配置部分,killall -0 nginx属于第1种情况,/etc/keepalived/check_nginx.sh属于第2种情况(脚本中关闭keepalived)。个人更倾向于通过shell脚本判断,但有异常时exit 1,正常退出exit 0,然后keepalived根据动态调整的 vrrp_instance 优先级选举决定是否抢占VIP:
    []如果脚本执行结果为0,并且weight配置的值大于0,则优先级相应的增加[/][]如果脚本执行结果非0,并且weight配置的值小于0,则优先级相应的减少[/]

其他情况,原本配置的优先级不变,即配置文件中priority对应的值。
提示:
    []优先级不会不断的提高或者降低[/][]可以编写多个检测脚本并为每个检测脚本设置不同的weight(在配置中列出就行)[/][]不管提高优先级还是降低优先级,最终优先级的范围是在[1,254],不会出现优先级小于等于0或者优先级大于等于255的情况[/][]在MASTER节点的 vrrp_instance 中 配置 nopreempt ,当它异常恢复后,即使它 prio 更高也不会抢占,这样可以避免正常情况下做无谓的切换[/]

以上可以做到利用脚本检测业务进程的状态,并动态调整优先级从而实现主备切换。
 
配置结束
在默认的keepalive.conf里面还有 virtual_server,real_server 这样的配置,我们这用不到,它是为lvs准备的。 notify 可以定义在切换成MASTER或BACKUP时执行的脚本,如有需求请自行google。


2.5 nginx配置


当然nginx没有什么可配置的,因为它与keepalived并没有联系。但记住,2台nginx服务器上的配置应该是完全一样的(rsync同步),这样才能做到对用户透明,nginx.conf 里面的 server_name 尽量使用域名来代替,然后dns解析这个域名到虚拟IP 172.29.88.222。
更多关于nginx内容配置请参考 这里


  1. 测试


根据上面的配置,初始化状态:172.29.88.224 (itoatest1,MASTER,101),172.29.88.222(itoatest2,BACKUP,100),nginx和keepalived都启动,虚拟IP 172.29.88.222 在 itoatest1 上:
# 使用ip命令配置的地址,ifconfig查看不了
[root@itoatest1 nginx-1.6]# ip a|grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 172.29.88.224/24 brd 172.29.88.255 scope global eth0
inet 172.29.88.222/32 scope global eth0
直接关闭 itoatest1 上的nginx:/usr/local/nginx-1.6/sbin/nginx -s stop:
[root@localhost keepalived]# ip a|grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 172.29.88.224/24 brd 172.29.88.255 scope global eth0
vip消失,漂移到 itoatest2:
nginx-keepalived-vip.png

同时可以看到两台服务器上 /var/log/messages:
[size=16] itoatest1[/size]
Jun 5 16:44:01 itoatest1 Keepalived_vrrp[44875]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.29.88.222
Jun 5 16:44:06 itoatest1 Keepalived_vrrp[44875]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.29.88.222
Jun 5 16:44:46 itoatest1 Keepalived_vrrp[44875]: VRRP_Script(chk_nginx) failed
Jun 5 16:44:48 itoatest1 Keepalived_vrrp[44875]: VRRP_Instance(VI_1) Received higher prio advert
Jun 5 16:44:48 itoatest1 Keepalived_vrrp[44875]: VRRP_Instance(VI_1) Entering BACKUP STATE
Jun 5 16:44:48 itoatest1 Keepalived_vrrp[44875]: VRRP_Instance(VI_1) removing protocol VIPs.
Jun 5 16:44:48 itoatest1 Keepalived_healthcheckers[44874]: Netlink reflector reports IP 172.29.88.222 removed

[size=16] itoatest2[/size]
Jun 5 16:44:00 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Transition to MASTER STATE
Jun 5 16:44:00 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Received higher prio advert
Jun 5 16:44:00 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Entering BACKUP STATE
Jun 5 16:44:48 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) forcing a new MASTER election
Jun 5 16:44:48 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) forcing a new MASTER election
Jun 5 16:44:49 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Transition to MASTER STATE
Jun 5 16:44:50 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Entering MASTER STATE
Jun 5 16:44:50 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) setting protocol VIPs.
Jun 5 16:44:50 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.29.88.222
Jun 5 16:44:50 itoatest2 Keepalived_healthcheckers[35554]: Netlink reflector reports IP 172.29.88.222 added
Jun 5 16:44:55 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.29.88.222

你也可以通过在两台服务器上抓包来查看 优先级priority 的变化:
[size=16] itoatest1 上[/size]
[size=16] 直接输出,或后加 -w itoatest-kl.cap存入文件用wireshark查看[/size]
# tcpdump -vvv -n -i eth0 dst 224.0.0.18 and src 172.29.88.224
nginx-keepalived-prio.png

参考
使用Keepalived实现Nginx高可用性
High Availability Support Based on keepalived
nginx+keepalived实现双机热备的高可用
LVS原理详解及部署之五:LVS+keepalived实现负载均衡&高可用
Keepalived双主模型中vrrp_script中权重改变故障排查
虚拟路由器冗余协议【原理篇】VRRP详解
Keepalived原理与实战精讲
原文分享地址:http://seanlook.com/2015/05/18/nginx-keepalived-ha/

京东咚咚架构演进

运维技术koyo 发表了文章 • 0 个评论 • 1348 次浏览 • 2016-08-24 22:26 • 来自相关话题

咚咚是什么?咚咚之于京东相当于旺旺之于淘宝,它们都是服务于买家和卖家的沟通。 自从京东开始为第三方卖家提供入驻平台服务后,咚咚也就随之诞生了。 我们首先看看它诞生之初是什么样的。
 

1.0 诞生(2010 - 2011)​

为了业务的快速上线,1.0 版本的技术架构实现是非常直接且简单粗暴的。 如何简单粗暴法?请看架构图,如下:




1.0 的功能十分简单,实现了一个 IM 的基本功能,接入、互通消息和状态。 另外还有客服功能,就是顾客接入咨询时的客服分配,按轮询方式把顾客分配给在线的客服接待。 用开源 Mina 框架实现了 TCP 的长连接接入,用 Tomcat Comet 机制实现了 HTTP 的长轮询服务。 而消息投递的实现是一端发送的消息临时存放在 Redis 中,另一端拉取的生产消费模型。

这个模型的做法导致需要以一种高频率的方式来轮询 Redis 遍历属于自己连接的关联会话消息。 这个模型很简单,简单包括多个层面的意思:理解起来简单;开发起来简单;部署起来也简单。 只需要一个 Tomcat 应用依赖一个共享的 Redis,简单的实现核心业务功能,并支持业务快速上线。

但这个简单的模型也有些严重的缺陷,主要是效率和扩展问题。 轮询的频率间隔大小基本决定了消息的延时,轮询越快延时越低,但轮询越快消耗也越高。 这个模型实际上是一个高功耗低效能的模型,因为不活跃的连接在那做高频率的无意义轮询。 高频有多高呢,基本在 100 ms 以内,你不能让轮询太慢,比如超过 2 秒轮一次,人就会在聊天过程中感受到明显的会话延迟。 随着在线人数增加,轮询的耗时也线性增长,因此这个模型导致了扩展能力和承载能力都不好,一定会随着在线人数的增长碰到性能瓶颈。

1.0 的时代背景正是京东技术平台从 .NET 向 Java 转型的年代,我也正是在这期间加入京东并参与了京东主站技术转型架构升级的过程。 之后开始接手了京东咚咚,并持续完善这个产品,进行了三次技术架构演进。
 

2.0 成长(2012)

我们刚接手时 1.0 已在线上运行并支持京东 POP(开放平台)业务,之后京东打算组建自营在线客服团队并落地在成都。 不管是自营还是 POP 客服咨询业务当时都起步不久,1.0 架构中的性能和效率缺陷问题还没有达到引爆的业务量级。 而自营客服当时还处于起步阶段,客服人数不足,服务能力不够,顾客咨询量远远超过客服的服务能力。 超出服务能力的顾客咨询,当时我们的系统统一返回提示客服繁忙,请稍后咨询。 这种状况导致高峰期大量顾客无论怎么刷新请求,都很可能无法接入客服,体验很差。 所以 2.0 重点放在了业务功能体验的提升上,如下图所示:




针对无法及时提供服务的顾客,可以排队或者留言。 针对纯文字沟通,提供了文件和图片等更丰富的表达方式。 另外支持了客服转接和快捷回复等方式来提升客服的接待效率。 总之,整个 2.0 就是围绕提升客服效率和用户体验。 而我们担心的效率问题在 2.0 高速发展业务的时期还没有出现,但业务量正在逐渐积累,我们知道它快要爆了。 到 2012 年末,度过双十一后开始了 3.0 的一次重大架构升级。
 

3.0 爆发(2013 - 2014)

经历了 2.0 时代一整年的业务高速发展,实际上代码规模膨胀的很快。 与代码一块膨胀的还有团队,从最初的 4 个人到近 30 人。 团队大了后,一个系统多人开发,开发人员层次不一,规范难统一,系统模块耦合重,改动沟通和依赖多,上线风险难以控制。 一个单独 tomcat 应用多实例部署模型终于走到头了,这个版本架构升级的主题就是服务化。

服务化的第一个问题如何把一个大的应用系统切分成子服务系统。 当时的背景是京东的部署还在半自动化年代,自动部署系统刚起步,子服务系统若按业务划分太细太多,部署工作量很大且难管理。 所以当时我们不是按业务功能分区服务的,而是按业务重要性级别划分了 0、1、2 三个级别不同的子业务服务系统。 另外就是独立了一组接入服务,针对不同渠道和通信方式的接入端,见下图。




更细化的应用服务和架构分层方式可见下图:




这次大的架构升级,主要考虑了三个方面:稳定性、效率和容量。 做了下面这些事情:
业务分级、核心、非核心业务隔离多机房部署,流量分流、容灾冗余、峰值应对冗余读库多源,失败自动转移写库主备,短暂有损服务容忍下的快速切换外部接口,失败转移或快速断路Redis 主备,失败转移大表迁移,MongoDB 取代 MySQL 存储消息记录改进消息投递模型
 
前 6 条基本属于考虑系统稳定性、可用性方面的改进升级。 这一块属于陆续迭代完成的,承载很多失败转移的配置和控制功能在上面图中是由管控中心提供的。 第 7 条主要是随着业务量的上升,单日消息量越来越大后,使用了 MongoDB 来单独存储量最大的聊天记录。 第 8 条是针对 1.0 版本消息轮询效率低的改进,改进后的投递方式如下图所示:




不再是轮询了,而是让终端每次建立连接后注册接入点位置,消息投递前定位连接所在接入点位置再推送过去。 这样投递效率就是恒定的了,而且很容易扩展,在线人数越多则连接数越多,只需要扩展接入点即可。 其实,这个模型依然还有些小问题,主要出在离线消息的处理上,可以先思考下,我们最后再讲。

3.0 经过了两年的迭代式升级,单纯从业务量上来说还可以继续支撑很长时间的增长。 但实际上到 2014 年底我们面对的不再是业务量的问题,而是业务模式的变化。 这直接导致了一个全新时代的到来。
 

4.0 涅槃(2015 至今 )

2014 年京东的组织架构发生了很大变化,从一个公司变成了一个集团,下设多个子公司。 原来的商城成为了其中一个子公司,新成立的子公司包括京东金融、京东智能、京东到家、拍拍、海外事业部等。 各自业务范围不同,业务模式也不同,但不管什么业务总是需要客服服务。 如何复用原来为商城量身订做的咚咚客服系统并支持其他子公司业务快速接入成为我们新的课题。

最早要求接入的是拍拍网,它是从腾讯收购的,所以是完全不同的账户和订单交易体系。 由于时间紧迫,我们把为商城订做的部分剥离,基于 3.0 架构对接拍拍又单独订做了一套,并独立部署,像下面这样。




虽然在业务要求的时间点前完成了上线,但这样做也带来了明显的问题:
复制工程,定制业务开发,多套源码维护成本高独立部署,至少双机房主备外加一个灰度集群,资源浪费大
 
以前我们都是面向业务去架构系统,如今新的业务变化形势下我们开始考虑面向平台去架构,在统一平台上跑多套业务,统一源码,统一部署,统一维护。 把业务服务继续拆分,剥离出最基础的 IM 服务,IM 通用服务,客服通用服务,而针对不同的业务特殊需求做最小化的定制服务开发。 部署方式则以平台形式部署,不同的业务方的服务跑在同一个平台上,但数据互相隔离。 服务继续被拆分的更微粒化,形成了一组服务矩阵(见下图)




而部署方式,只需要在双机房建立两套对等集群,并另外建一个较小的灰度发布集群即可,所有不同业务都运行在统一平台集群上,如下图:




更细粒度的服务意味着每个服务的开发更简单,代码量更小,依赖更少,隔离稳定性更高。 但更细粒度的服务也意味着更繁琐的运维监控管理,直到今年公司内部弹性私有云、缓存云、消息队列、部署、监控、日志等基础系统日趋完善, 使得实施这类细粒度划分的微服务架构成为可能,运维成本可控。 而从当初 1.0 的 1 种应用进程,到 3.0 的 6、7 种应用进程,再到 4.0 的 50+ 更细粒度的不同种应用进程。 每种进程再根据承载业务流量不同分配不同的实例数,真正的实例进程数会过千。 为了更好的监控和管理这些进程,为此专门定制了一套面向服务的运维管理系统,见下图:




统一服务运维提供了实用的内部工具和库来帮助开发更健壮的微服务。 包括中心配置管理,流量埋点监控,数据库和缓存访问,运行时隔离,如下图所示是一个运行隔离的图示:




细粒度的微服务做到了进程间隔离,严格的开发规范和工具库帮助实现了异步消息和异步 HTTP 来避免多个跨进程的同步长调用链。 进程内部通过切面方式引入了服务增强容器 Armor 来隔离线程, 并支持进程内的单独业务降级和同步转异步化执行。而所有这些工具和库服务都是为了两个目标:
让服务进程运行时状态可见让服务进程运行时状态可被管理和改变

最后我们回到前文留下的一个悬念,就是关于消息投递模型的缺陷。 一开始我们在接入层检测到终端连接断开后,消息无法投递,再将消息缓存下来,等终端重连接上来再拉取离线消息。 这个模型在移动时代表现的很不好,因为移动网络的不稳定性,导致经常断链后重连。 而准确的检测网络连接断开是依赖一个网络超时的,导致检测可能不准确,引发消息假投递成功。 新的模型如下图所示,它不再依赖准确的网络连接检测,投递前待确认消息 id 被缓存,而消息体被持久存储。 等到终端接收确认返回后,该消息才算投妥,未确认的消息 id 再重新登陆后或重连接后作为离线消息推送。 这个模型不会产生消息假投妥导致的丢失,但可能导致消息重复,只需由客户终端按消息 id 去重即可。




京东咚咚诞生之初正是京东技术转型到 Java 之时,经历这些年的发展,取得了很大的进步。 从草根走向专业,从弱小走向规模,从分散走向统一,从杂乱走向规范。 本文主要重心放在了几年来咚咚架构演进的过程,技术架构单独拿出来看我认为没有绝对的好与不好, 技术架构总是要放在彼时的背景下来看,要考虑业务的时效价值、团队的规模和能力、环境基础设施等等方面。 架构演进的生命周期适时匹配好业务的生命周期,才可能发挥最好的效果。
分享阅读原文:http://www.cnblogs.com/mindwind/p/5017591.html  查看全部
dongdong.png

咚咚是什么?咚咚之于京东相当于旺旺之于淘宝,它们都是服务于买家和卖家的沟通。 自从京东开始为第三方卖家提供入驻平台服务后,咚咚也就随之诞生了。 我们首先看看它诞生之初是什么样的。
 


1.0 诞生(2010 - 2011)​


为了业务的快速上线,1.0 版本的技术架构实现是非常直接且简单粗暴的。 如何简单粗暴法?请看架构图,如下:
Arch1.png

1.0 的功能十分简单,实现了一个 IM 的基本功能,接入、互通消息和状态。 另外还有客服功能,就是顾客接入咨询时的客服分配,按轮询方式把顾客分配给在线的客服接待。 用开源 Mina 框架实现了 TCP 的长连接接入,用 Tomcat Comet 机制实现了 HTTP 的长轮询服务。 而消息投递的实现是一端发送的消息临时存放在 Redis 中,另一端拉取的生产消费模型。

这个模型的做法导致需要以一种高频率的方式来轮询 Redis 遍历属于自己连接的关联会话消息。 这个模型很简单,简单包括多个层面的意思:理解起来简单;开发起来简单;部署起来也简单。 只需要一个 Tomcat 应用依赖一个共享的 Redis,简单的实现核心业务功能,并支持业务快速上线。

但这个简单的模型也有些严重的缺陷,主要是效率和扩展问题。 轮询的频率间隔大小基本决定了消息的延时,轮询越快延时越低,但轮询越快消耗也越高。 这个模型实际上是一个高功耗低效能的模型,因为不活跃的连接在那做高频率的无意义轮询。 高频有多高呢,基本在 100 ms 以内,你不能让轮询太慢,比如超过 2 秒轮一次,人就会在聊天过程中感受到明显的会话延迟。 随着在线人数增加,轮询的耗时也线性增长,因此这个模型导致了扩展能力和承载能力都不好,一定会随着在线人数的增长碰到性能瓶颈。

1.0 的时代背景正是京东技术平台从 .NET 向 Java 转型的年代,我也正是在这期间加入京东并参与了京东主站技术转型架构升级的过程。 之后开始接手了京东咚咚,并持续完善这个产品,进行了三次技术架构演进。
 


2.0 成长(2012)


我们刚接手时 1.0 已在线上运行并支持京东 POP(开放平台)业务,之后京东打算组建自营在线客服团队并落地在成都。 不管是自营还是 POP 客服咨询业务当时都起步不久,1.0 架构中的性能和效率缺陷问题还没有达到引爆的业务量级。 而自营客服当时还处于起步阶段,客服人数不足,服务能力不够,顾客咨询量远远超过客服的服务能力。 超出服务能力的顾客咨询,当时我们的系统统一返回提示客服繁忙,请稍后咨询。 这种状况导致高峰期大量顾客无论怎么刷新请求,都很可能无法接入客服,体验很差。 所以 2.0 重点放在了业务功能体验的提升上,如下图所示:
Arch2.png

针对无法及时提供服务的顾客,可以排队或者留言。 针对纯文字沟通,提供了文件和图片等更丰富的表达方式。 另外支持了客服转接和快捷回复等方式来提升客服的接待效率。 总之,整个 2.0 就是围绕提升客服效率和用户体验。 而我们担心的效率问题在 2.0 高速发展业务的时期还没有出现,但业务量正在逐渐积累,我们知道它快要爆了。 到 2012 年末,度过双十一后开始了 3.0 的一次重大架构升级。
 


3.0 爆发(2013 - 2014)


经历了 2.0 时代一整年的业务高速发展,实际上代码规模膨胀的很快。 与代码一块膨胀的还有团队,从最初的 4 个人到近 30 人。 团队大了后,一个系统多人开发,开发人员层次不一,规范难统一,系统模块耦合重,改动沟通和依赖多,上线风险难以控制。 一个单独 tomcat 应用多实例部署模型终于走到头了,这个版本架构升级的主题就是服务化。

服务化的第一个问题如何把一个大的应用系统切分成子服务系统。 当时的背景是京东的部署还在半自动化年代,自动部署系统刚起步,子服务系统若按业务划分太细太多,部署工作量很大且难管理。 所以当时我们不是按业务功能分区服务的,而是按业务重要性级别划分了 0、1、2 三个级别不同的子业务服务系统。 另外就是独立了一组接入服务,针对不同渠道和通信方式的接入端,见下图。
Arch3.png

更细化的应用服务和架构分层方式可见下图:
Arch4.png

这次大的架构升级,主要考虑了三个方面:稳定性、效率和容量。 做了下面这些事情:
  1. 业务分级、核心、非核心业务隔离
  2. 多机房部署,流量分流、容灾冗余、峰值应对冗余
  3. 读库多源,失败自动转移
  4. 写库主备,短暂有损服务容忍下的快速切换
  5. 外部接口,失败转移或快速断路
  6. Redis 主备,失败转移
  7. 大表迁移,MongoDB 取代 MySQL 存储消息记录
  8. 改进消息投递模型

 
前 6 条基本属于考虑系统稳定性、可用性方面的改进升级。 这一块属于陆续迭代完成的,承载很多失败转移的配置和控制功能在上面图中是由管控中心提供的。 第 7 条主要是随着业务量的上升,单日消息量越来越大后,使用了 MongoDB 来单独存储量最大的聊天记录。 第 8 条是针对 1.0 版本消息轮询效率低的改进,改进后的投递方式如下图所示:
Arch5.png

不再是轮询了,而是让终端每次建立连接后注册接入点位置,消息投递前定位连接所在接入点位置再推送过去。 这样投递效率就是恒定的了,而且很容易扩展,在线人数越多则连接数越多,只需要扩展接入点即可。 其实,这个模型依然还有些小问题,主要出在离线消息的处理上,可以先思考下,我们最后再讲。

3.0 经过了两年的迭代式升级,单纯从业务量上来说还可以继续支撑很长时间的增长。 但实际上到 2014 年底我们面对的不再是业务量的问题,而是业务模式的变化。 这直接导致了一个全新时代的到来。
 


4.0 涅槃(2015 至今 )


2014 年京东的组织架构发生了很大变化,从一个公司变成了一个集团,下设多个子公司。 原来的商城成为了其中一个子公司,新成立的子公司包括京东金融、京东智能、京东到家、拍拍、海外事业部等。 各自业务范围不同,业务模式也不同,但不管什么业务总是需要客服服务。 如何复用原来为商城量身订做的咚咚客服系统并支持其他子公司业务快速接入成为我们新的课题。

最早要求接入的是拍拍网,它是从腾讯收购的,所以是完全不同的账户和订单交易体系。 由于时间紧迫,我们把为商城订做的部分剥离,基于 3.0 架构对接拍拍又单独订做了一套,并独立部署,像下面这样。
Arch6.png

虽然在业务要求的时间点前完成了上线,但这样做也带来了明显的问题:
  1. 复制工程,定制业务开发,多套源码维护成本高
  2. 独立部署,至少双机房主备外加一个灰度集群,资源浪费大

 
以前我们都是面向业务去架构系统,如今新的业务变化形势下我们开始考虑面向平台去架构,在统一平台上跑多套业务,统一源码,统一部署,统一维护。 把业务服务继续拆分,剥离出最基础的 IM 服务,IM 通用服务,客服通用服务,而针对不同的业务特殊需求做最小化的定制服务开发。 部署方式则以平台形式部署,不同的业务方的服务跑在同一个平台上,但数据互相隔离。 服务继续被拆分的更微粒化,形成了一组服务矩阵(见下图)
Arch7.png

而部署方式,只需要在双机房建立两套对等集群,并另外建一个较小的灰度发布集群即可,所有不同业务都运行在统一平台集群上,如下图:
Arch8.png

更细粒度的服务意味着每个服务的开发更简单,代码量更小,依赖更少,隔离稳定性更高。 但更细粒度的服务也意味着更繁琐的运维监控管理,直到今年公司内部弹性私有云、缓存云、消息队列、部署、监控、日志等基础系统日趋完善, 使得实施这类细粒度划分的微服务架构成为可能,运维成本可控。 而从当初 1.0 的 1 种应用进程,到 3.0 的 6、7 种应用进程,再到 4.0 的 50+ 更细粒度的不同种应用进程。 每种进程再根据承载业务流量不同分配不同的实例数,真正的实例进程数会过千。 为了更好的监控和管理这些进程,为此专门定制了一套面向服务的运维管理系统,见下图:
Arch9.png

统一服务运维提供了实用的内部工具和库来帮助开发更健壮的微服务。 包括中心配置管理,流量埋点监控,数据库和缓存访问,运行时隔离,如下图所示是一个运行隔离的图示:
Arch10.png

细粒度的微服务做到了进程间隔离,严格的开发规范和工具库帮助实现了异步消息和异步 HTTP 来避免多个跨进程的同步长调用链。 进程内部通过切面方式引入了服务增强容器 Armor 来隔离线程, 并支持进程内的单独业务降级和同步转异步化执行。而所有这些工具和库服务都是为了两个目标:
  1. 让服务进程运行时状态可见
  2. 让服务进程运行时状态可被管理和改变


最后我们回到前文留下的一个悬念,就是关于消息投递模型的缺陷。 一开始我们在接入层检测到终端连接断开后,消息无法投递,再将消息缓存下来,等终端重连接上来再拉取离线消息。 这个模型在移动时代表现的很不好,因为移动网络的不稳定性,导致经常断链后重连。 而准确的检测网络连接断开是依赖一个网络超时的,导致检测可能不准确,引发消息假投递成功。 新的模型如下图所示,它不再依赖准确的网络连接检测,投递前待确认消息 id 被缓存,而消息体被持久存储。 等到终端接收确认返回后,该消息才算投妥,未确认的消息 id 再重新登陆后或重连接后作为离线消息推送。 这个模型不会产生消息假投妥导致的丢失,但可能导致消息重复,只需由客户终端按消息 id 去重即可。
Arch11.png

京东咚咚诞生之初正是京东技术转型到 Java 之时,经历这些年的发展,取得了很大的进步。 从草根走向专业,从弱小走向规模,从分散走向统一,从杂乱走向规范。 本文主要重心放在了几年来咚咚架构演进的过程,技术架构单独拿出来看我认为没有绝对的好与不好, 技术架构总是要放在彼时的背景下来看,要考虑业务的时效价值、团队的规模和能力、环境基础设施等等方面。 架构演进的生命周期适时匹配好业务的生命周期,才可能发挥最好的效果。
分享阅读原文:http://www.cnblogs.com/mindwind/p/5017591.html 

京东咚咚架构演进

运维技术koyo 发表了文章 • 0 个评论 • 1348 次浏览 • 2016-08-24 22:26 • 来自相关话题

咚咚是什么?咚咚之于京东相当于旺旺之于淘宝,它们都是服务于买家和卖家的沟通。 自从京东开始为第三方卖家提供入驻平台服务后,咚咚也就随之诞生了。 我们首先看看它诞生之初是什么样的。
 

1.0 诞生(2010 - 2011)​

为了业务的快速上线,1.0 版本的技术架构实现是非常直接且简单粗暴的。 如何简单粗暴法?请看架构图,如下:




1.0 的功能十分简单,实现了一个 IM 的基本功能,接入、互通消息和状态。 另外还有客服功能,就是顾客接入咨询时的客服分配,按轮询方式把顾客分配给在线的客服接待。 用开源 Mina 框架实现了 TCP 的长连接接入,用 Tomcat Comet 机制实现了 HTTP 的长轮询服务。 而消息投递的实现是一端发送的消息临时存放在 Redis 中,另一端拉取的生产消费模型。

这个模型的做法导致需要以一种高频率的方式来轮询 Redis 遍历属于自己连接的关联会话消息。 这个模型很简单,简单包括多个层面的意思:理解起来简单;开发起来简单;部署起来也简单。 只需要一个 Tomcat 应用依赖一个共享的 Redis,简单的实现核心业务功能,并支持业务快速上线。

但这个简单的模型也有些严重的缺陷,主要是效率和扩展问题。 轮询的频率间隔大小基本决定了消息的延时,轮询越快延时越低,但轮询越快消耗也越高。 这个模型实际上是一个高功耗低效能的模型,因为不活跃的连接在那做高频率的无意义轮询。 高频有多高呢,基本在 100 ms 以内,你不能让轮询太慢,比如超过 2 秒轮一次,人就会在聊天过程中感受到明显的会话延迟。 随着在线人数增加,轮询的耗时也线性增长,因此这个模型导致了扩展能力和承载能力都不好,一定会随着在线人数的增长碰到性能瓶颈。

1.0 的时代背景正是京东技术平台从 .NET 向 Java 转型的年代,我也正是在这期间加入京东并参与了京东主站技术转型架构升级的过程。 之后开始接手了京东咚咚,并持续完善这个产品,进行了三次技术架构演进。
 

2.0 成长(2012)

我们刚接手时 1.0 已在线上运行并支持京东 POP(开放平台)业务,之后京东打算组建自营在线客服团队并落地在成都。 不管是自营还是 POP 客服咨询业务当时都起步不久,1.0 架构中的性能和效率缺陷问题还没有达到引爆的业务量级。 而自营客服当时还处于起步阶段,客服人数不足,服务能力不够,顾客咨询量远远超过客服的服务能力。 超出服务能力的顾客咨询,当时我们的系统统一返回提示客服繁忙,请稍后咨询。 这种状况导致高峰期大量顾客无论怎么刷新请求,都很可能无法接入客服,体验很差。 所以 2.0 重点放在了业务功能体验的提升上,如下图所示:




针对无法及时提供服务的顾客,可以排队或者留言。 针对纯文字沟通,提供了文件和图片等更丰富的表达方式。 另外支持了客服转接和快捷回复等方式来提升客服的接待效率。 总之,整个 2.0 就是围绕提升客服效率和用户体验。 而我们担心的效率问题在 2.0 高速发展业务的时期还没有出现,但业务量正在逐渐积累,我们知道它快要爆了。 到 2012 年末,度过双十一后开始了 3.0 的一次重大架构升级。
 

3.0 爆发(2013 - 2014)

经历了 2.0 时代一整年的业务高速发展,实际上代码规模膨胀的很快。 与代码一块膨胀的还有团队,从最初的 4 个人到近 30 人。 团队大了后,一个系统多人开发,开发人员层次不一,规范难统一,系统模块耦合重,改动沟通和依赖多,上线风险难以控制。 一个单独 tomcat 应用多实例部署模型终于走到头了,这个版本架构升级的主题就是服务化。

服务化的第一个问题如何把一个大的应用系统切分成子服务系统。 当时的背景是京东的部署还在半自动化年代,自动部署系统刚起步,子服务系统若按业务划分太细太多,部署工作量很大且难管理。 所以当时我们不是按业务功能分区服务的,而是按业务重要性级别划分了 0、1、2 三个级别不同的子业务服务系统。 另外就是独立了一组接入服务,针对不同渠道和通信方式的接入端,见下图。




更细化的应用服务和架构分层方式可见下图:




这次大的架构升级,主要考虑了三个方面:稳定性、效率和容量。 做了下面这些事情:
业务分级、核心、非核心业务隔离多机房部署,流量分流、容灾冗余、峰值应对冗余读库多源,失败自动转移写库主备,短暂有损服务容忍下的快速切换外部接口,失败转移或快速断路Redis 主备,失败转移大表迁移,MongoDB 取代 MySQL 存储消息记录改进消息投递模型
 
前 6 条基本属于考虑系统稳定性、可用性方面的改进升级。 这一块属于陆续迭代完成的,承载很多失败转移的配置和控制功能在上面图中是由管控中心提供的。 第 7 条主要是随着业务量的上升,单日消息量越来越大后,使用了 MongoDB 来单独存储量最大的聊天记录。 第 8 条是针对 1.0 版本消息轮询效率低的改进,改进后的投递方式如下图所示:




不再是轮询了,而是让终端每次建立连接后注册接入点位置,消息投递前定位连接所在接入点位置再推送过去。 这样投递效率就是恒定的了,而且很容易扩展,在线人数越多则连接数越多,只需要扩展接入点即可。 其实,这个模型依然还有些小问题,主要出在离线消息的处理上,可以先思考下,我们最后再讲。

3.0 经过了两年的迭代式升级,单纯从业务量上来说还可以继续支撑很长时间的增长。 但实际上到 2014 年底我们面对的不再是业务量的问题,而是业务模式的变化。 这直接导致了一个全新时代的到来。
 

4.0 涅槃(2015 至今 )

2014 年京东的组织架构发生了很大变化,从一个公司变成了一个集团,下设多个子公司。 原来的商城成为了其中一个子公司,新成立的子公司包括京东金融、京东智能、京东到家、拍拍、海外事业部等。 各自业务范围不同,业务模式也不同,但不管什么业务总是需要客服服务。 如何复用原来为商城量身订做的咚咚客服系统并支持其他子公司业务快速接入成为我们新的课题。

最早要求接入的是拍拍网,它是从腾讯收购的,所以是完全不同的账户和订单交易体系。 由于时间紧迫,我们把为商城订做的部分剥离,基于 3.0 架构对接拍拍又单独订做了一套,并独立部署,像下面这样。




虽然在业务要求的时间点前完成了上线,但这样做也带来了明显的问题:
复制工程,定制业务开发,多套源码维护成本高独立部署,至少双机房主备外加一个灰度集群,资源浪费大
 
以前我们都是面向业务去架构系统,如今新的业务变化形势下我们开始考虑面向平台去架构,在统一平台上跑多套业务,统一源码,统一部署,统一维护。 把业务服务继续拆分,剥离出最基础的 IM 服务,IM 通用服务,客服通用服务,而针对不同的业务特殊需求做最小化的定制服务开发。 部署方式则以平台形式部署,不同的业务方的服务跑在同一个平台上,但数据互相隔离。 服务继续被拆分的更微粒化,形成了一组服务矩阵(见下图)




而部署方式,只需要在双机房建立两套对等集群,并另外建一个较小的灰度发布集群即可,所有不同业务都运行在统一平台集群上,如下图:




更细粒度的服务意味着每个服务的开发更简单,代码量更小,依赖更少,隔离稳定性更高。 但更细粒度的服务也意味着更繁琐的运维监控管理,直到今年公司内部弹性私有云、缓存云、消息队列、部署、监控、日志等基础系统日趋完善, 使得实施这类细粒度划分的微服务架构成为可能,运维成本可控。 而从当初 1.0 的 1 种应用进程,到 3.0 的 6、7 种应用进程,再到 4.0 的 50+ 更细粒度的不同种应用进程。 每种进程再根据承载业务流量不同分配不同的实例数,真正的实例进程数会过千。 为了更好的监控和管理这些进程,为此专门定制了一套面向服务的运维管理系统,见下图:




统一服务运维提供了实用的内部工具和库来帮助开发更健壮的微服务。 包括中心配置管理,流量埋点监控,数据库和缓存访问,运行时隔离,如下图所示是一个运行隔离的图示:




细粒度的微服务做到了进程间隔离,严格的开发规范和工具库帮助实现了异步消息和异步 HTTP 来避免多个跨进程的同步长调用链。 进程内部通过切面方式引入了服务增强容器 Armor 来隔离线程, 并支持进程内的单独业务降级和同步转异步化执行。而所有这些工具和库服务都是为了两个目标:
让服务进程运行时状态可见让服务进程运行时状态可被管理和改变

最后我们回到前文留下的一个悬念,就是关于消息投递模型的缺陷。 一开始我们在接入层检测到终端连接断开后,消息无法投递,再将消息缓存下来,等终端重连接上来再拉取离线消息。 这个模型在移动时代表现的很不好,因为移动网络的不稳定性,导致经常断链后重连。 而准确的检测网络连接断开是依赖一个网络超时的,导致检测可能不准确,引发消息假投递成功。 新的模型如下图所示,它不再依赖准确的网络连接检测,投递前待确认消息 id 被缓存,而消息体被持久存储。 等到终端接收确认返回后,该消息才算投妥,未确认的消息 id 再重新登陆后或重连接后作为离线消息推送。 这个模型不会产生消息假投妥导致的丢失,但可能导致消息重复,只需由客户终端按消息 id 去重即可。




京东咚咚诞生之初正是京东技术转型到 Java 之时,经历这些年的发展,取得了很大的进步。 从草根走向专业,从弱小走向规模,从分散走向统一,从杂乱走向规范。 本文主要重心放在了几年来咚咚架构演进的过程,技术架构单独拿出来看我认为没有绝对的好与不好, 技术架构总是要放在彼时的背景下来看,要考虑业务的时效价值、团队的规模和能力、环境基础设施等等方面。 架构演进的生命周期适时匹配好业务的生命周期,才可能发挥最好的效果。
分享阅读原文:http://www.cnblogs.com/mindwind/p/5017591.html  查看全部
dongdong.png

咚咚是什么?咚咚之于京东相当于旺旺之于淘宝,它们都是服务于买家和卖家的沟通。 自从京东开始为第三方卖家提供入驻平台服务后,咚咚也就随之诞生了。 我们首先看看它诞生之初是什么样的。
 


1.0 诞生(2010 - 2011)​


为了业务的快速上线,1.0 版本的技术架构实现是非常直接且简单粗暴的。 如何简单粗暴法?请看架构图,如下:
Arch1.png

1.0 的功能十分简单,实现了一个 IM 的基本功能,接入、互通消息和状态。 另外还有客服功能,就是顾客接入咨询时的客服分配,按轮询方式把顾客分配给在线的客服接待。 用开源 Mina 框架实现了 TCP 的长连接接入,用 Tomcat Comet 机制实现了 HTTP 的长轮询服务。 而消息投递的实现是一端发送的消息临时存放在 Redis 中,另一端拉取的生产消费模型。

这个模型的做法导致需要以一种高频率的方式来轮询 Redis 遍历属于自己连接的关联会话消息。 这个模型很简单,简单包括多个层面的意思:理解起来简单;开发起来简单;部署起来也简单。 只需要一个 Tomcat 应用依赖一个共享的 Redis,简单的实现核心业务功能,并支持业务快速上线。

但这个简单的模型也有些严重的缺陷,主要是效率和扩展问题。 轮询的频率间隔大小基本决定了消息的延时,轮询越快延时越低,但轮询越快消耗也越高。 这个模型实际上是一个高功耗低效能的模型,因为不活跃的连接在那做高频率的无意义轮询。 高频有多高呢,基本在 100 ms 以内,你不能让轮询太慢,比如超过 2 秒轮一次,人就会在聊天过程中感受到明显的会话延迟。 随着在线人数增加,轮询的耗时也线性增长,因此这个模型导致了扩展能力和承载能力都不好,一定会随着在线人数的增长碰到性能瓶颈。

1.0 的时代背景正是京东技术平台从 .NET 向 Java 转型的年代,我也正是在这期间加入京东并参与了京东主站技术转型架构升级的过程。 之后开始接手了京东咚咚,并持续完善这个产品,进行了三次技术架构演进。
 


2.0 成长(2012)


我们刚接手时 1.0 已在线上运行并支持京东 POP(开放平台)业务,之后京东打算组建自营在线客服团队并落地在成都。 不管是自营还是 POP 客服咨询业务当时都起步不久,1.0 架构中的性能和效率缺陷问题还没有达到引爆的业务量级。 而自营客服当时还处于起步阶段,客服人数不足,服务能力不够,顾客咨询量远远超过客服的服务能力。 超出服务能力的顾客咨询,当时我们的系统统一返回提示客服繁忙,请稍后咨询。 这种状况导致高峰期大量顾客无论怎么刷新请求,都很可能无法接入客服,体验很差。 所以 2.0 重点放在了业务功能体验的提升上,如下图所示:
Arch2.png

针对无法及时提供服务的顾客,可以排队或者留言。 针对纯文字沟通,提供了文件和图片等更丰富的表达方式。 另外支持了客服转接和快捷回复等方式来提升客服的接待效率。 总之,整个 2.0 就是围绕提升客服效率和用户体验。 而我们担心的效率问题在 2.0 高速发展业务的时期还没有出现,但业务量正在逐渐积累,我们知道它快要爆了。 到 2012 年末,度过双十一后开始了 3.0 的一次重大架构升级。
 


3.0 爆发(2013 - 2014)


经历了 2.0 时代一整年的业务高速发展,实际上代码规模膨胀的很快。 与代码一块膨胀的还有团队,从最初的 4 个人到近 30 人。 团队大了后,一个系统多人开发,开发人员层次不一,规范难统一,系统模块耦合重,改动沟通和依赖多,上线风险难以控制。 一个单独 tomcat 应用多实例部署模型终于走到头了,这个版本架构升级的主题就是服务化。

服务化的第一个问题如何把一个大的应用系统切分成子服务系统。 当时的背景是京东的部署还在半自动化年代,自动部署系统刚起步,子服务系统若按业务划分太细太多,部署工作量很大且难管理。 所以当时我们不是按业务功能分区服务的,而是按业务重要性级别划分了 0、1、2 三个级别不同的子业务服务系统。 另外就是独立了一组接入服务,针对不同渠道和通信方式的接入端,见下图。
Arch3.png

更细化的应用服务和架构分层方式可见下图:
Arch4.png

这次大的架构升级,主要考虑了三个方面:稳定性、效率和容量。 做了下面这些事情:
  1. 业务分级、核心、非核心业务隔离
  2. 多机房部署,流量分流、容灾冗余、峰值应对冗余
  3. 读库多源,失败自动转移
  4. 写库主备,短暂有损服务容忍下的快速切换
  5. 外部接口,失败转移或快速断路
  6. Redis 主备,失败转移
  7. 大表迁移,MongoDB 取代 MySQL 存储消息记录
  8. 改进消息投递模型

 
前 6 条基本属于考虑系统稳定性、可用性方面的改进升级。 这一块属于陆续迭代完成的,承载很多失败转移的配置和控制功能在上面图中是由管控中心提供的。 第 7 条主要是随着业务量的上升,单日消息量越来越大后,使用了 MongoDB 来单独存储量最大的聊天记录。 第 8 条是针对 1.0 版本消息轮询效率低的改进,改进后的投递方式如下图所示:
Arch5.png

不再是轮询了,而是让终端每次建立连接后注册接入点位置,消息投递前定位连接所在接入点位置再推送过去。 这样投递效率就是恒定的了,而且很容易扩展,在线人数越多则连接数越多,只需要扩展接入点即可。 其实,这个模型依然还有些小问题,主要出在离线消息的处理上,可以先思考下,我们最后再讲。

3.0 经过了两年的迭代式升级,单纯从业务量上来说还可以继续支撑很长时间的增长。 但实际上到 2014 年底我们面对的不再是业务量的问题,而是业务模式的变化。 这直接导致了一个全新时代的到来。
 


4.0 涅槃(2015 至今 )


2014 年京东的组织架构发生了很大变化,从一个公司变成了一个集团,下设多个子公司。 原来的商城成为了其中一个子公司,新成立的子公司包括京东金融、京东智能、京东到家、拍拍、海外事业部等。 各自业务范围不同,业务模式也不同,但不管什么业务总是需要客服服务。 如何复用原来为商城量身订做的咚咚客服系统并支持其他子公司业务快速接入成为我们新的课题。

最早要求接入的是拍拍网,它是从腾讯收购的,所以是完全不同的账户和订单交易体系。 由于时间紧迫,我们把为商城订做的部分剥离,基于 3.0 架构对接拍拍又单独订做了一套,并独立部署,像下面这样。
Arch6.png

虽然在业务要求的时间点前完成了上线,但这样做也带来了明显的问题:
  1. 复制工程,定制业务开发,多套源码维护成本高
  2. 独立部署,至少双机房主备外加一个灰度集群,资源浪费大

 
以前我们都是面向业务去架构系统,如今新的业务变化形势下我们开始考虑面向平台去架构,在统一平台上跑多套业务,统一源码,统一部署,统一维护。 把业务服务继续拆分,剥离出最基础的 IM 服务,IM 通用服务,客服通用服务,而针对不同的业务特殊需求做最小化的定制服务开发。 部署方式则以平台形式部署,不同的业务方的服务跑在同一个平台上,但数据互相隔离。 服务继续被拆分的更微粒化,形成了一组服务矩阵(见下图)
Arch7.png

而部署方式,只需要在双机房建立两套对等集群,并另外建一个较小的灰度发布集群即可,所有不同业务都运行在统一平台集群上,如下图:
Arch8.png

更细粒度的服务意味着每个服务的开发更简单,代码量更小,依赖更少,隔离稳定性更高。 但更细粒度的服务也意味着更繁琐的运维监控管理,直到今年公司内部弹性私有云、缓存云、消息队列、部署、监控、日志等基础系统日趋完善, 使得实施这类细粒度划分的微服务架构成为可能,运维成本可控。 而从当初 1.0 的 1 种应用进程,到 3.0 的 6、7 种应用进程,再到 4.0 的 50+ 更细粒度的不同种应用进程。 每种进程再根据承载业务流量不同分配不同的实例数,真正的实例进程数会过千。 为了更好的监控和管理这些进程,为此专门定制了一套面向服务的运维管理系统,见下图:
Arch9.png

统一服务运维提供了实用的内部工具和库来帮助开发更健壮的微服务。 包括中心配置管理,流量埋点监控,数据库和缓存访问,运行时隔离,如下图所示是一个运行隔离的图示:
Arch10.png

细粒度的微服务做到了进程间隔离,严格的开发规范和工具库帮助实现了异步消息和异步 HTTP 来避免多个跨进程的同步长调用链。 进程内部通过切面方式引入了服务增强容器 Armor 来隔离线程, 并支持进程内的单独业务降级和同步转异步化执行。而所有这些工具和库服务都是为了两个目标:
  1. 让服务进程运行时状态可见
  2. 让服务进程运行时状态可被管理和改变


最后我们回到前文留下的一个悬念,就是关于消息投递模型的缺陷。 一开始我们在接入层检测到终端连接断开后,消息无法投递,再将消息缓存下来,等终端重连接上来再拉取离线消息。 这个模型在移动时代表现的很不好,因为移动网络的不稳定性,导致经常断链后重连。 而准确的检测网络连接断开是依赖一个网络超时的,导致检测可能不准确,引发消息假投递成功。 新的模型如下图所示,它不再依赖准确的网络连接检测,投递前待确认消息 id 被缓存,而消息体被持久存储。 等到终端接收确认返回后,该消息才算投妥,未确认的消息 id 再重新登陆后或重连接后作为离线消息推送。 这个模型不会产生消息假投妥导致的丢失,但可能导致消息重复,只需由客户终端按消息 id 去重即可。
Arch11.png

京东咚咚诞生之初正是京东技术转型到 Java 之时,经历这些年的发展,取得了很大的进步。 从草根走向专业,从弱小走向规模,从分散走向统一,从杂乱走向规范。 本文主要重心放在了几年来咚咚架构演进的过程,技术架构单独拿出来看我认为没有绝对的好与不好, 技术架构总是要放在彼时的背景下来看,要考虑业务的时效价值、团队的规模和能力、环境基础设施等等方面。 架构演进的生命周期适时匹配好业务的生命周期,才可能发挥最好的效果。
分享阅读原文:http://www.cnblogs.com/mindwind/p/5017591.html 

蘑菇街运维体系及双十一关键技术分享

大数据/云计算being 发表了文章 • 0 个评论 • 1672 次浏览 • 2016-05-22 00:49 • 来自相关话题

关于蘑菇街:
中国最大的女性时尚社交电商平台。成立于2011年,总部位于浙江杭州, 目前(2015.Q3)拥有1.3亿注册用户,双十一日UV超2000万。2015.11.21日宣布完成D轮融资,并实施"一街双城"战略,杭州+北京,杭 州偏电商方向,北京偏社交媒体方向。 




蘑菇街业务架构-导购期(2011-2012)








运维早期情况 
早期阶段(2011-2012年)
      – 两位数机器、个位数网络设备
      – 没有运维,开发即运维,靠牛逼的脚本和一些开源工具搞定 
蘑菇街业务架构-转型期(2013)








运维的发展 
中间阶段(2013年-2014年)
           – 三位数服务器、两位数网络设备
           – 2-3名专职运维同学(主机&网络&DB&缓存&......) – 问题响应式的工作方式
– 工具化的运维平台
[]机器资源管理(CMDB的雏形)[/][] PHP发布系统[/][] 从指标维度监控系统(主机、QPS、RT、调用次数.... ) [/]
蘑菇街业务架构-社会化电商












我们应该怎么做 ​
思路:
[]建立以应用服务为核心的管理标准体系[/][]打造CMDB、流程申请、持续集成和监控为一体的自动化运维系统, 而不是孤立的单点系统[/][]把运维能力服务化(API),使运维的能力无处不在 [/]




关于应用服务管理 ​




案例介绍
让我们看一个从服务器管理—申请—代码发布—线上监控的案例 
关于应用服务器-Hestia服务和资源管理
[]从业务的维度来管理主机-CMDB的核心概念[/][]支持扩容、上下线、设备保障、权限等常规流程申请 [/]
[]自动化任务的配置和下发 [/]




关于应用服务管理-Mops流程申请系统




关于应用服务管理-发布系统
以trade_ordership_service为标示,进行代码发布 




关于应用服务管理-监控系统Sentry
通用+自定义监控,运维+开发可以时刻关注自己的服务状态和质量




运维的现状 ​
专业的运维团队 – 系统运维
– 应用运维 – DBA
– 运维开发

• 运维的能力向平台化和服务化发展(DevOps,依赖于能力而不是人) – CMDB服务化平台
– PHP+Java持续集成发布平台
– 统一的监控平台
– 全链路服务质量分析平台 – 稳定性平台
– 容量评估平台(待做)

• 工作方式的改变
– 从问题响应式,向整体解决方案提供方向发展 
双11技术保障,运维做了什么?




双11关键技术分享—全链路系统 
全链路背景
[]复杂的分布式系统,页面上的一次链接点击,在后端 可能会产生几十次的RPC调用,Web、服务化、缓存、 消息、DB.......都有可能涉及,如果出了问题,如何快 速定位到故障点要扩容,如何合理评估[/][]关键概念,全局唯一的TraceId [/]
全链路技术架构 




全链路应用-快速发现问题点和瓶颈点




全链路应用-调用合理性分析 
没有明显的瓶颈点,每一次调用RT也很正常,但是全链整体的RT却很高, 问题又出在哪里了呢? 








全链路使用后的收益和后续
使用全链路后的收益
– 提升问题的定位效率 – 准确的评估容量
 
后续
– Mogu-Watch,与前端打通,实现用户全链路的分析 – 压测做到平时,与容量评估平台和资源分配打通
– 引入云资源弹性扩容,避免应对峰值的批量机器采购 
压测之后,关键技术改造-ATS静态化方案
静态化方案背景和简介
– 主链路(首页-详情&活动-交易-支付),降低RT,提升容量

– 资源类的如图片、CSS、JS等的静态化方案都会采用CDN技术

– 对于页面内容类的数据,如商品名称、商品详情等都属于静态数据,而 商品的库存、优惠等则需要获取动态结果

– 对于活动页面、H5活动推广页面等,则可以完全静态化 




ATS(Apache Traffic Server)静态化技术方案-Cheetah 




ATS静态化案例-商品详情页 ​




ATS静态化使用后的收益和后续 ​
• 使用静态化后的收益 
–  详情页(全站流量的30%+)静态化在双11期间的命中率达到95%,换言之,减少了后端服务接近30%的流量压力
–  RT从原来200ms降低到50ms,用户体验大大提升
–  容量提升,减少了后端服务器的数量

• 后续
– 借助云资源搭建云上的ATS,更贴近用户 – ATS Cluster方案
– 支持HTTPS
– 回源流控和容灾控制 
限流&降级开关推送和WEB应急扩容方案
• 限流&降级开关
– 限流,Web层,防止被流量打垮
– 降级,App层(服务化),保障核心应用

• Web应急扩容方案
– 选择Docker 容器,批量生成效率高 – 启动速度快
– 资源利用率提升明显  查看全部
关于蘑菇街:
中国最大的女性时尚社交电商平台。成立于2011年,总部位于浙江杭州, 目前(2015.Q3)拥有1.3亿注册用户,双十一日UV超2000万。2015.11.21日宣布完成D轮融资,并实施"一街双城"战略,杭州+北京,杭 州偏电商方向,北京偏社交媒体方向。 
mogujie.png

蘑菇街业务架构-导购期(2011-2012)
dgq.png

dgq2.png

运维早期情况 
早期阶段(2011-2012年)
      – 两位数机器、个位数网络设备
      – 没有运维,开发即运维,靠牛逼的脚本和一些开源工具搞定 
蘑菇街业务架构-转型期(2013)
zxq.png

zxq2.png

运维的发展 
中间阶段(2013年-2014年)
           – 三位数服务器、两位数网络设备
           – 2-3名专职运维同学(主机&网络&DB&缓存&......) – 问题响应式的工作方式
– 工具化的运维平台
    []机器资源管理(CMDB的雏形)[/][] PHP发布系统[/][] 从指标维度监控系统(主机、QPS、RT、调用次数.... ) [/]

蘑菇街业务架构-社会化电商
ds.png

ds2.png

pro.png

我们应该怎么做 ​
思路:
    []建立以应用服务为核心的管理标准体系[/][]打造CMDB、流程申请、持续集成和监控为一体的自动化运维系统, 而不是孤立的单点系统[/][]把运维能力服务化(API),使运维的能力无处不在 [/]

cmdb.png

关于应用服务管理 ​
appserver.png

案例介绍
让我们看一个从服务器管理—申请—代码发布—线上监控的案例 
关于应用服务器-Hestia服务和资源管理
    []从业务的维度来管理主机-CMDB的核心概念[/][]支持扩容、上下线、设备保障、权限等常规流程申请 [/]

    []自动化任务的配置和下发 [/]

hestia.png

关于应用服务管理-Mops流程申请系统
Mops.png

关于应用服务管理-发布系统
以trade_ordership_service为标示,进行代码发布 
fb.png

关于应用服务管理-监控系统Sentry
通用+自定义监控,运维+开发可以时刻关注自己的服务状态和质量
sentry.png

运维的现状 ​
专业的运维团队 – 系统运维
– 应用运维 – DBA
– 运维开发

• 运维的能力向平台化和服务化发展(DevOps,依赖于能力而不是人) – CMDB服务化平台
– PHP+Java持续集成发布平台
– 统一的监控平台
– 全链路服务质量分析平台 – 稳定性平台
– 容量评估平台(待做)

• 工作方式的改变
– 从问题响应式,向整体解决方案提供方向发展 
双11技术保障,运维做了什么?
s11.png

双11关键技术分享—全链路系统 
全链路背景
    []复杂的分布式系统,页面上的一次链接点击,在后端 可能会产生几十次的RPC调用,Web、服务化、缓存、 消息、DB.......都有可能涉及,如果出了问题,如何快 速定位到故障点要扩容,如何合理评估[/][]关键概念,全局唯一的TraceId [/]

全链路技术架构 
qll.png

全链路应用-快速发现问题点和瓶颈点
wtd.png

全链路应用-调用合理性分析 
没有明显的瓶颈点,每一次调用RT也很正常,但是全链整体的RT却很高, 问题又出在哪里了呢? 
hlx.png

jiazhi.png

全链路使用后的收益和后续
使用全链路后的收益
– 提升问题的定位效率 – 准确的评估容量
 
后续
– Mogu-Watch,与前端打通,实现用户全链路的分析 – 压测做到平时,与容量评估平台和资源分配打通
– 引入云资源弹性扩容,避免应对峰值的批量机器采购 
压测之后,关键技术改造-ATS静态化方案
静态化方案背景和简介
– 主链路(首页-详情&活动-交易-支付),降低RT,提升容量

– 资源类的如图片、CSS、JS等的静态化方案都会采用CDN技术

– 对于页面内容类的数据,如商品名称、商品详情等都属于静态数据,而 商品的库存、优惠等则需要获取动态结果

– 对于活动页面、H5活动推广页面等,则可以完全静态化 
ATS.png

ATS(Apache Traffic Server)静态化技术方案-Cheetah 
cheetah.png

ATS静态化案例-商品详情页 ​
atsjh.png

ATS静态化使用后的收益和后续 ​
• 使用静态化后的收益 
–  详情页(全站流量的30%+)静态化在双11期间的命中率达到95%,换言之,减少了后端服务接近30%的流量压力
–  RT从原来200ms降低到50ms,用户体验大大提升
–  容量提升,减少了后端服务器的数量

• 后续
– 借助云资源搭建云上的ATS,更贴近用户 – ATS Cluster方案
– 支持HTTPS
– 回源流控和容灾控制 
限流&降级开关推送和WEB应急扩容方案
• 限流&降级开关
– 限流,Web层,防止被流量打垮
– 降级,App层(服务化),保障核心应用

• Web应急扩容方案
– 选择Docker 容器,批量生成效率高 – 启动速度快
– 资源利用率提升明显 

跨境电商Crazysales的高稳定性架构实践

运维技术cloudwise 发表了文章 • 0 个评论 • 1306 次浏览 • 2016-05-13 11:55 • 来自相关话题

Crazysales是一家典型的跨境电商企业,以澳洲和英国作为主要目标市场,产品大多数由国内供应商提供。Crazysales不但是Amazon、eBay等大型电商平台上的大卖家,同时在澳洲、新西兰建设有自营电商网站,为广大用户提供完整的网购服务。 
 






由于涉及跨国网络部署,不可避免地需要穿过“万里长城”,因此应用架构相对普通电商网站更加复杂,管理成本也自然提升,如何能够及时了解分布在中国、澳洲、英国等地不同业务系统的运行状态,是运维部门最关心的工作。

跨境电商的典型IT架构

Crazysales的核心业务系统及网店系统均搭建在Amazon的AWS平台之上,用Amazon CloudFront进行前端内容分发,而后端的数据维护平台因为供应商在国内,所以也在国内。 系统架构如下图:






目前,我们应用的技术都不是“高大上”的新技术,但稳定性得到很好的保证: 1.传统的PHP+LINUX+MYSQL,辅助数据的统计和分析应用mongoDB , 搜索引擎基于Solr。 系统架构做到前后低耦合,前端网站强依赖数据库转变成弱依赖。 2.MYSQL部署了两台slave 和定时静态备份数据,确保数据库的异地备份,和读写分离,为以后的无限扩展搭好基础。 3.通过每个应用层的监控,及时发现系统的瓶颈,针对性地优化。 整套系统都是我们团队经过多年合作开发逐步建立和维护的,所以很难保证统一的代码风格和代码水平,那是可遇不可求的。因此,必须建立合理的监控体系及时发现项目管理的漏洞、测试的漏洞、线上的性能瓶颈,这都让运维的工作在整个系统生命周期里更重要,这也是时下运维开发工程师的工作核心。

跨境电商的最佳监控解决方案

因为使用了Amazon的云服务,所以我们运维工程师不必花费大量时间维护基础硬件设施,而有更多的时间和精力来研究和优化我们的业务系统,其中监控体系是令我们为之骄傲的一部分。 






我们的自建监控系统能够及时、准确的发现部署在AWS上和国内的各个业务系统的运行状况,但对于通过CloudFront分发出去的前端内容,以及主要分布于英国、澳大利亚、新西兰等不同国家的用户的访问体验,则是自建监控系统很难准确感知的。另外我们的开发和运维团队主要在国内,因此需要一款既能准确感知海外用户访问Crazysales网站情况,又能通过手机短信、微信等手段给国内技术团队提供准确告警消息的监控工具。经过多方测试,我们最终采用云智慧的监控宝网站监控和网页性能监控功能,负责网站从CDN到前端浏览器环节的可用性监控。  





 
各个层级设不同的监控点

红色部分使用监控宝的监控系统,绿色是监控宝和自建监控系统混合使用 这是我们目前实施的监控架构: 通过脚本/自建监控系统 / 外部监控点(模拟真实客户访问) 多种实时监控数据来监测业务系统的运作状态,根据不同系统的特性来调整数据采样的频率,多维度的监控和及时的告警信息让维护人员及时知道系统的运作情况,保障系统的正常运作和提高异常处理的及时性,最终实现故障出现前预防和故障出现后及时解决的效果。 例如,我们的内部监控系统发现数据库在凌晨4点会出现服务很忙,同时监控宝监控数据显示前台出现等待时间过长(>10s),通过和我们的后台任务调度系统的运行时间进行对比,发现一个JOB需要大量SQL查询,导致数据库CPU占用过多,因此及时调整SQL的查询指向其它Slave,同时优化该SQL。 如下图,马上就看到优化后的效果了:  






监控宝遍布全球的分布式监测点能够模拟真实客户访问,及时了解客户遇到的问题,避免IT团队无法取到第一手材料导致丢失重现系统故障的机会,这是我们设置外部监控点的原因。如果自己购买服务器和节点进行部署的话,维护成本很高,也不专业。监控宝基于SaaS的服务和收费模式,很好的解决了成本和维护的问题,帮助我们掌握在澳洲,英国,中国大陆等地的访问速度,可用性等数据。 监控宝模拟客户端在各个监测点的数据采样频率最高可达到5分钟每次,不但能在第一时间发现故障并给予告警,而且能帮助我们掌握Web页面的性能表现,让开发人员可以针对性进行页面优化。而监控宝在全球范围内不断地增加的监测点数量,也和我们公司不断拓展英语国家业务的发展思路不谋而合。 最后说一下告警方式,众所周知,告警是监控的最后一步,大部分监控平台使用的是邮件和短信告警,但现在最流行的社交应用是微信,也是我们现在用得最多和最及时的平台。因此,我们将多种收集数据的介质通过监控宝转化到微信进行提示,基本上能做到故障发生半分钟内运维同事作出反应。 查看全部
Crazysales是一家典型的跨境电商企业,以澳洲和英国作为主要目标市场,产品大多数由国内供应商提供。Crazysales不但是Amazon、eBay等大型电商平台上的大卖家,同时在澳洲、新西兰建设有自营电商网站,为广大用户提供完整的网购服务。 
 
1.png



由于涉及跨国网络部署,不可避免地需要穿过“万里长城”,因此应用架构相对普通电商网站更加复杂,管理成本也自然提升,如何能够及时了解分布在中国、澳洲、英国等地不同业务系统的运行状态,是运维部门最关心的工作。

跨境电商的典型IT架构

Crazysales的核心业务系统及网店系统均搭建在Amazon的AWS平台之上,用Amazon CloudFront进行前端内容分发,而后端的数据维护平台因为供应商在国内,所以也在国内。 系统架构如下图:

2.png


目前,我们应用的技术都不是“高大上”的新技术,但稳定性得到很好的保证: 1.传统的PHP+LINUX+MYSQL,辅助数据的统计和分析应用mongoDB , 搜索引擎基于Solr。 系统架构做到前后低耦合,前端网站强依赖数据库转变成弱依赖。 2.MYSQL部署了两台slave 和定时静态备份数据,确保数据库的异地备份,和读写分离,为以后的无限扩展搭好基础。 3.通过每个应用层的监控,及时发现系统的瓶颈,针对性地优化。 整套系统都是我们团队经过多年合作开发逐步建立和维护的,所以很难保证统一的代码风格和代码水平,那是可遇不可求的。因此,必须建立合理的监控体系及时发现项目管理的漏洞、测试的漏洞、线上的性能瓶颈,这都让运维的工作在整个系统生命周期里更重要,这也是时下运维开发工程师的工作核心。

跨境电商的最佳监控解决方案

因为使用了Amazon的云服务,所以我们运维工程师不必花费大量时间维护基础硬件设施,而有更多的时间和精力来研究和优化我们的业务系统,其中监控体系是令我们为之骄傲的一部分。 

3.png


我们的自建监控系统能够及时、准确的发现部署在AWS上和国内的各个业务系统的运行状况,但对于通过CloudFront分发出去的前端内容,以及主要分布于英国、澳大利亚、新西兰等不同国家的用户的访问体验,则是自建监控系统很难准确感知的。另外我们的开发和运维团队主要在国内,因此需要一款既能准确感知海外用户访问Crazysales网站情况,又能通过手机短信、微信等手段给国内技术团队提供准确告警消息的监控工具。经过多方测试,我们最终采用云智慧的监控宝网站监控和网页性能监控功能,负责网站从CDN到前端浏览器环节的可用性监控。  

4.png

 
各个层级设不同的监控点

红色部分使用监控宝的监控系统,绿色是监控宝和自建监控系统混合使用 这是我们目前实施的监控架构: 通过脚本/自建监控系统 / 外部监控点(模拟真实客户访问) 多种实时监控数据来监测业务系统的运作状态,根据不同系统的特性来调整数据采样的频率,多维度的监控和及时的告警信息让维护人员及时知道系统的运作情况,保障系统的正常运作和提高异常处理的及时性,最终实现故障出现前预防和故障出现后及时解决的效果。 例如,我们的内部监控系统发现数据库在凌晨4点会出现服务很忙,同时监控宝监控数据显示前台出现等待时间过长(>10s),通过和我们的后台任务调度系统的运行时间进行对比,发现一个JOB需要大量SQL查询,导致数据库CPU占用过多,因此及时调整SQL的查询指向其它Slave,同时优化该SQL。 如下图,马上就看到优化后的效果了:  

5.png


监控宝遍布全球的分布式监测点能够模拟真实客户访问,及时了解客户遇到的问题,避免IT团队无法取到第一手材料导致丢失重现系统故障的机会,这是我们设置外部监控点的原因。如果自己购买服务器和节点进行部署的话,维护成本很高,也不专业。监控宝基于SaaS的服务和收费模式,很好的解决了成本和维护的问题,帮助我们掌握在澳洲,英国,中国大陆等地的访问速度,可用性等数据。 监控宝模拟客户端在各个监测点的数据采样频率最高可达到5分钟每次,不但能在第一时间发现故障并给予告警,而且能帮助我们掌握Web页面的性能表现,让开发人员可以针对性进行页面优化。而监控宝在全球范围内不断地增加的监测点数量,也和我们公司不断拓展英语国家业务的发展思路不谋而合。 最后说一下告警方式,众所周知,告警是监控的最后一步,大部分监控平台使用的是邮件和短信告警,但现在最流行的社交应用是微信,也是我们现在用得最多和最及时的平台。因此,我们将多种收集数据的介质通过监控宝转化到微信进行提示,基本上能做到故障发生半分钟内运维同事作出反应。

Nginx+Keepalived实现网站高可用方案

运维技术push 发表了文章 • 0 个评论 • 2583 次浏览 • 2015-10-31 17:00 • 来自相关话题

公司内部 OA 系统要做线上高可用,避免单点故障,所以计划使用2台虚拟机通过 Keepalived 工具来实现 nginx 的高可用(High Avaiability),达到一台nginx入口服务器宕机,另一台备机自动接管服务的效果。
 1. Keepalived介绍Keepalived是一个基于VRRP协议来实现的服务高可用方案,可以利用其来避免IP单点故障,类似的工具还有heartbeat、corosync、pacemaker。但是它一般不会单独出现,而是与其它负载均衡技术(如lvs、haproxy、nginx)一起工作来达到集群的高可用。

1.1 VRRP协议

VRRP全称 Virtual Router Redundancy Protocol,即 虚拟路由冗余协议。可以认为它是实现路由器高可用的容错协议,即将N台提供相同功能的路由器组成一个路由器组(Router Group),这个组里面有一个master和多个backup,但在外界看来就像一台一样,构成虚拟路由器,拥有一个虚拟IP(vip,也就是路由器所在局域网内其他机器的默认路由),占有这个IP的master实际负责ARP相应和转发IP数据包,组中的其它路由器作为备份的角色处于待命状态。master会发组播消息,当backup在超时时间内收不到vrrp包时就认为master宕掉了,这时就需要根据VRRP的优先级来选举一个backup当master,保证路由器的高可用。
 
在VRRP协议实现里,虚拟路由器使用 00-00-5E-00-01-XX 作为虚拟MAC地址,XX就是唯一的 VRID (Virtual Router IDentifier),这个地址同一时间只有一个物理路由器占用。在虚拟路由器里面的物理路由器组里面通过多播IP地址 224.0.0.18 来定时发送通告消息。每个Router都有一个 1-255 之间的优先级别,级别最高的(highest priority)将成为主控(master)路由器。通过降低master的优先权可以让处于backup状态的路由器抢占(pro-empt)主路由器的状态,两个backup优先级相同的IP地址较大者为master,接管虚拟IP。




与heartbeat/corosync等比较:Heartbeat、Corosync、Keepalived这三个集群组件我们到底选哪个好,首先我想说明的是,Heartbeat、Corosync是属于同一类型,Keepalived与Heartbeat、Corosync,根本不是同一类型的。Keepalived使用的vrrp协议方式,虚拟路由冗余协议 (Virtual Router Redundancy Protocol,简称VRRP);Heartbeat或Corosync是基于主机或网络服务的高可用方式;简单的说就是,Keepalived的目的是模拟路由器的高可用,Heartbeat或Corosync的目的是实现Service的高可用。

所以一般Keepalived是实现前端高可用,常用的前端高可用的组合有,就是我们常见的LVS+Keepalived、Nginx+Keepalived、HAproxy+Keepalived。而Heartbeat或Corosync是实现服务的高可用,常见的组合有Heartbeat v3(Corosync)+Pacemaker+NFS+Httpd 实现Web服务器的高可用、Heartbeat v3(Corosync)+Pacemaker+NFS+MySQL 实现MySQL服务器的高可用。总结一下,Keepalived中实现轻量级的高可用,一般用于前端高可用,且不需要共享存储,一般常用于两个节点的高可用。而Heartbeat(或Corosync)一般用于服务的高可用,且需要共享存储,一般用于多节点的高可用。这个问题我们说明白了。

又有博友会问了,那heartbaet与corosync我们又应该选择哪个好啊,我想说我们一般用corosync,因为corosync的运行机制更优于heartbeat,就连从heartbeat分离出来的pacemaker都说在以后的开发当中更倾向于corosync,所以现在corosync+pacemaker是最佳组合。

1.2 Keepalived + nginx

keepalived可以认为是VRRP协议在Linux上的实现,主要有三个模块,分别是core、check和vrrp。core模块为keepalived的核心,负责主进程的启动、维护以及全局配置文件的加载和解析。check负责健康检查,包括常见的各种检查方式。vrrp模块是来实现VRRP协议的。本文基于如下的拓扑图: +-------------+
| uplink |
+-------------+
|
+
MASTER keep|alived BACKUP
172.29.88.224 172.29.88.222 172.29.88.225
+-------------+ +-------------+ +-------------+
| nginx01 |----| virtualIP |----| nginx02 |
+-------------+ +-------------+ +-------------+
|
+------------------+------------------+
| | |
+-------------+ +-------------+ +-------------+
| web01 | | web02 | | web03 |
+-------------+ +-------------+ +-------------+2. keepalived实现nginx高可用

2.1安装

我的环境是CentOS 6.2 X86_64,直接通过yum方式安装最简单:# yum install -y keepalived
# keepalived -v
Keepalived v1.2.13 (03/19,2015)

2.2 nginx监控脚本

该脚本检测ngnix的运行状态,并在nginx进程不存在时尝试重新启动ngnix,如果启动失败则停止keepalived,准备让其它机器接管。/etc/keepalived/check_nginx.sh :#!/bin/bash
counter=$(ps -C nginx --no-heading|wc -l)
if [ "${counter}" = "0" ]; then
/usr/local/bin/nginx
sleep 2
counter=$(ps -C nginx --no-heading|wc -l)
if [ "${counter}" = "0" ]; then
/etc/init.d/keepalived stop
fi
fi你也可以根据自己的业务需求,总结出在什么情形下关闭keepalived,如 curl 主页连续2个5s没有响应则切换:#!/bin/bash
# curl -IL http://localhost/member/login.htm
# curl --data "memberName=fengkan&password=22" http://localhost/member/login.htm

count = 0
for (( k=0; k<2; k++ ))
do
check_code=$( curl --connect-timeout 3 -sL -w "%{http_code}\\n" http://localhost/login.html -o /dev/null )
if [ "$check_code" != "200" ]; then
count = count +1
continue
else
count = 0
break
fi
done
if [ "$count" != "0" ]; then
# /etc/init.d/keepalived stop
exit 1
else
exit 0
fi

2.3 keepalived.conf

! Configuration File for keepalived
global_defs {
notification_email {
zhouxiao@example.com
itsection@example.com
}
notification_email_from itsection@example.com
smtp_server mail.example.com
smtp_connect_timeout 30
router_id LVS_DEVEL
}

vrrp_script chk_nginx {
# script "killall -0 nginx"
script "/etc/keepalived/check_nginx.sh"
interval 2
weight -5
fall 3
rise 2
}

vrrp_instance VI_1 {
state MASTER
interface eth0
mcast_src_ip 172.29.88.224
virtual_router_id 51
priority 101
advert_int 2
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.29.88.222
}
track_script {
chk_nginx
}
}在其它备机BACKUP上,只需要改变 state MASTER -> state BACKUP,priority 101 -> priority 100,mcast_src_ip 172.29.88.224 -> mcast_src_ip 172.29.88.225即可。# service keepalived restart

2.4 配置选项说明

global_defs
[]notification_email : keepalived在发生诸如切换操作时需要发送email通知地址,后面的 smtp_server 相比也都知道是邮件服务器地址。也可以通过其它方式报警,毕竟邮件不是实时通知的。[/][]router_id : 机器标识,通常可设为hostname。故障发生时,邮件通知会用到[/]

vrrp_instance
[]state : 指定instance(Initial)的初始状态,就是说在配置好后,这台服务器的初始状态就是这里指定的,但这里指定的不算,还是得要通过竞选通过优先级来确定。如果这里设置为MASTER,但如若他的优先级不及另外一台,那么这台在发送通告时,会发送自己的优先级,另外一台发现优先级不如自己的高,那么他会就回抢占为MASTER[/][]interface : 实例绑定的网卡,因为在配置虚拟IP的时候必须是在已有的网卡上添加的[/][]mcast_src_ip : 发送多播数据包时的源IP地址,这里注意了,这里实际上就是在那个地址上发送VRRP通告,这个非常重要,一定要选择稳定的网卡端口来发送,这里相当于heartbeat的心跳端口,如果没有设置那么就用默认的绑定的网卡的IP,也就是interface指定的IP地址[/][]virtual_router_id : 这里设置VRID,这里非常重要,相同的VRID为一个组,他将决定多播的MAC地址[/][]priority : 设置本节点的优先级,优先级高的为master[/][]advert_int : 检查间隔,默认为1秒。这就是VRRP的定时器,MASTER每隔这样一个时间间隔,就会发送一个advertisement报文以通知组内其他路由器自己工作正常[/][]authentication : 定义认证方式和密码,主从必须一样[/][]virtual_ipaddress : 这里设置的就是VIP,也就是虚拟IP地址,他随着state的变化而增加删除,当state为master的时候就添加,当state为backup的时候删除,这里主要是有优先级来决定的,和state设置的值没有多大关系,这里可以设置多个IP地址[/][]track_script : 引用VRRP脚本,即在 vrrp_script 部分指定的名字。定期运行它们来改变优先级,并最终引发主备切换。[/]

vrrp_script
告诉 keepalived 在什么情况下切换,所以尤为重要。可以有多个 vrrp_script
[]script : 自己写的检测脚本。也可以是一行命令如killall -0 nginx[/][]interval 2 : 每2s检测一次[/][]weight -5 : 检测失败(脚本返回非0)则优先级 -5[/][]fall 2 : 检测连续 2 次失败才算确定是真失败。会用weight减少优先级(1-255之间)[/][]rise 1 : 检测 1 次成功就算成功。但不修改优先级[/]
 
这里要提示一下script一般有2种写法:
[]通过脚本执行的返回结果,改变优先级,keepalived继续发送通告消息,backup比较优先级再决定[/][]脚本里面检测到异常,直接关闭keepalived进程,backup机器接收不到advertisement会抢占IP[/]
 
上文 vrrp_script 配置部分,killall -0 nginx属于第1种情况,/etc/keepalived/check_nginx.sh属于第2种情况(脚本中关闭keepalived)。个人更倾向于通过shell脚本判断,但有异常时exit 1,正常退出exit 0,然后keepalived根据动态调整的 vrrp_instance 优先级选举决定是否抢占VIP:
[]如果脚本执行结果为0,并且weight配置的值大于0,则优先级相应的增加[/][]如果脚本执行结果非0,并且weight配置的值小于0,则优先级相应的减少[/]
其他情况,原本配置的优先级不变,即配置文件中priority对应的值。
提示:
[]优先级不会不断的提高或者降低[/][]可以编写多个检测脚本并为每个检测脚本设置不同的weight(在配置中列出就行)[/][]不管提高优先级还是降低优先级,最终优先级的范围是在[1,254],不会出现优先级小于等于0或者优先级大于等于255的情况[/][]在MASTER节点的 vrrp_instance 中 配置 nopreempt ,当它异常恢复后,即使它 prio 更高也不会抢占,这样可以避免正常情况下做无谓的切换[/]
以上可以做到利用脚本检测业务进程的状态,并动态调整优先级从而实现主备切换。
 
配置结束
在默认的keepalive.conf里面还有 virtual_server,real_server 这样的配置,我们这用不到,它是为lvs准备的。 notify 可以定义在切换成MASTER或BACKUP时执行的脚本,如有需求请自行google。

2.5 nginx配置

当然nginx没有什么可配置的,因为它与keepalived并没有联系。但记住,2台nginx服务器上的配置应该是完全一样的(rsync同步),这样才能做到对用户透明,nginx.conf 里面的 server_name 尽量使用域名来代替,然后dns解析这个域名到虚拟IP 172.29.88.222。
更多关于nginx内容配置请参考 这里

测试
根据上面的配置,初始化状态:172.29.88.224 (itoatest1,MASTER,101),172.29.88.222(itoatest2,BACKUP,100),nginx和keepalived都启动,虚拟IP 172.29.88.222 在 itoatest1 上:# 使用ip命令配置的地址,ifconfig查看不了
[root@itoatest1 nginx-1.6]# ip a|grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 172.29.88.224/24 brd 172.29.88.255 scope global eth0
inet 172.29.88.222/32 scope global eth0直接关闭 itoatest1 上的nginx:/usr/local/nginx-1.6/sbin/nginx -s stop:[root@localhost keepalived]# ip a|grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 172.29.88.224/24 brd 172.29.88.255 scope global eth0vip消失,漂移到 itoatest2:




同时可以看到两台服务器上 /var/log/messages:[size=16] itoatest1[/size]
Jun 5 16:44:01 itoatest1 Keepalived_vrrp[44875]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.29.88.222
Jun 5 16:44:06 itoatest1 Keepalived_vrrp[44875]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.29.88.222
Jun 5 16:44:46 itoatest1 Keepalived_vrrp[44875]: VRRP_Script(chk_nginx) failed
Jun 5 16:44:48 itoatest1 Keepalived_vrrp[44875]: VRRP_Instance(VI_1) Received higher prio advert
Jun 5 16:44:48 itoatest1 Keepalived_vrrp[44875]: VRRP_Instance(VI_1) Entering BACKUP STATE
Jun 5 16:44:48 itoatest1 Keepalived_vrrp[44875]: VRRP_Instance(VI_1) removing protocol VIPs.
Jun 5 16:44:48 itoatest1 Keepalived_healthcheckers[44874]: Netlink reflector reports IP 172.29.88.222 removed

[size=16] itoatest2[/size]
Jun 5 16:44:00 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Transition to MASTER STATE
Jun 5 16:44:00 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Received higher prio advert
Jun 5 16:44:00 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Entering BACKUP STATE
Jun 5 16:44:48 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) forcing a new MASTER election
Jun 5 16:44:48 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) forcing a new MASTER election
Jun 5 16:44:49 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Transition to MASTER STATE
Jun 5 16:44:50 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Entering MASTER STATE
Jun 5 16:44:50 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) setting protocol VIPs.
Jun 5 16:44:50 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.29.88.222
Jun 5 16:44:50 itoatest2 Keepalived_healthcheckers[35554]: Netlink reflector reports IP 172.29.88.222 added
Jun 5 16:44:55 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.29.88.222

你也可以通过在两台服务器上抓包来查看 优先级priority 的变化:[size=16] itoatest1 上[/size]
[size=16] 直接输出,或后加 -w itoatest-kl.cap存入文件用wireshark查看[/size]
# tcpdump -vvv -n -i eth0 dst 224.0.0.18 and src 172.29.88.224



参考
使用Keepalived实现Nginx高可用性
High Availability Support Based on keepalived
nginx+keepalived实现双机热备的高可用
LVS原理详解及部署之五:LVS+keepalived实现负载均衡&高可用
Keepalived双主模型中vrrp_script中权重改变故障排查
虚拟路由器冗余协议【原理篇】VRRP详解
Keepalived原理与实战精讲
原文分享地址:http://seanlook.com/2015/05/18/nginx-keepalived-ha/ 查看全部
公司内部 OA 系统要做线上高可用,避免单点故障,所以计划使用2台虚拟机通过 Keepalived 工具来实现 nginx 的高可用(High Avaiability),达到一台nginx入口服务器宕机,另一台备机自动接管服务的效果。
 1. Keepalived介绍
Keepalived是一个基于VRRP协议来实现的服务高可用方案,可以利用其来避免IP单点故障,类似的工具还有heartbeat、corosync、pacemaker。但是它一般不会单独出现,而是与其它负载均衡技术(如lvs、haproxy、nginx)一起工作来达到集群的高可用。


1.1 VRRP协议


VRRP全称 Virtual Router Redundancy Protocol,即 虚拟路由冗余协议。可以认为它是实现路由器高可用的容错协议,即将N台提供相同功能的路由器组成一个路由器组(Router Group),这个组里面有一个master和多个backup,但在外界看来就像一台一样,构成虚拟路由器,拥有一个虚拟IP(vip,也就是路由器所在局域网内其他机器的默认路由),占有这个IP的master实际负责ARP相应和转发IP数据包,组中的其它路由器作为备份的角色处于待命状态。master会发组播消息,当backup在超时时间内收不到vrrp包时就认为master宕掉了,这时就需要根据VRRP的优先级来选举一个backup当master,保证路由器的高可用。
 
在VRRP协议实现里,虚拟路由器使用 00-00-5E-00-01-XX 作为虚拟MAC地址,XX就是唯一的 VRID (Virtual Router IDentifier),这个地址同一时间只有一个物理路由器占用。在虚拟路由器里面的物理路由器组里面通过多播IP地址 224.0.0.18 来定时发送通告消息。每个Router都有一个 1-255 之间的优先级别,级别最高的(highest priority)将成为主控(master)路由器。通过降低master的优先权可以让处于backup状态的路由器抢占(pro-empt)主路由器的状态,两个backup优先级相同的IP地址较大者为master,接管虚拟IP。
nginx-keepalived-vrrp.jpg

与heartbeat/corosync等比较:
Heartbeat、Corosync、Keepalived这三个集群组件我们到底选哪个好,首先我想说明的是,Heartbeat、Corosync是属于同一类型,Keepalived与Heartbeat、Corosync,根本不是同一类型的。Keepalived使用的vrrp协议方式,虚拟路由冗余协议 (Virtual Router Redundancy Protocol,简称VRRP);Heartbeat或Corosync是基于主机或网络服务的高可用方式;简单的说就是,Keepalived的目的是模拟路由器的高可用,Heartbeat或Corosync的目的是实现Service的高可用。

所以一般Keepalived是实现前端高可用,常用的前端高可用的组合有,就是我们常见的LVS+Keepalived、Nginx+Keepalived、HAproxy+Keepalived。而Heartbeat或Corosync是实现服务的高可用,常见的组合有Heartbeat v3(Corosync)+Pacemaker+NFS+Httpd 实现Web服务器的高可用、Heartbeat v3(Corosync)+Pacemaker+NFS+MySQL 实现MySQL服务器的高可用。总结一下,Keepalived中实现轻量级的高可用,一般用于前端高可用,且不需要共享存储,一般常用于两个节点的高可用。而Heartbeat(或Corosync)一般用于服务的高可用,且需要共享存储,一般用于多节点的高可用。这个问题我们说明白了。

又有博友会问了,那heartbaet与corosync我们又应该选择哪个好啊,我想说我们一般用corosync,因为corosync的运行机制更优于heartbeat,就连从heartbeat分离出来的pacemaker都说在以后的开发当中更倾向于corosync,所以现在corosync+pacemaker是最佳组合。


1.2 Keepalived + nginx


keepalived可以认为是VRRP协议在Linux上的实现,主要有三个模块,分别是core、check和vrrp。core模块为keepalived的核心,负责主进程的启动、维护以及全局配置文件的加载和解析。check负责健康检查,包括常见的各种检查方式。vrrp模块是来实现VRRP协议的。本文基于如下的拓扑图:
                   +-------------+
| uplink |
+-------------+
|
+
MASTER keep|alived BACKUP
172.29.88.224 172.29.88.222 172.29.88.225
+-------------+ +-------------+ +-------------+
| nginx01 |----| virtualIP |----| nginx02 |
+-------------+ +-------------+ +-------------+
|
+------------------+------------------+
| | |
+-------------+ +-------------+ +-------------+
| web01 | | web02 | | web03 |
+-------------+ +-------------+ +-------------+
2. keepalived实现nginx高可用


2.1安装


我的环境是CentOS 6.2 X86_64,直接通过yum方式安装最简单:
# yum install -y keepalived
# keepalived -v
Keepalived v1.2.13 (03/19,2015)


2.2 nginx监控脚本


该脚本检测ngnix的运行状态,并在nginx进程不存在时尝试重新启动ngnix,如果启动失败则停止keepalived,准备让其它机器接管。
/etc/keepalived/check_nginx.sh :
#!/bin/bash
counter=$(ps -C nginx --no-heading|wc -l)
if [ "${counter}" = "0" ]; then
/usr/local/bin/nginx
sleep 2
counter=$(ps -C nginx --no-heading|wc -l)
if [ "${counter}" = "0" ]; then
/etc/init.d/keepalived stop
fi
fi
你也可以根据自己的业务需求,总结出在什么情形下关闭keepalived,如 curl 主页连续2个5s没有响应则切换:
#!/bin/bash
# curl -IL http://localhost/member/login.htm
# curl --data "memberName=fengkan&password=22" http://localhost/member/login.htm

count = 0
for (( k=0; k<2; k++ ))
do
check_code=$( curl --connect-timeout 3 -sL -w "%{http_code}\\n" http://localhost/login.html -o /dev/null )
if [ "$check_code" != "200" ]; then
count = count +1
continue
else
count = 0
break
fi
done
if [ "$count" != "0" ]; then
# /etc/init.d/keepalived stop
exit 1
else
exit 0
fi


2.3 keepalived.conf


! Configuration File for keepalived
global_defs {
notification_email {
zhouxiao@example.com
itsection@example.com
}
notification_email_from itsection@example.com
smtp_server mail.example.com
smtp_connect_timeout 30
router_id LVS_DEVEL
}

vrrp_script chk_nginx {
# script "killall -0 nginx"
script "/etc/keepalived/check_nginx.sh"
interval 2
weight -5
fall 3
rise 2
}

vrrp_instance VI_1 {
state MASTER
interface eth0
mcast_src_ip 172.29.88.224
virtual_router_id 51
priority 101
advert_int 2
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.29.88.222
}
track_script {
chk_nginx
}
}
在其它备机BACKUP上,只需要改变 state MASTER -> state BACKUP,priority 101 -> priority 100,mcast_src_ip 172.29.88.224 -> mcast_src_ip 172.29.88.225即可。
# service keepalived restart


2.4 配置选项说明


global_defs
    []notification_email : keepalived在发生诸如切换操作时需要发送email通知地址,后面的 smtp_server 相比也都知道是邮件服务器地址。也可以通过其它方式报警,毕竟邮件不是实时通知的。[/][]router_id : 机器标识,通常可设为hostname。故障发生时,邮件通知会用到[/]


vrrp_instance
    []state : 指定instance(Initial)的初始状态,就是说在配置好后,这台服务器的初始状态就是这里指定的,但这里指定的不算,还是得要通过竞选通过优先级来确定。如果这里设置为MASTER,但如若他的优先级不及另外一台,那么这台在发送通告时,会发送自己的优先级,另外一台发现优先级不如自己的高,那么他会就回抢占为MASTER[/][]interface : 实例绑定的网卡,因为在配置虚拟IP的时候必须是在已有的网卡上添加的[/][]mcast_src_ip : 发送多播数据包时的源IP地址,这里注意了,这里实际上就是在那个地址上发送VRRP通告,这个非常重要,一定要选择稳定的网卡端口来发送,这里相当于heartbeat的心跳端口,如果没有设置那么就用默认的绑定的网卡的IP,也就是interface指定的IP地址[/][]virtual_router_id : 这里设置VRID,这里非常重要,相同的VRID为一个组,他将决定多播的MAC地址[/][]priority : 设置本节点的优先级,优先级高的为master[/][]advert_int : 检查间隔,默认为1秒。这就是VRRP的定时器,MASTER每隔这样一个时间间隔,就会发送一个advertisement报文以通知组内其他路由器自己工作正常[/][]authentication : 定义认证方式和密码,主从必须一样[/][]virtual_ipaddress : 这里设置的就是VIP,也就是虚拟IP地址,他随着state的变化而增加删除,当state为master的时候就添加,当state为backup的时候删除,这里主要是有优先级来决定的,和state设置的值没有多大关系,这里可以设置多个IP地址[/][]track_script : 引用VRRP脚本,即在 vrrp_script 部分指定的名字。定期运行它们来改变优先级,并最终引发主备切换。[/]


vrrp_script
告诉 keepalived 在什么情况下切换,所以尤为重要。可以有多个 vrrp_script
    []script : 自己写的检测脚本。也可以是一行命令如killall -0 nginx[/][]interval 2 : 每2s检测一次[/][]weight -5 : 检测失败(脚本返回非0)则优先级 -5[/][]fall 2 : 检测连续 2 次失败才算确定是真失败。会用weight减少优先级(1-255之间)[/][]rise 1 : 检测 1 次成功就算成功。但不修改优先级[/]

 
这里要提示一下script一般有2种写法:
    []通过脚本执行的返回结果,改变优先级,keepalived继续发送通告消息,backup比较优先级再决定[/][]脚本里面检测到异常,直接关闭keepalived进程,backup机器接收不到advertisement会抢占IP[/]

 
上文 vrrp_script 配置部分,killall -0 nginx属于第1种情况,/etc/keepalived/check_nginx.sh属于第2种情况(脚本中关闭keepalived)。个人更倾向于通过shell脚本判断,但有异常时exit 1,正常退出exit 0,然后keepalived根据动态调整的 vrrp_instance 优先级选举决定是否抢占VIP:
    []如果脚本执行结果为0,并且weight配置的值大于0,则优先级相应的增加[/][]如果脚本执行结果非0,并且weight配置的值小于0,则优先级相应的减少[/]

其他情况,原本配置的优先级不变,即配置文件中priority对应的值。
提示:
    []优先级不会不断的提高或者降低[/][]可以编写多个检测脚本并为每个检测脚本设置不同的weight(在配置中列出就行)[/][]不管提高优先级还是降低优先级,最终优先级的范围是在[1,254],不会出现优先级小于等于0或者优先级大于等于255的情况[/][]在MASTER节点的 vrrp_instance 中 配置 nopreempt ,当它异常恢复后,即使它 prio 更高也不会抢占,这样可以避免正常情况下做无谓的切换[/]

以上可以做到利用脚本检测业务进程的状态,并动态调整优先级从而实现主备切换。
 
配置结束
在默认的keepalive.conf里面还有 virtual_server,real_server 这样的配置,我们这用不到,它是为lvs准备的。 notify 可以定义在切换成MASTER或BACKUP时执行的脚本,如有需求请自行google。


2.5 nginx配置


当然nginx没有什么可配置的,因为它与keepalived并没有联系。但记住,2台nginx服务器上的配置应该是完全一样的(rsync同步),这样才能做到对用户透明,nginx.conf 里面的 server_name 尽量使用域名来代替,然后dns解析这个域名到虚拟IP 172.29.88.222。
更多关于nginx内容配置请参考 这里


  1. 测试


根据上面的配置,初始化状态:172.29.88.224 (itoatest1,MASTER,101),172.29.88.222(itoatest2,BACKUP,100),nginx和keepalived都启动,虚拟IP 172.29.88.222 在 itoatest1 上:
# 使用ip命令配置的地址,ifconfig查看不了
[root@itoatest1 nginx-1.6]# ip a|grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 172.29.88.224/24 brd 172.29.88.255 scope global eth0
inet 172.29.88.222/32 scope global eth0
直接关闭 itoatest1 上的nginx:/usr/local/nginx-1.6/sbin/nginx -s stop:
[root@localhost keepalived]# ip a|grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 172.29.88.224/24 brd 172.29.88.255 scope global eth0
vip消失,漂移到 itoatest2:
nginx-keepalived-vip.png

同时可以看到两台服务器上 /var/log/messages:
[size=16] itoatest1[/size]
Jun 5 16:44:01 itoatest1 Keepalived_vrrp[44875]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.29.88.222
Jun 5 16:44:06 itoatest1 Keepalived_vrrp[44875]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.29.88.222
Jun 5 16:44:46 itoatest1 Keepalived_vrrp[44875]: VRRP_Script(chk_nginx) failed
Jun 5 16:44:48 itoatest1 Keepalived_vrrp[44875]: VRRP_Instance(VI_1) Received higher prio advert
Jun 5 16:44:48 itoatest1 Keepalived_vrrp[44875]: VRRP_Instance(VI_1) Entering BACKUP STATE
Jun 5 16:44:48 itoatest1 Keepalived_vrrp[44875]: VRRP_Instance(VI_1) removing protocol VIPs.
Jun 5 16:44:48 itoatest1 Keepalived_healthcheckers[44874]: Netlink reflector reports IP 172.29.88.222 removed

[size=16] itoatest2[/size]
Jun 5 16:44:00 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Transition to MASTER STATE
Jun 5 16:44:00 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Received higher prio advert
Jun 5 16:44:00 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Entering BACKUP STATE
Jun 5 16:44:48 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) forcing a new MASTER election
Jun 5 16:44:48 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) forcing a new MASTER election
Jun 5 16:44:49 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Transition to MASTER STATE
Jun 5 16:44:50 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Entering MASTER STATE
Jun 5 16:44:50 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) setting protocol VIPs.
Jun 5 16:44:50 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.29.88.222
Jun 5 16:44:50 itoatest2 Keepalived_healthcheckers[35554]: Netlink reflector reports IP 172.29.88.222 added
Jun 5 16:44:55 itoatest2 Keepalived_vrrp[35555]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.29.88.222

你也可以通过在两台服务器上抓包来查看 优先级priority 的变化:
[size=16] itoatest1 上[/size]
[size=16] 直接输出,或后加 -w itoatest-kl.cap存入文件用wireshark查看[/size]
# tcpdump -vvv -n -i eth0 dst 224.0.0.18 and src 172.29.88.224
nginx-keepalived-prio.png

参考
使用Keepalived实现Nginx高可用性
High Availability Support Based on keepalived
nginx+keepalived实现双机热备的高可用
LVS原理详解及部署之五:LVS+keepalived实现负载均衡&高可用
Keepalived双主模型中vrrp_script中权重改变故障排查
虚拟路由器冗余协议【原理篇】VRRP详解
Keepalived原理与实战精讲
原文分享地址:http://seanlook.com/2015/05/18/nginx-keepalived-ha/
架构,又名软件架构,是有关软件整体结构与组件的抽象描述,用于指导大型软件系统各个方面的设计。架构描述语言(ADL)用于描述软件的体系架构。现在已有多种架构描述语言,如Wright(由卡内基梅隆大学开发),Acme(由卡内基梅隆大学开发),C2(由UCI开发),Darwin(由伦敦帝国学院开发)。ADL的基本构成包括组件、连接器和配置。