当前位置: 首页 > 科技观察

不停机应用发布的思考与初步认识

时间:2023-03-20 17:11:45 科技观察

应用发布,简单来说就是将开发好的系统功能部署到生产环境中,正常为用户提供服务。传统的应用发布步骤一般采用“三步曲”:第一步:停止应用第二步:更新应用第三步:启动应用那么你一定会问,从停止应用到启动应用,是不是系统功能不正常?这是正确的。应用发布过程中,可能会出现页面白屏、访问超时等各种异常,且一般持续时间较长,因此发布时间基本集中在凌晨。如果您比较讲究,可以添加友情提示“系统维护中,请稍后访问!”。这些情况大多发生在传统行业。究其原因,可能是不必要的,因为:传统行业的生意一般都集中在白天,也就是说,清晨基本没有生意或不重要的生意。就算凌晨不能用这些功能也没关系,第二天回来就好了,客户也不会跑掉。但事实真的如此吗?如今,越来越多的传统行业正在向互联网服务模式转型。其服务的主要特点:为客户提供“全天候”不间断的“优质”“在线”服务。我们来分解关键词:“allday”代表任何时间“Quality”代表客户体验“Online”代表在线自助服务所以,一个优质的客服必然对服务可用性提出更高的要求,而传统的宕机发布不仅会对客户的使用造成影响,还会改变方向,给企业造成间接的经济损失。例如:这就是由于糟糕的客户体验导致客户流失的全部原因吗?不!作为一名曾是运维工程师的运维工程师,每天清晨发布一顿饭是家常便饭,时不时还要来一场8小时的“长途旅行”,而我的身体直接被掏空,第二天还在“补血”。》,还会被各种骚扰电话狂轰滥炸,简直就是一场噩梦。由此可见,应用发布不间断的重要性可以帮助我们:第一,应用发布过程中在线服务持续可用,提升服务可用性;第二,可以在白天发布,也可以随时发布,提高了运维人员的灵活性。不停机发布,从字面上看,应用发布过程中服务不中断很容易理解,但是仔细想想,原来应用发布过程中,无论如何都会中断服务,所以应用后发布完成后,将通过网络阻断外部流量,先进行核心或公共功能的内部验证。确保没有问题,解除网络屏蔽,对外提供服务。现在呢?应用程序发布后直接?不需要内部或小流量验证?想必每个人的答案都不一样。对此,对于应用的不间断发布能力,可以简单定义三个成熟度等级。成熟度一级:应用发布过程中业务不中断。成熟度二级:应用发布过程中服务不中断,单体应用功能可在内部或小流量优先验证。成熟度三级:应用发布过程中服务不中断,多应用(联动)功能可在内部或小流量优先验证。注:不同成熟度等级对技术能力的要求不同。建议通过逐步演进的方式来提高成熟度,在演进过程中验证不同的技术能力,从而持续改进。有人会说蓝绿发布,或者有人会说滚动发布,灰度发布可以实现以上能力。但实际上,这些答案并不准确,或者说并不全面。虽有重叠,但不能覆盖。既然说到了发布模式,那我们就简单比较一下几种发布模式的优缺点。注:大多数技术文章中都提到,以上任何一种发布方式都可以实现用户无感知的应用发布,但在实际情况下,这还不够,还需要结合一些辅助手段来实现达到。综合以上几种发布模式的优缺点,如果你的组织在基础设施技术能力方面已经非常成熟,那么灰度发布一定是最好的选择,但如果还处于起步阶段,就未必了,而蓝-绿色发布高资源投入不是一个很好的选择。只剩下滚动发布了,但是滚动发布的发布策略会比较复杂,尤其是在容器环境下,同一个应用的多个服务实例的滚动策略需要分别实现。因此,前期可以选择折中的方式,即单独搭建预发布验证环境。应用架构需要与生产环境保持一致,但容量可以最小化。通常,一个应用程序至少有2个服务实例。这样,我们就可以在将应用发布到生产环境之前,先将应用发布到生产预验证环境。发布后,仅对内部用户可见。验证通过后,我们就可以将完整的应用发布到生产环境中了。2.不间断应用发布是综合能力。定义发布模型后,需要逐步确定涉及到哪些技术组件,明确整个解决方案中各个技术组件的职责边界,使它们能够协同工作。部分主要技术组件如下:应用管理平台主要负责控制整个应用发布流程,整合调度不同的技术组件,协同完成应用的不间断发布。负载均衡(第4层)主要负责服务请求的流量接入,可以根据识别到的流量特征将负载分配到不同的负载均衡(第7层)。负载均衡(第7层)主要负责服务请求的流量路由,可以根据识别出的流量特征,将路由分配给同一应用的不同实例。容器/虚拟机平台主要负责容器/虚拟机的资源管理,包括容器/虚拟机的创建、更新和销毁。域名解析系统主要负责域名地址管理,包括域名注册、更新、解析等,提供用户访问应用或应用间访问等寻址能力。注册中心主要负责服务资源管理,包括服务注册、更新、注销等,同时为服务请求者提供发现服务提供者的能力。在明确了技术组件之后,还需要对技术组件进行合理的架构规划,以适应不同的网络架构需求。这一次,我们将重点放在负载均衡上。一方面,它是负责处理流量的核心技术组件。另一方面,网络架构的差异可能对其部署架构的影响最大。在传统的网络架构环境中,出于网络安全或其他方面的考虑,通常会划分多个不同的网络区域,网络区域之间的访问需要通过设置防火墙的访问策略来实现互通。但是这种方式必然会影响到应用服务之间点对点的直接访问。主要原因是在虚拟机或容器环境中,应用的IP地址可能会发生变化,导致无法提前指定防火墙的访问策略。所以一般会考虑使用负载均衡(代理模式)来解决这个问题。建议前期优先选择方案3。虽然较长的链路会略微影响性能,但这种部署方案已经比较成熟。一方面可以避免流量负载不均的问题,另一方面应用改造的成本会比较低。注意:除了网络区域隔离的这种情况,在一些网络架构中,不同的容器集群也是无法访问的,所以也是适用的。此外,除非必要,还应尽量减少跨网络区域或跨容器集群访问。例如,优先考虑容器集群内的路由访问,推荐跨网域交互频繁的应用服务迁移到同网域。负载均衡一般分为四层模式和七层模式,四层更关注流量负载,七层更关注流量路由。一般建议分层部署负载均衡(第4层)和负载均衡(第7层),以充分发挥各自的优势。建议前期优先选择方案2。虽然无法实现多容器集群间的全局流量调度,但对于目前可观察性和故障排除能力尚不完善的组织而言,通过物理隔离降低运维难度也是一个不错的选择。基于以上架构决策,最终的全局流量链路大致如下。默认情况下,数据中心之间的流量是隔离的,即单个数据中心内的流量是汇聚的,但可以根据实际情况进行选择性释放。3、应用不间断发布的基础是服务路由。在这里,我们可以将应用服务分为两个角色,服务请求者或者服务提供者,服务请求者通过不同的寻址方式最终访问到服务提供者的形式可以称为服务路由。服务路线可分为南北向和东西向。南北方向:服务请求者->负载均衡(第4层)->负载均衡(第7层)->服务提供者东西方向:服务请求者->服务提供者不难发现,主要区别在于北-south服务请求者需要使用负载均衡(代理方式)访问服务提供者,而东西向服务请求者直接访问服务提供者。注意:域名解析结果会缓存在本地,可以缓解域名解析服务的压力,但是缓存时间要根据不同的服务等级来评估,否则会延长解析地址切换和故障转移的时间。如果可以,建议使用httpdns来解决本地缓存问题。但无论是南北向还是东西向,服务提供者都必须让服务请求者在被访问之前知道或可见。常见的有两种方式,一种不依赖注册中心,一种依赖Registry的。如果当前应用架构中没有使用微服务框架,即不依赖注册中心,服务提供者可以手动或自动将服务注册到负载均衡器上,服务请求者直接调用负载均衡器。如果当前应用架构已经使用了微服务框架,即依赖注册中心,服务提供者可以在注册中心进行服务注册,服务请求者可以在注册中心进行服务发现,或者负载均衡器可以在注册中心进行服务发现。服务请求者直接调用负载均衡器。注:在多注册中心场景下,异构注册中心的服务发现可以通过统一的注册中心完成。另外,我们还会对同一个应用的不同服务实例进行分组,分组策略可以根据不同的条件来确定,比如:不同的环境,不同的版本等。假设根据不同环境的条件(预productionenvironmentandproductionenvironment),部署在预发布验证环境的应用服务可以划分为预发布组,部署在生产环境的应用服务可以划分为在线组。然后通过配置路由策略发送给负载均衡或者应用服务,可以实现简单的服务路由。例如:默认不允许不同群之间的服务路由,但在特殊场景下,允许预发群服务路由到在线群。注意:如果服务请求者是前端页面或客户端,也可以对前端流量进行分组。例如,根据网络环境,可以将接入公司WI-FI网络环境的流量识别为预发组。4.应用不停止发布的核心是如何优雅的停止应用。仅服务路由可能还不够。虽然解决了大部分问题,但离成功还有一步之遥。前面我们提到应用的发布一定是用户察觉不到的,那么如果在应用发布的过程中出现了瞬间或短时间的中断,恰好用户正在使用,用户会察觉到吗?不过,如果你觉得5分钟的在线服务中断是可以忍受的,那我也只能呵呵了。但是我相信大部分互联网服务模式的龙头企业可能都承受不了5秒,更别提一发布就停5分钟了。那我们先分析一下为什么会出现瞬时或短时中断:在服务请求处理完成之前,强行停止了应用(例如:kill-9进程,运维必备),导致正在处理的请求中无法处理。正常返回。虽然服务提供者已经停止,但是服务请求者没有得到通知,服务请求者仍然继续访问停止的服务提供者,导致异常。鉴于以上两种情况,有必要对南北和东西方向进行探讨。在南北方向上,通过服务请求者和服务提供者之间的负载均衡来进行服务路由。所以在发布应用的时候需要对负载均衡做一些特殊的处理。1)在负载均衡方面,对应用服务实例一个一个进行流量阻塞。此阻止只会影响新请求。服务请求处理完成后,执行如下操作:容器:销毁服务实例,并创建新版本的服务实例虚拟机:更新服务实例,更新后解除阻塞。注:商业负载均衡一般都支持Gracefuloffline/online。2)因为服务请求者的请求会先经过负载均衡,负载均衡的成员节点只需要保证至少有一个服务实例存在即可。这种场景不需要通知,所以不适用。在东西方向上,服务路由直接在服务请求者和服务提供者之间进行。因此,在发布应用时,需要分别对服务请求者和服务提供者进行一些特殊的处理,而这些处理方式受到应用框架的限制,这里先介绍一个通用的框架,即Springboot+Eureka应用框架,在服务提供者上实现了Shutdownhook,即等待服务请求处理完毕再停止应用。在服务提供者停止之前,需要通知所有服务请求者,通知完成后应停止应用程序。第二点看似很简单,实际上会比较复杂。我做了一些降级以权衡收益的价值和转型的成本。方法一:最多中断5秒step1:依赖spring-boot-starter-actuator组件暴露/shutdown端点管理:endpoint:shutdown:enabled:trueendpoints:web:exposure:include:shutdownstep2:调整Eureka配置参数,调整后会分别增加Eureka客户端和服务端的性能压力Step3:在容器销毁服务实例或虚拟机更新服务实例之前,请求如下地址停止应用服务实例curl-Xhttp://应用服务地址/actuator/shutdown方法二:不中断(不通知)step1:依赖spring-boot-starter-actuator组件,暴露/shutdown和/service-registry端点管理:endpoint:shutdown:enabled:true端点:web:exposure:include:shutdown,service-registrystep2:调整Eureka配置参数,该调整会增加Eurekaclient和ser的性能压力ver分别step3:在容器销毁服务实例或者虚拟机更新服务实例之前,请求如下地址使应用服务实例下线curl-Xhttp://应用服务地址/actuator/service-registry?status=DOWN注意:此时服务提供者仍然可以提供服务,但是再次获取服务实例的服务请求者将不会再次获取服务实例。Step4:服务请求者最多等待5秒后会更新服务列表,所以在完成以上操作后,可以休眠5秒,然后请求如下地址停止应用服务实例curl-Xhttp://应用服务地址/actuator/shutdown注意:eureka.client.registry-fetch-interval-seconds+ribbon.ServerListRefreshInterval=5秒。方法三:不中断(通知)step1:依赖spring-boot-starter-actuator组件暴露/shutdown和/service-registry端点管理:endpoint:shutdown:enabled:trueendpoints:web:exposure:include:shutdown,service-registrystep2:调整Eureka配置参数,会增加Eureka服务器的性能压力step3:容器销毁服务实例或虚拟机更新服务实例前,请求如下地址使应用服务实例下线curl-Xhttp://applicationserviceaddress/actuator/service-registry?status=DOWN注意:此时服务提供者仍然可以提供服务,但是再次获取服务实例的服务请求者将无法获取服务再次实例。Step4:在注册中心记录当前订阅服务实例的服务请求者列表,并通知他们根据列表立即重新获取最新的服务实例。通知完成后,请求以下地址停止应用服务实例curl-Xhttp://以上三种应用服务地址/actuator/shutdown的方式,可以结合价值收益和改造成本进行权衡。接受瞬时中断的可以选择方法一,对技术有极致追求的可以选择方法三,如果两者都不是,那么就选择方法二。注意:各个应用服务的Eureka配置参数可能不完全统一,可能会导致配置管理成本大幅增加,但如果能统一的话,第二种方式还是不错的选择。5、满足以上条件和能力后,应用不停机发布的基本框架已经形成,但是这样一来,应用发布是不是可以做到不停机?就这么简单,我们在开发中还是需要遵循一些规范,但是如果满足这些规范,可能会增加一些我们的开发成本。因此,并不是说每次发布应用都要强制实现不停发布,而是要做出合理的权衡。然而,一个好的系统设计必须能够遵循开发规范而不增加太多的开发成本。下面列出了一些常用的开发规范,可以根据实际情况进行调整。目的是尽可能做到向上兼容,无论是接口更新还是数据库更新。1)接口允许新增字段,必填字段需要设置默认值;允许原始字段扩展长度或添加新的字典值;不允许修改原始字段的语义和格式;不允许删除原有字段;不兼容时,应添加接口;接口下线前,需要保证没有调用者。2)数据库允许新增字段,必填字段需要设置默认值;允许原始字段扩展长度或添加新的字典值;不允许修改原始字段的语义和格式;原有字段不允许删除;当它们不兼容时,应该添加一个新表;新旧表共存期间,需要聚合数据统计;在旧表下线之前,需要进行数据迁移。3)新旧格式的兼容性是报文的优先级;如果不兼容,生产者和消费者可以共同商定一个新话题;如果生产者无法就新主题达成一致,消费者可以添加消息分发层来重命名主题。4)缓存优先考虑新旧格式的兼容;最后感谢您耐心阅读到这里。整篇文章主要针对应用的不间断发布,从为什么要做,可以带来什么价值,到应该怎么做,需要关心哪些方面进行了简单的讲解。主要目的是让大家对应用不间断发布的框架有一个大概的了解。实现应用不间断发布的手段不止文中提到的这些,涉及的技术组件可能不止这些,但解决方案基本相同。具体的技术实现方式可以结合自身的架构环境。适应和调整。