如何快速构建服务发现的高可用能力

简介:保障云上业务的永远在线,是 MSE 一直在追求的目标,本文通过面向失败设计的服务发现高可用能力的分享,以及 MSE 的服务治理能力快速构建起服务发现高可用能力的演示,模拟了线上不可预期的服务发现相关异常发生时的影响以及我们如何预防的手段,展示了一个简单的开源微服务应用应该如何构建起服务发现高可用能力。

作者:十眠

背景

注册中心作为承担服务注册发现的核心组件,是微服务架构中必不可少的一环。在 CAP 的模型中,注册中心可以牺牲一点点数据一致性(C),即同一时刻每一个节点拿到的服务地址允许短暂的不一致,但必须要保证可用性(A)。因为一旦由于某些问题导致注册中心不可用,或者服务连不上注册中心,那么想要连接他的节点可能会因为无法获取服务地址而对整个系统出现灾难性的打击。

一个真实的案例

全篇从一个真实的案例说起,某客户在阿里云上使用 Kubernetes 集群部署了许多自己的微服务,由于某台 ECS 的网卡发生了异常,虽然网卡异常很快恢复了,但是却出现了大面积持续的服务不可用,业务受损。

我们来看一下这个问题链是如何形成的?

  1. ECS 故障节点上运行着 Kubernetes 集群的核心基础组件 CoreDNS 的所有 Pod,且低版本 Kubernetes 集群缺少 NodeLocal DNSCache 的特性,导致集群 DNS 解析出现问题。
     
  2. 该客户的服务发现使用了有缺陷的客户端版本(Nacos-client 的 1.4.1 版本),这个版本的缺陷就是跟 DNS 有关——心跳请求在域名解析失败后,会导致进程后续不会再续约心跳,只有重启才能恢复。
  3. 这个缺陷版本实际上是已知问题,阿里云在 5 月份推送了 Nacos-client 1.4.1 存在严重 bug 的公告,但客户研发未收到通知,进而在生产环境中使用了这个版本。

风险环环相扣,缺一不可。

最终导致故障的原因是服务无法调用下游,可用性降低,业务受损。下图示意的是客户端缺陷导致问题的根因:

  1. Provider 客户端在心跳续约时发生 DNS 异常;
  2. 心跳线程未能正确地处理这个 DNS 异常,导致线程意外退出了;
  3. 注册中心的正常机制是,心跳不续约,30 秒后自动下线。由于 CoreDNS 影响的是整个 Kubernetes 集群的 DNS 解析,所以 Provider 的所有实例都遇到相同的问题,整个服务所有实例都被下线;
  4. 在 Consumer 这一侧,收到推送的空列表后,无法找到下游,那么调用它的上游(比如网关)就会发生异常。

回顾整个案例,每一环每个风险看起来发生概率都很小,但是一旦发生就会造成恶劣的影响。服务发现高可用是微服务体系中很重要的一环,当然也是我们时常忽略的点。在阿里内部的故障演练中,这一直是必不可少的一个环节。

面向失败的设计

由于网络环境的抖动比如 CoreDns 的异常,或者是由于某些因素导致我们的注册中心不可用等情况,经常会出现服务批量闪断的情况,但这种情况其实不是业务服务的不可用,如果我们的微服务可以识别到这是一种异常情况(批量闪断或地址变空时),应该采取一种保守的策略,以免误推从而导致全部服务出现"no provider"的问题,会导致所有的微服务不可用的故障,并且持续较长时间难以恢复。

站在微服务角度上考虑,我们如何可以切段以上的问题链呢?以上的案例看起来是 Nacos-client 低版本造成的问题,但是如果我们用的是 zookeeper、eureka 等注册中心呢?我们能拍着胸脯说,不会发生以上的问题吗?面向失败的设计原则告诉我们,如果注册中心挂掉了,或者我们的服务连不上注册中心了,我们需要有一个方式保证我们的服务正常调用,线上的业务持续不断。

本文介绍的是服务发现过程中的高可用的机制,从服务框架层面思考如何彻底解决以上的问题。

服务发现过程中的高可用原理解析

服务发现高可用-推空保护

面向失败的设计告诉我们,服务并不能完全相信注册中心的通知的地址,当注册中心的推送地址为空时候,服务调用肯定会出 no provider 错误,那么我们就忽略此次推送的地址变更。

微服务治理中心提供推空保护能力

  • 默认无侵入支持市面上近五年来的 Spring Cloud 与 Dubbo 框架
  • 无关注册中心实现,无需升级 client 版本

服务发现高可用-离群实例摘除

心跳续约是注册中心感知实例可用性的基本途径。但是在特定情况下,心跳存续并不能完全等同于服务可用。

因为仍然存在心跳正常,但服务不可用的情况,例如:

  • Request 处理的线程池满
  • 依赖的 RDS 连接异常导致出现大量慢 SQL
  • 某几台机器由于磁盘满,或者是宿主机资源争抢导致 load 很高

此时服务并不能完全相信注册中心的通知的地址,推送的地址中,可能存在一些服务质量低下的服务提供者,因此客户端需要自己根据调用的结果来判断服务地址的可用性与提供服务质量的好坏,来定向忽略某些地址。

微服务治理中心提供离群实例摘除

  • 默认无侵入,支持市面上近五年来的 Spring Cloud 与 Dubbo 框架
  • 无关注册中心实现,无需升级 client 版本
  • 基于异常检测的摘除策略:包含网络异常和网络异常 + 业务异常(HTTP 5xx)
  • 设置异常阈值、QPS 下限、摘除比例下限
  • 摘除事件通知、钉钉群告警

离群实例摘除的能力是一个补充,根据特定接口的调用异常特征,来衡量服务的可用性。

动手实践

前提条件

  • 已创建 Kubernetes 集群,请参见创建 Kubernetes 托管版集群[1]
  • 已开通 MSE 微服务治理专业版,请参见开通 MSE 微服务治理[2]

准备工作

开启 MSE 微服务治理

1、开通微服务治理专业版:

  1. 单击开通 MSE 微服务治理[3]
  2. 微服务治理版本选择专业版,选中服务协议,然后单击立即开通。关于微服务治理的计费详情,请参见价格说明[4]

2、安装 MSE 微服务治理组件:

  1. 在容器服务控制台[5]左侧导航栏中,选择市场 > 应用目录
  2. 应用目录页面搜索框中输入 ack-mse-pilot,单击搜索图标,然后单击组件。
  3. 详情页面选择开通该组件的集群,然后单击创建。安装完成后,在命名空间 mse-pilotmse-pilot-ack-mse-pilot 应用,表示安装成功。

3、为应用开启微服务治理:

  1. 登录 MSE 治理中心控制台[6]
  2. 在左侧导航栏选择微服务治理中心 > Kubernetes 集群列表
  3. Kubernetes 集群列表页面搜索目标集群,单击搜索图标,然后单击目标集群操作列下方的管理
  4. 集群详情页面命名空间列表区域,单击目标命名空间操作列下方的开启微服务治理
  5. 开启微服务治理对话框中单击确认

部署 Demo 应用程序

  1. 在容器服务控制台[5]左侧导航栏中,单击集群
  2. 集群列表页面中,单击目标集群名称或者目标集群右侧操作列下的详情
  3. 在集群管理页左侧导航栏中,选择工作负载 > 无状态
  4. 无状态页面选择命名空间,然后单击使用 YAML 创建资源
  5. 对模板进行相关配置,完成配置后单击创建。本文示例中部署 sc-consumer、sc-consumer-empty、sc-provider,使用的是开源的 Nacos。

部署示例应用(springcloud)

YAML:

# 开启推空保护的 sc-consumer
apiVersion: apps/v1
kind: Deployment
metadata:name: sc-consumer
spec:replicas: 1selector:matchLabels:app: sc-consumertemplate:metadata:annotations:msePilotCreateAppName: sc-consumerlabels:app: sc-consumerspec:containers:- env:- name: JAVA_HOMEvalue: /usr/lib/jvm/java-1.8-openjdk/jre- name: spring.cloud.nacos.discovery.server-addrvalue: nacos-server:8848- name: profiler.micro.service.registry.empty.push.reject.enablevalue: "true"image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/demo:sc-consumer-0.1imagePullPolicy: Alwaysname: sc-consumerports:- containerPort: 18091livenessProbe:tcpSocket:port: 18091initialDelaySeconds: 10periodSeconds: 30
# 无推空保护的sc-consumer-empty
---
apiVersion: apps/v1
kind: Deployment
metadata:name: sc-consumer-empty
spec:replicas: 1selector:matchLabels:app: sc-consumer-emptytemplate:metadata:annotations:msePilotCreateAppName: sc-consumer-emptylabels:app: sc-consumer-emptyspec:containers:- env:- name: JAVA_HOMEvalue: /usr/lib/jvm/java-1.8-openjdk/jre- name: spring.cloud.nacos.discovery.server-addrvalue: nacos-server:8848image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/demo:sc-consumer-0.1imagePullPolicy: Alwaysname: sc-consumer-emptyports:- containerPort: 18091livenessProbe:tcpSocket:port: 18091initialDelaySeconds: 10periodSeconds: 30
# sc-provider
---
apiVersion: apps/v1
kind: Deployment
metadata:name: sc-provider
spec:replicas: 1selector:matchLabels:app: sc-providerstrategy:template:metadata:annotations:msePilotCreateAppName: sc-providerlabels:app: sc-providerspec:containers:- env:- name: JAVA_HOMEvalue: /usr/lib/jvm/java-1.8-openjdk/jre- name: spring.cloud.nacos.discovery.server-addrvalue: nacos-server:8848image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/demo:sc-provider-0.3imagePullPolicy: Alwaysname: sc-providerports:- containerPort: 18084livenessProbe:tcpSocket:port: 18084initialDelaySeconds: 10periodSeconds: 30
# Nacos Server
---
apiVersion: apps/v1
kind: Deployment
metadata:name: nacos-server
spec:replicas: 1selector:matchLabels:app: nacos-servertemplate:metadata:labels:app: nacos-serverspec:containers:- env:- name: MODEvalue: standaloneimage: nacos/nacos-server:latestimagePullPolicy: Alwaysname: nacos-serverdnsPolicy: ClusterFirstrestartPolicy: Always# Nacos Server Service 配置
---
apiVersion: v1
kind: Service
metadata:name: nacos-server
spec:ports:- port: 8848protocol: TCPtargetPort: 8848selector:app: nacos-servertype: ClusterIP

我们只需在 Consumer 增加一个环境变量 profiler.micro.service.registry.empty.push.reject.enable=true,开启注册中心的推空保护(无需升级注册中心的客户端版本,无关注册中心的实现,支持 MSE 的 Nacos、eureka、zookeeper 以及自建的 Nacos、eureka、console、zookeeper 等)

分别给 Consumer 应用增加 SLB 用于公网访问

以下分别使用 {sc-consumer-empty} 代表 sc-consumer-empty 应用的 slb 的公网地址,{sc-consumer} 代表 sc-consumer 应用的 slb 的公网地址。

应用场景

下面通过上述准备的 Demo 来分别实践以下场景

  • 编写测试脚本

vi curl.sh

while :
doresult=`curl $1 -s`if [[ "$result" == *"500"* ]]; thenecho `date +%F-%T` $resultelseecho `date +%F-%T` $resultfisleep 0.1
done
  • 测试,分别开两个命令行,执行如下脚本,显示如下

% sh curl.sh {sc-consumer-empty}:18091/user/rest2022-01-19-11:58:12 Hello from [18084]10.116.0.142!2022-01-19-11:58:12 Hello from [18084]10.116.0.142!2022-01-19-11:58:12 Hello from [18084]10.116.0.142!2022-01-19-11:58:13 Hello from [18084]10.116.0.142!2022-01-19-11:58:13 Hello from [18084]10.116.0.142!2022-01-19-11:58:13 Hello from [18084]10.116.0.142!

% sh curl.sh {sc-consumer}:18091/user/rest2022-01-19-11:58:13 Hello from [18084]10.116.0.142!2022-01-19-11:58:13 Hello from [18084]10.116.0.142!2022-01-19-11:58:13 Hello from [18084]10.116.0.142!2022-01-19-11:58:14 Hello from [18084]10.116.0.142!2022-01-19-11:58:14 Hello from [18084]10.116.0.142!2022-01-19-11:58:14 Hello from [18084]10.116.0.142!

并保持脚本一直在调用,观察 MSE 控制台分别看到如下情况

  • 将 coredns 组件缩容至数量 0,模拟 DNS 网络解析异常场景。

发现实例与 Nacos 的连接断开且服务列表为空。

  • 模拟 DNS 服务恢复,将其扩容回数量 2。

结果验证

在以上过程中保持持续的业务流量,我们发现 sc-consumer-empty 服务出现大量且持续的报错

2022-01-19-12:02:37 {"timestamp":"2022-01-19T04:02:37.597+0000","status":500,"error":"Internal Server Error","message":"com.netflix.client.ClientException: Load balancer does not have available server for client: mse-service-provider","path":"/user/feign"}2022-01-19-12:02:37 {"timestamp":"2022-01-19T04:02:37.799+0000","status":500,"error":"Internal Server Error","message":"com.netflix.client.ClientException: Load balancer does not have available server for client: mse-service-provider","path":"/user/feign"}2022-01-19-12:02:37 {"timestamp":"2022-01-19T04:02:37.993+0000","status":500,"error":"Internal Server Error","message":"com.netflix.client.ClientException: Load balancer does not have available server for client: mse-service-provider","path":"/user/feign"}

相比之下,sc-consumer 应用全流程没有任何报错

  • 只有重启了 Provider,sc-consumer-empty 才恢复正常

相比之下,sc-consumer 应用全流程没有任何报错

后续

我们当发生推空保护后,我们会上报事件、告警至钉钉群,同时建议配合离群实例摘除使用,推空保护可能会导致 Consumer 持有过多的 Provider 地址,当 Provider 地址为无效地址时,离群实例摘除可以对其进行逻辑隔离,保证业务的高可用。

保障云上业务的永远在线,是 MSE 一直在追求的目标,本文通过面向失败设计的服务发现高可用能力的分享,以及 MSE 的服务治理能力快速构建起服务发现高可用能力的演示,模拟了线上不可预期的服务发现相关异常发生时的影响以及我们如何预防的手段,展示了一个简单的开源微服务应用应该如何构建起服务发现高可用能力。

相关链接

[1] 创建 Kubernetes 托管版集群

如何创建Kubernetes托管版集群_容器服务 ACK-阿里云

[2] 开通 MSE 微服务治理

开通MSE微服务治理 - 微服务引擎MSE - 阿里云

[3] 开通 MSE 微服务治理

阿里云通用售卖

[4] 价格说明

价格说明 - 微服务引擎MSE - 阿里云

[5] 容器服务控制台

https://cs.console.aliyun.com

[6] MSE 治理中心控制台

https://mse.console.aliyun.com

原文链接

本文为阿里云原创内容,未经允许不得转载。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/511035.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

火山引擎发布新一代数智平台VeDI,以数据驱动企业数字化增长

数据是“新石油”,经过提炼加工才能创造价值。 9月2日,火山引擎数据智能科技峰会在杭州举办。会上,火山引擎发布新一代企业级数据产品——数智平台VeDI(Volcengine Data Intelligence),包括数据引擎、数据…

阿里云服务网格 ASM 正式发布商业化版本

简介:为了更好地满足企业日益加深的大规模使用服务网格产品、服务多语言互通、服务精细治理等需求,2022 年 4 月 1 日起,阿里云服务网格产品 ASM 正式发布商业化版本,为企业在生产环境下大规模落地服务网格能力提供性能、安全、高…

Redis消息队列发展历程

简介:Redis是目前最受欢迎的kv类数据库,当然它的功能越来越多,早已不限定在kv场景,消息队列就是Redis中一个重要的功能。Redis从2010年发布1.0版本就具备一个消息队列的雏形,随着10多年的迭代,其消息队列的…

手机+卫星,到底有多难?

作者 | 小枣君来源 | 鲜枣课堂这几天,关于卫星手机的新闻又火了。根据媒体报道,9月6日即将发布的华为Mate 50系列手机,将具备“卫星通信能力”,在没有网络的地方,可通过卫星系统发送紧急短信。无独有偶,另有…

一线技术人的成长思考总结

简介: 作为长期奋战在一线的技术人,我深刻体会到几个思维能力对技术人成长的重要性,熟练运用这几种思维可以帮助我们快速的进入到新的领域,在分析、定位和解决问题上有很大帮助。作为长期奋战在一线的技术人,我深刻体会…

sealer背后实现整个集群一键交付的奥秘 | 龙蜥技术

简介:解读集群镜像“开箱即用”神器——sealer! 编者按:集群镜像把整个集群看成一台服务器,把 k8s 看成云操作系统,实现整个集群的镜像化打包和交付,为企业级软件提供一种“开箱即用”的应用封装技术。本文…

突发!GitHub 将关闭 Trending 热榜,开发者不答应

作者 | 苏宓出品 | CSDN(ID:CSDNnews)今天,当登录到 GitHub 上时,GitHub Trending 页面突然显示了这样一则通知:Heads up! This Trending tab is being deprecated. Due to low usage of Trending Reposito…

如何设计一条稳定的应用交付流程?|云效工程师指北

简介:如何设计一条稳定的应用交付流程?为持续交付的过程提供了规范化的可能,也引入了让人不时埋首于配置文件的小山里的麻烦。我们不妨从一次略有波折、稍显隐患的集成部署案例开始,看看如何着手设计一条更为稳定的应用交付流程。…

阿里云混合云开放网络生态的探索与实践

简介:2022年F5多云应用服务科技峰会于4月正式召开。阿里云智能混合云平台高级网络架构师张然(然犀)应邀于合作伙伴生态专场分享了阿里云混合云在开放网络生态领域的探索与实践。 2022年F5多云应用服务科技峰会于4月正式召开。阿里云智能混合…

阿里云启动超级智算中心,总算力达12 EFLOPS

8月30日,阿里云宣布正式启动张北超级智算中心,总建设规模为12 EFLOPS(每秒1200亿亿次浮点运算)AI算力,将超过谷歌的9 EFLOPS和特斯拉的1.8 EFLOPS,成为全球最大的智算中心,可为AI大模型训练、自…

领域驱动编程,代码怎么写?

简介:领域驱动开发最重要的当然是正确地进行领域拆解,这个拆解工作可以在理论的指导下,结合设计者对业务的深入分析和充分理解进行。本文假定开发前已经进行了领域划分,侧重于研究编码阶段具体如何实践才能体现领域驱动的优势。 …

8年持续增长,全闪存厂商PureStorage分享存储智能化的三大重要指标

作者 | 宋慧 出品 | CSDN云计算 从PureStorage去年宣布为现代数据应用提供多云环境提供存储即服务,已经过去了快一年时间。全闪存技术厂商PureStorage最近再次接受CSDN采访,分享这一年的发展和对全闪存市场的分析。 首先,今年PureStorage继…

深度解密|基于 eBPF 的 Kubernetes 问题排查全景图发布

简介:通过 eBPF 无侵入地采集多语言、多网络协议的黄金指标/网络指标/Trace,通过关联 Kubernetes 对象、应用、云服务等各种上下文,同时在需要进一步下钻的时候提供专业化的监测工具(如火焰图),实现了 Kube…

技术抉择:阿里云13年后重构全部核心调度系统

简介:在阿里云十三年的发展历史上,重新设计调度系统算得上是一个重要的技术抉择。 在阿里云十三年的发展历史上,重新设计调度系统算得上是一个重要的技术抉择。 云计算是一个庞大的技术工程。2009 年,阿里云从 0 到 1 自建国产云…

Redis 的数据被删除,内存占用还这么大?

作者 | 码哥来源 | 码哥字节操作系统分配给 Redis 的内存有 6GB,通过指标 used_memory_human 发现存储数据只使用了 4GB,为何会这样?为何无法保存数据?通过 CONFIG SET maxmemory 100mb或者在 redis.conf 配置文件设置 maxmemory …

阿里云架构师解读四大主流游戏架构

简介:游戏行业是阿里云最早聚焦的行业之一,近年来游戏行业的变化、云计算产品技术的变化都与日俱进。随着行业业务的变化、技术架构的演进以及阿里云产品的迭代演进,整体的产品技术选型在不同的游戏场景、业务场景也不尽相同。本文将聚焦阿里…

国内唯一连续入选Gartner,Quick BI是如何做到的?

简介:阿里云Quick BI凭借灵活的公共云部署,私有化独立部署能力、无缝对接各类云上数据库和自建数据库、可视化搭建分析、高效数据处理能力与强大数据计算能力,使得在2022年持续入选Gartner ABI魔力象限报告。 作者 | 馨心 来源 | 阿里开发者公…

龙蜥开源Plugsched:首次实现 Linux kernel 调度器热升级 | 龙蜥技术

简介:对于plugsched而言,无论是 bugfix,还是性能优化,甚至是特性的增、删、改,都可胜任。 文/龙蜥社区内核开发人员 陈善佩、吴一昊、邓二伟 Plugsched 是 Linux 内核调度器子系统热升级的 SDK,它可以实现…

出家12年,北大数学天才柳智宇下山还俗:从事心理咨询,主动要求降薪至2万...

整理 | 于轩 出品 | CSDN(ID:CSDNnews)提到北大数学天才,大家脑海中首先浮现的或许是有“北大扫地僧”之称的韦东奕。虽有“扫地僧”的称呼,但韦东奕并不是一位真正的僧人,相反,他的师兄&am…

启明创投合伙人叶冠泰:我对云原生投资趋势的思考 | 云原生加速器观点

简介:投资就是一种相信,要相信这个产业,这位企业家,通过我们的相信去传递给下一轮合作的投资人。“相信相信的力量”,我相信软件的未来,也相信软件在中国发展的力量。 作者 | 叶冠泰 3 月 3 日 - 4 日&am…