事务布景
众所周知,在咱们迭代事务需求和Fix Bug时往往需要重启咱们的服务,在高并发场景下,如果还像N年前一样,通过上机操作敲Linux命令执行Kill操作,在分布式环境下显然会让你敲断手指,而且这种方法重启还会影响用户的操作,导致一些线上事端,所以,在微服务、分布式体系中,滑润翻滚发布无疑是非常重要的(主打的便是一个丝滑)。
SpringCloud微服务架构导致发布的一些坏处
1.Nacos组件导致的一些坏处
众所周知,Nacos利用心跳机制每隔一段时间(可装备,defalut:30s)服务端与客户端都会互相发送心跳包,当服务端接收到的客户端心跳包有反常情况时,Nacos服务端会剔除客户端在服务端中的注册信息,意味着这个服务是不可用状态,这种方法其实是有坏处的,这其实也是心跳机制的坏处,比如我服务A重启了,Nacos服务端并没有马上感知服务A的反常情况,这个时候还以为其是可用状态,这个时候如果有流量打进来,通过负载均衡很明显会有流量进入到服务A,无法即时感知客户端反常,便是它的最大坏处。
2.SpringCloud Gateway组件导致的一些坏处
SpringCloud Gateway组件对比以前的Zuul网关,在功能和吞吐提升了许多,首要是因为它是根据Spring5.0+SpringBoot2.0+Spring Reactor,没错看到Reactor你就会想到功能强悍的Netty,SpringCloud Gateway正是用了这一高功能通讯框架。
提到网关,榜首咱们要想到的便是负载均衡机制,之前面试过不少后端的兄弟,你们的体系怎么做的负载均衡,他们中多数人的回答是运用了Nginx的负载均衡机制,我…,咱不废话,接着说SpringCloud Gateway的负载均衡机制,当运用Ribbon作为负载中间件时会运用定时线程从Nacos注册中心拉取服务列表然后放到Gateway服务的本地缓存中,拉取时间默认也是30s,相同的也是无法及时感知Nacos注册中心的服务反常情况,所以其实许多人在运用SpringCloud Gateway中会经常出现一些500,503等问题,下面我将针对这些组件的坏处做一个完善解决计划。
针对Nacos与GateWay坏处的解决计划
Nacos与Gateway之间即时感知坏处的优化切入思路
- 在程序停止前通过Nacos上下线事情监听回调操作中自动调用Nacos服务下线操作,让Nacos服务端能即时剔除重启的客户端,防止流量流入
- SpringCloud GateWay组件中能够重写其负载均衡战略,也便是在服务上下线回调监听事情中刷新在网关服务本地缓存中的Nacos服务信息,就好比咱们事务中更新了数据库要刷一遍缓存一般,操作起来没啥难度。
线上优化实战
- 问题简介
根据线上日志发现,gateway网关在服务重启时会有调用失利的现象,调用失利或许会导致一些数据的丢失甚至引发一些金钱、充值相关的数据有误,尤其在并发越高的情况下,这种现象表现得越发严重,不才曾经的项目中有因为此等原因导致了服务雪崩的情况,所以针对此网关进行一个优化。
- 优化思路可行性剖析
-
榜首种方法 重写gateway的负载均衡器,从可行性来看问题不大,但是咱们的首要问题是针对服务上下线无法及时感知而优化,并不是针对其负载均衡器进行深度优化,所以此方法虽可完成,但开发、成果成本或许稍大,不优先采纳
-
第二种方法 剖析Nacos与Gateway之间的关联联系可知,咱们能够通过Nacos上下线的事情监听回调来操作Gateway 令其刷新。
-
代码
@Slf4j @Component public class ApplicationEventListener implements ApplicationListener { @Value("${spring.application.name}") private String applicationName; @Value("${server.port}") private int port; @Autowired private DiscoveryClient discoveryClient; @Autowired private NacosAutoServiceRegistration nacosAutoServiceRegistration; @Override public void onApplicationEvent(ApplicationEvent applicationEvent) { if (applicationEvent instanceof ApplicationStartedEvent) { log.info("【{}】【{}】使用启动", IpUtil.getIntranetIp(), applicationName); Executors.newSingleThreadExecutor().execute(() -> checkDiscoveryClient()); } else if (applicationEvent instanceof ContextClosedEvent) { log.info("【{}】【{}】程序已停止...", IpUtil.getIntranetIp(), applicationName); ApplicationCheckUtil.setSystemIsNormal(false); //高雅停机 nacosAutoServiceRegistration.stop(); SpringApplication.exit(SpringContextUtil.getApplicationContext()); ((ConfigurableApplicationContext) SpringContextUtil.getApplicationContext()).close(); } } private void checkDiscoveryClient() { try { List<ServiceInstance> serviceInstanceList; AtomicBoolean currentInstanceHasRegister = new AtomicBoolean(false); while (true) { serviceInstanceList = discoveryClient.getInstances(applicationName); serviceInstanceList.forEach(serviceInstance -> { log.info("host:{} | port:{} | serviceId:{}", serviceInstance.getHost(), serviceInstance.getPort(), serviceInstance.getServiceId()); if (IpUtil.getIntranetIp().equals(serviceInstance.getHost()) && serviceInstance.getPort() == port) { currentInstanceHasRegister.set(true); } }); if (currentInstanceHasRegister.get()) { log.info("当时服务实例已成功注册到Nacos中..."); break; } TimeUnit.SECONDS.sleep(1); } } catch (Exception e) { log.error("检测服务注册反常..."); } finally { DingTalkUtil.send(DingTalkType.PUBLISH_NOTICE, String.format("【%s】【%s】使用启动成功", IpUtil.getIntranetIp(), applicationName)); ApplicationCheckUtil.setSystemIsNormal(true); } } }
首要中心代码就一行:nacosAutoServiceRegistration.stop();
线上优化成果目标
通过此优化 频繁重启了几次服务,而且用测验工具一向并发调用重启的服务,并未发现有调用反常的情况,至此 服务端真正意义上的滑润重启略微提升了一个层次,但还不够,请接着往下看。
K8S翻滚发布更新计划
用户请求服务进程
服务重启预想进程
翻滚发布流程
k8s参数装备
服务在翻滚更新时,deployment操控器的目的是:给旧版本(old_rs)副本数减少至0、给新版本(new_rs)副本数量增至希望值(replicas)。我们在运用时,通常容易忽视操控速率的特性,以下是kubernetes提供的两个参数:
1. maxUnavailable:和希望ready的副本数比,不可用副本数最大份额(或最大值),这个值越小,越能确保服务稳定,更新越滑润;
2. maxSurge:和希望ready的副本数比,超越希望副本数最大份额(或最大值),这个值调的越大,副本更新速度越快。
spec:
---副本数量
replicas: 5
selector:
matchLabels:
app: user-service
minReadySeconds: 120
strategy:
---翻滚更新方法
type: RollingUpdate
rollingUpdate:
---超越希望副本数最大份额(或最大值)
maxSurge: 1
---不可用副本数最大份额(或最大值)
maxUnavailable: 3
至此,一套完好高可用、稳定的微服务翻滚更新计划已完成,根本现已能够满意目前的运用情况。
后续优化展望
- 添加灰度发布计划
- 添加长衔接服务的滑润发布计划(涉及到的知识点很干,我们敬请期待)