本文主要介绍微服务架构流量分布(微服务流量着色),下面一起看看微服务架构流量分布(微服务流量着色)相关资讯。
简介:绝大多数的软件生产安全事故都发生在生产线的发布阶段,虽然遵循灰度、可观察、可滚动的生产安全斧的行业惯例,可以最大限度地避免生产代码的问题对用户造成的影响。但仍然解决了并发流量情况下的短时流量损失问题。因此,本文将重点研究如何解决释放过程中的流量损失问题,实现释放过程中上下行效果的损失。?
作者|程普来源|阿里开发者官方账号
绝大多数的软件生产安全事故都发生在应用线的发布阶段,虽然遵循灰度、可观察、可滚动的安全生产三轴的行业惯例,可以最大限度地避免发布过程中应用代码问题对用户造成的影响,但仍然解决了并发流量情况下的短时流量损失问题。因此,本文将重点研究如何解决释放过程中的流量损失问题,实现释放过程中上下行效果的损失。
据统计,装卸过程中经常发生事故,有时是因为编码问题。但是有时候我们会发现,虽然代码本身没有问题,但是在线上线下发布的过程中还是会出现短时间的服务调试错误,比如连接被拒绝,调试时没有实例。相关问题产生的原因,有相关发布经验的同学可能或多或少都有所了解,而经济学家发现,这类问题在流量高峰时尤为明显,在深夜流量较低的时候比较少见,所以很多人为了避免网络发布事故,选择在深夜发布。本节将介绍这些问题背后的真正原因,以及业界相应的设计案例。交通损失的常见原因包括但不限于以下几种:
服务规律及时离线:服务消费者在注册时感知到服务列表存在延迟,导致服务消费者在注销特定实例后的一定时间内仍然调整离线实例而导致的请求错误。缓慢初始化:接收线路上的流量应该刚刚开始加载初始资源。由于流量太大,初始化过程缓慢,响应流量请求超时,阻塞,资源耗尽,导致机器一开始就停了。注册太早:服务存在资源加载不同步的问题。当服务没有完全初始化时,就在注册中注册,导致请求响应慢,超时出错的现象。发布状态和运输状态不正确:kubernetes的滚动发布功能被启用为发布,因为与kubernetes 滚动释放是通过检查是否应该启动特定终端作为准备就绪的标志来触发的。批量实例发布,但是在微服务应用中,只有在应该完成服务注册的情况下才能提供服务调整。因此,在某些情况下,新应用程序在注册之前会处于离线状态,从而导致服务可用。接下来,将分别介绍如何避免离线和在线过程中的流量损失。
无损离线由于微服务应用本身的调用特性,在高并发下,服务提供者的应用实例直接离线,会导致服务消费者的应用实例无法实时感知下游实例的实时状态,所以会继续将请求转发给离线实例,造成请求错误和流量损失。
?
图1春云根据《消法》及时感知提供者线下服务。
例如,对于spring cloud,应该如上面的图1所示。当两个实例a 而a是离线的,因为spring云框架旨在平衡可用性和性能,消费者会默认注册30s来拉最新的服务列表,所以实例a的离线无法实时感知。当流量较大时,消费者会继续通过本地缓存调整离线实例a,造成流量损失。基于上述背景,业界提出了相应的输线下(也称优雅线下)技术案例来应对上述问题。本节将介绍一些业界主流的线下技术。
针对这类问题,业内普遍的解决方案是将应用更新过程分为手动接流量、停止应用更新重启三个步骤。客户端通过手动操作来避免调用离线实例简单有效,但是有很多限制:不仅需要流量控制能力来实现实时流量拣选,还需要人工判断来确保在途请求在停止应用之前已经处理完毕。这种需要人工干预的方法,运维复杂度高,只适合小规模应用。无法解决当前云原生架构中实例离线过程中的流量损失问题,如自动弹性伸缩、滚动升级等。本节将介绍一些业界在云原生场景下应用的无损离线技术方案。
1个活动通知
一般注册中心会提供一个主动注销接口,供微服务应用在正常关闭时调用,以便离线实例及时在注册中心更新状态。在一些基于事件感知注册服务列表的微服务框架中的主动注销,如dubbo,可以使上游服务消费者感知到提供者 以避免对脱机实例的后续调用。而对于spring cloud等微服务框架的服务消费者,则是通过定时拉取服务清单来实现的。虽然线下实例已经通过注册中心的主动注销接口更新了自己在注册中心的申请状态信息,但是由于上游消费者下次需要拉取注册中心的申请列表,消费者感知注册中心实例的变化会有延迟。在高流量、高并发的场景下,当实例离线时,仍然没有实现流量无损的方法。由于现有的消费者实例不可能通过注册中心实时感知下游服务商的变化,业界提出用主动通知来解决这类问题。主动通知过程如下面的图2所示:
?
图2损失线案例
如图2所示,服务提供商b的实例不能被上游消费者a实时感知,以避免在离线时调用离线实例的问题。在接收到离线命令之前,提供者b会在离线等待阶段接收到的请求的返回值中添加特殊标记,让服务消费者在接收到返回值并识别相关标记后,主动拉一次注册中心的服务实例,从而实时感知实例b的最新状态,让服务消费者实时感知服务提供者的离线状态。
2适应性等待
在不同并发的场景下,主动通知可以解决大部分离线流量受损的问题。但是对于并发流量应该离线的场景,如果主动完成通知,可能还会有一些在途请求需要处理后才能离线,否则这些流量会得到正常响应。为了解决这种在途请求的问题,可以通过在处理所有在途请求之前给下行线一个自适应等待机制来实现流量损失。
?
图3自适应等待机制
如上面的图3所示,自适应等待机制通过计算是否还有未处理的传输中的请求来确定注销时间,以便在注销之前处理完所有剩余的请求。
无损在线延迟加载是软件框架设计过程中最常见的策略。例如,在spring cloud框架中,默认情况下会初始化ribbon组件的pull服务列表,直到服务被调优。例如,下面的图4显示了通过在spring cloud中调优?resttemplate对远程服务进行的第一次和第二次调优的耗时比较:
?
图4应该开始资源初始化,并且应该匹配正常操作期间的耗时情况。
从图4的结果可以看出,由于一些资源初始化,第二次调优的耗时是正常情况下的几倍。因此,在线发布新的应用程序来直接处理流量是非常容易的,例如对卷请求的响应速度慢、资源拥塞和应用程序宕机。
业界针对上述亏损上线场景提出了以下一系列解决方案,包括延迟注册、流量服务预热、就绪检查等。详细完整的案例如下图5所示:
?
图5受损线路的整体情况
1延迟注册
对于初始化过程中需要异步加载资源的复杂启动过程,由于注册通常与初始化过程同步,所以在应用程序完全初始化之前,已经在注册中注册了应用程序以供外部使用者调整。此时,由于资源加载不完全,直接调整可能会导致请求错误。通过设置延迟注册,您可以让应用程序等待,直到它完全初始化。注册对外提供服务。比如开源的微服务治理框架dubbo,最初就提供了延迟注册功能[1]。
2小流量服务预热
在线发布的场景中,很多时候新启动的冷系统直接处理卷请求,可能是由于系统内部资源初始化不完全,超时、阻塞,甚至报错,导致刚发布就宕机等在线发布事故。为了避免这类问题,业界根据不同的框架类型和对应的特性设计了不同的对策,比如写脚本促进jvm预热,ababa group 的内部hsf(高速框架)分批发布,延迟注册,通过模拟脚本预热模拟请求,预热流量。本节将介绍最合适的气流预热方法。
与一般场景相比,新发布的微服务应该与其他正常实例共享在线总qps。流量预热方法通过根据每个服务提供者实例的启动时间计算服务消费端的权重,结合负载均衡算法控制刚启动的入局流量随启动时间逐渐增加到正常水平的过程,来帮助刚启动的入局预热。详细的qps随时间的变化曲线如图6所示:
图6气流预热过程的qps曲线
开源dubbo实现的流量服务预热过程原理如下图7所示:
?
图7气流预热过程示意图
服务注册时,服务提供者通过元数据在注册中注册预热时间和服务开始时间,服务消费者在注册中订阅相关服务实例列表,根据调整时的预热时间和开始时间计算每个实例的批量调整权重。在起动时间和起动时间之间的时间差相对较大的示例权重下,应当通过分配较少的流量给起动时间来预热入口流量。
开源dubbo实现的流量服务预热模型的计算如下式所示:
模型中,qps应用对应的f(x)随调用时间x线性变化,其中x代表调用时间,starttime为应用启动时间,warmuptime为用户配置的应用预热时间,k为常数,一般代表每个实例的默认权重。
?
图8流量预热权重的计算
通过流量预热的方法,可以有效解决并发流量下,资源初始化慢导致的卷请求响应慢和阻塞,以及资源耗尽导致启动时停机的事故。
3微服务就绪检查
在介绍微服务就绪检查之前,让 下面简要介绍相关的kubernetes探头技术作为技术背景,以便更好地理解以下内容:
库伯内es探针技术
在云领域,为了保证pod在对外提供服务前应全面启动或在pod出货过程中发生意外后及时恢复,kubernetes提供了probe技术,动态检测出货情况,为保证pod的破损线路和健康出货提供了保障。
生存探测器
kubernetes中提供的生存检测器,用于检测何时重启容器。例如,生存检测器可以捕获死锁(程序正在运行,但方法继续执行下一步)。在这种情况下重新启动容器有助于在出现问题时使应用程序更加可行。
就绪探针
kubernetes中提供的就绪检测器可以知道容器何时就绪,并可以开始接受请求的流量。当一个容器中的所有容器都准备好时,该容器可以被认为是准备好的。该信号的一种是控制哪个pod是服务的后端。当pod未就绪时,它将从服务的负载平衡器中删除。
启动探针
kubernetes中提供的启动检测器可以知道应用程序容器何时启动。如果配置了这种检测器,可以控制它在成功启动后检查容器的生存性和就绪性,以保证这些生存性和就绪性检测器不会影响应用的启动。这可用于检测慢启动容器的生存能力,并防止它们在启动前被杀死。
探针使用总结
1.当需要在容器启动后检查活动探针或就绪探针时,可以通过设置启动探针来实现。
2.当容器在异常或不健康的条件下崩溃时,可能不需要生存探针,kubernetes可以根据pod 的重启策略。
3.当容器被终止并在检测失败时重新启动时,您可以指定survival探测器并将restartpolicy指定为always或onfailure。
4.当您希望pod仅在探测成功时才开始接收外部请求流量时,您可以使探测就绪。
有关使用kubernetes探针技术的更多示例,请参见[2]。
目前,kubernetes容器基于维度的部署已经成为业界事实上的标准。相关技术在为微服务的维度化部署带来极利的同时,在一些特殊的部署场景下,也存在一些需要解决的问题。例如,为了使kubernetes的滚动发布功能进入发布,与kubernetes 滚动发布是通过检查特定终端是否应该启动作为应该就绪的标志来触发下一批的实例发布,但仅限于微服务应用。只有完成服务注册,才能对外提供服务。因此,在某些情况下,新应用程序在注册之前会被设置为离线,从而导致服务可用。
目前业内也已经有了针对发布状态和情况应对等问题引发的线上事故的相关解决方案。例如,我们可以通过检查相关服务的注册来检查微服务的准备情况,通过字节码技术植入服务注册前后的逻辑,然后打开一个终端来检测服务的注册是否应该完成,这样kubernetes的ready探针就可以检测绑定户的发布状态和运行状态来实现微服务的准备情况检查,从而避免相关状态不会造成应该发布的在线流量损失的问题。
参考数据
[1] dubbo延迟注册:延迟曝光|阿帕奇dubbo
[2]kubernetes探针技术举例:配置生存、就绪和启动探测器| kubernetes
原始链接
本文为阿里云原创内容,未经允许不得转载。
标签:
流程实例
了解更多微服务架构流量分布(微服务流量着色)相关内容请关注本站点。