Skip to content

Commit 0cc3c20

Browse files
Create index.md (#1307)
* Create index.md * Update index.md * Update and rename index.md to index.md
1 parent d0809f8 commit 0cc3c20

File tree

1 file changed

+132
-0
lines changed
  • content/zh/blog/koupleless-enables-renlijia-to-achieve-centralized-deployment-of-distributed-R&D,quickly-and-cost-effectivelyindex.md

1 file changed

+132
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
---
2+
title: "社区文章|Koupleless 助力「人力家」实现分布式研发集中式部署,又快又省!"
3+
authorlink: "https://github.com/sofastack"
4+
description: "人力家由阿里钉钉与人力窝共同孵化,致力于为企业提供以薪酬为核心的一体化 HR SaaS 解决方案,加速对中国人力资源服务行业数字化赋能。"
5+
categories: "SOFAStack"
6+
tags: ["SOFAStack"]
7+
date: 2024-10-29T15:00:00+08:00
8+
cover: "https://img.alicdn.com/imgextra/i3/O1CN0115QEFQ1V83a8DyXGw_!!6000000002607-0-tps-1080-540.jpg"
9+
---
10+
11+
**原创** **赵云兴、葛志刚**
12+
13+
文|赵云兴,葛志刚
14+
15+
仁励家网络科技(杭州)有限公司架构师
16+
专注 to B 领域架构
17+
18+
**本文 2111 字 阅读 5 分钟**
19+
20+
# 背景
21+
22+
人力家由阿里钉钉与人力窝共同孵化,致力于为企业提供以薪酬为核心的一体化 HR SaaS 解决方案,加速对中国人力资源服务行业数字化赋能。
23+
24+
人力资源软件通常由**多模块**组成,如人力资源规划、招聘、培训、绩效管理、薪酬福利、劳动关系,以及员工和组织管理等。随着业务发展,部分模块进入稳定期,仅需少量维护投入。例如,一个早期有 20 人研发的项目,现在拆分为 5 个应用。尽管产品成熟,但由于客户需求随竞争、业务和政策变化,仍需每年投入部分精力进行迭代。
25+
26+
长时间以来,我们一直面临着以下问题,而苦于没有解决方案:
27+
28+
* **系统资源浪费**:5 个应用支撑的业务,我们在生产环境为每个应用部署了 3 台 2C4G 的 Pod,一共是 15 个 Pod 的资源。
29+
* **迭代运维成本高**:因为业务的复杂性,经常需要多个应用同时改动,部署等待周期长,单应用部署时间在 6 分钟左右。
30+
31+
在过去,我们已经探索过以下方案:
32+
33+
* **压缩工程**:通过排除冗余的 jar 依赖,降低镜像大小。但空间有限,整个应用 jar 包只能从 100+M 减少到 80+M,整个镜像依然有 500M,能节省的部署等待时间有限。
34+
* **单 ECS 上部署多应用**:我们需要为这个应用做特别的定制,譬如监听端口要支持多个;部署脚本也要特别定制,要支持滚动发布,健康检测不同的端口,一段时间以后运维容易搞不清整个部署方案,容易出现运维事故。
35+
36+
# 初见成效
37+
38+
直到在某个月不黑风不高的夜晚,我们在最大的程序员交友网站上遇到了 Koupleless 团队。看完框架的介绍,我们立刻明白,Koupleless 就是我们要寻找的解决方案。
39+
40+
经过近两个月的敲敲打打,**模块成功瘦身了,其中最大的模块的 jar 也只有不到 4M****应用部署的体积从 500M 一下子降到了 5M 以下**,具体可见下图~
41+
42+
![瘦身以后模块的jar](https://img.alicdn.com/imgextra/i3/O1CN01bLsiXt27Y7WHF1G9z_!!6000000007808-0-tps-1080-594.jpg)
43+
44+
但高兴不过一天,我们在「**如何把 Koupleless 部署到生产环境**」上遇到了难题。因为我们没有专门的运维团队,部署都是开发人员通过阿里云的云效流水线,直接把镜像推送到 K8s 的 Pod。但这样改了以后,我们迎来了一连串待解决的问题……
45+
46+
* 模块要不要流量,还是直接通过基座处理流量?
47+
* 如何在单独部署模块的时候先把基座的流量摘掉?
48+
* 发布成功以后如何做健康检查?
49+
* 如何重新开放基座流量?
50+
51+
# Koupleless 的生产环境部署
52+
53+
在这里要特别感谢 Koupleless 团队的伙伴,给了我们很多专业的建议和方案。最终,我们选择了以下部署方案:
54+
55+
![图片](https://img.alicdn.com/imgextra/i3/O1CN01kXDBIQ1Vj9f9mimO0_!!6000000002688-2-tps-1080-696.png)
56+
57+
整体方案是,在基座上增加监听 oss 文件变化自动更新部署模块,卸载老版本模块安装新版模块,所有流量由 nginx 进入,转发到进程 tomcat *(基座和多个模块复用同个 tomcat host)*,并在基座上控制健康检查和流量的开关,主要工作是在基座上扩充一些能力:
58+
59+
1、基座支持配置自身运行的必要条件,譬如需要模块 A、B、C 都安装成功才能放流量进来;
60+
61+
2、检查 oss 目录,自动安装最新的模块版本,并做健康检查;
62+
63+
3、实现 K8s 的 liveness:用来在基座部署的时候判断基座是否成功启动。只要基座启动成功,即返回成功,这样基座可以走后续的安装模块逻辑;
64+
65+
4、实现 K8s 的 readiness:主要控制外部流量是否可以进来。因此这里需要判断所有必须安装的模块是否健康,并且对应的流量文件 A\_status 等是否存在 *(该文件是一个空文件,在滚动发布的时候开关流量的时候用)*
66+
67+
> **小 Tips**
68+
>
69+
> 目前 Koupleless 优化了静态部署和健康检查能力,能够直接满足我们的需求:
70+
>
71+
> * **静态部署**:在基座启动成功后,允许用户通过自定义的方式安装模块;
72+
> * **健康检查**:在基座启动成功且用户自定义安装的模块启动后,Koupleless 框架将原生 SpringBoot 的 readiness 配置为 'ACCEPTING\_TRAFFIC',用户可以通过探测 readiness 决定是否让流量进入。
73+
74+
以下是 K8s 上的配置图:
75+
76+
* 就绪检查和启动探测:
77+
78+
![图片](https://img.alicdn.com/imgextra/i4/O1CN01fNqGKv1GurYD5HDwR_!!6000000000683-0-tps-1080-974.jpg)
79+
80+
* 在 Pod 上增加云存储的挂载:
81+
82+
![图片](https://img.alicdn.com/imgextra/i4/O1CN01NaBgot1ErzqCYEQgg_!!6000000000406-0-tps-1080-145.jpg)
83+
84+
模块动态部署时需要考虑两个问题:怎么感知新的模块并部署?在模块部署的前后怎么通过健康检查,控制基座流量?
85+
86+
我们的方案大概如下:
87+
88+
1、模块通过流水线,直接 jar 上传到一个 oss 目录;
89+
90+
2、基座上增加配置,配置基座承接流量的必须安装的模块,以及对应模块的健康检查地址;
91+
92+
3、基座监听 oss 文件夹的变化,来决定是否重新部署模块 *(譬如有更晚的/更大的版本的模块上传到了 oss)*
93+
94+
4、基座部署模块前,先摘流量 *(可以通过删除一个空文件来实现,结合上一步 K8s 的 readiness 逻辑,空文件删除以后,readiness 检测不通过,流量就不会进来。但模块是存活的,防止有耗时的线程还在运行)*
95+
96+
5、安装好模块以后,把删除的文件写上,就可以开流量了;
97+
98+
6、集群下,基座通过 redis 来控制 Pod 不会出现并行安装,保证流量不会断;
99+
100+
7、基座提供就绪检查:就绪检查只需要判断基座起来了就可以。
101+
102+
存活检查是比较关键的一步:
103+
104+
a.判断第 4 步的空文件是否存在;
105+
106+
b.需要判断所有必须安装的模块都可以访问。
107+
108+
> **小 Tips**
109+
>
110+
> 目前 Koupleless 优化了**健康检查能力**,能够在模块动态安装/卸载之前关闭流量,将 readiness 配置为 REFUSING\_TRAFFIC,并允许用户配置模块卸载前的静默时长,让流量在静默时期处于关闭状态。在卸载的静默时长结束、旧模块卸载完成、全部模块安装成功后,readiness 才会配置为 ACCEPTING\_TRAFFIC 状态。
111+
112+
# 总结
113+
114+
在以前,单个模块升级发布一次要 6 分多钟。
115+
116+
![图片](https://img.alicdn.com/imgextra/i1/O1CN01mlMuVB1d0kBQENPgr_!!6000000003674-0-tps-1080-309.jpg)
117+
118+
而改造后,升级单个模块只需要把编译后的 jar 上传到 oss 即可。
119+
120+
![图片](https://img.alicdn.com/imgextra/i2/O1CN01z8sckO1PVWAuYM2g6_!!6000000001846-0-tps-1080-228.jpg)
121+
122+
最终的效果,通过一组简单的数字对比就可以看出差异:
123+
124+
* 在服务器资源上,以前需要 15X2C4G,现在只需要 3X4c8G,**节省了 18C36G 的服务器资源**
125+
* 在单个模块的发布时间上,我们从之前的 6 分钟**降低到了 3 分钟**
126+
* 在单个模块的部署资源上,我们从 500M **降低到了 5M**
127+
128+
再次感谢 Koupleless 团队伙伴的专业支持,特别是有济、立蓬。当我们在改造过程中遇到一些个性场景的兼容性问题,他们都能快速响应,让我们整个升级改造时间大大缩短。
129+
130+
通过升级 Koupleless 架构,人力家实现了**多应用的合并部署、并行研发、轻量集中部署,大大降低了运维成本。**
131+
132+
天下架构,分久必合,合久必分。而 Koupleless,让架构演进(分合)更丝滑🥰

0 commit comments

Comments
 (0)