微服务合并
有的团队为了节约机器成本、有的团队为了提升研发效率、有的团队为了降低人均服务数
微服务合并,可以从多个角度入手
- 代码重构融合:人工拷贝代码、解决冲突,然后分阶段实施迁移重构。
- 代码合并打包:将多个代码仓库,拉取后合并打包,构建成一个包部署。对于编译型语言,也称为
合并编译
。 - 服务合并部署:将多个服务,解决环境隔离、版本冲突问题后,合并部署到一个进程。
代码重构融合
原始而纯粹,只要落地阶段细致、严谨,遵循服务迁移的基本套路,做好流量diff,不大会出现严重问题。
以合并两个Java应用为例(将A服务合并到B)
步骤 | 事项(重点完成以下事项) |
---|---|
前置梳理 | 1. 代码迁移范围:①无流量、可下线接口/模块;②必迁移模块梳理。 2. 配置迁移范围:①动态配置:KV、Token、密钥等;②静态配置:application/xxx.properties等。 3. 依赖冲突:迁移前将原服务的依赖升级到与目标服务一致;补充原服务单独使用的特殊依赖到目标服务,防止冲突。 |
代码迁移 | 1. 新增module/package,实现模块隔离。 2. 命名空间冲突:同名配置类、同名bean、同名的动态配置key、同名的task、线程池名。 3. 资源层客户端隔离:合并后的服务,可能需要连接多个mysql/redis/ES集群,对应的datasource或客户端需要分别初始化;例如不同的mapper接口包使用不同的datasource。 |
流量diff | 流量入口异步双写,异步执行结果与原服务执行结果预期一致。 |
流量切换 | 异步执行结果与原服务执行结果稳定一致后,将流量入口调用,迁移到目标服务的新方法上。 |
**服务合并,不只是代码合并。**影响代码运行结果的还有:动态配置、组件依赖关系(初始化顺序、bean间依赖)、运行环境有效性(事务、代理、异步生效与否)、消息队列延迟消费配置等。
代码迁移
,除了解决命名冲突,还要考虑资源层在使用上的隔离。
对于只将多个小服务 代码合并,但DB等资源层不合并的情况:合并后的服务,不同模块独立使用不同的datasource数据源,需要隔离Databource和DatabourceTransactionllanager,并将迁移代码中的@Transactional指定对应新增的事务管理器;
- 以将A服务合并到B的场景举例,B原本使用的Databource和DatabourceTransactionllanager都是作为default的,对应业务模块的@Transactional无需指定。服务A的代码迁入B后,使用@Transactional时指定对应新增的事务管理器。
- 合并后的服务,如需连接多个redis/ES集群,也是显示初始化多个客户端,在不同的业务模块中使用不同的客户端进行资源操作;跟在一个服务里使用多个redis/ES集群方式差不多。
线下验证
,可以充分利用原服务已有的测试能力,包括单测、自动化测试等。这是理想情况。
服务合并过程中,除了解决冲突需要修改,原服务逻辑在不大改的情况下,可以线下覆盖核心流程;然后线上流量diff,稳定一致后再切流。
上线准备
,需要关注各类鉴权、配置迁移。
迁移原服务的接口鉴权、访问资源的客户端鉴权、定时任务配置等。
除此之外,还要迁移服务治理策略的配置:熔断、限流配置、告警策略等。
流量diff
在线上环境进行。理论上,需要覆盖所有的读写接口、以及其他形式的流量入口(定时任务or消费组等)。
- 读接口,进行实时、异步比对,整体成本较低。
- 写接口,有一定的成本。
优势 | 劣势 | |
---|---|---|
新建一套临时表,异步双向 流量入口处,接收写请求后,先同步调用老方法,变更写入正式表;再异步调用(迁移到目标服务后的)新方法,对流量染色、标记是diff流量。 (迁移到目标服务后的)新方法,使用Mybatis Interceptor依据染色改写表名(追加_temp后缀);将数据写入临时表;最后比对两份数据表的一致性。 | 无侵入、数据隔离 | 1. 需要新起一套数据表; 2. 新方法除了DB变更外,其他缓存、对外通知MQ,也需根据流量染色,在diff阶段忽略不执行(老方法已完整执行、并对外发了MQ,新方法写入临时表用于比对,不用再发)。 |
同步执行新流程,比对结果快照 接收写请求后,先调用新方法,再调用老方法; 新方法开启事务执行完,查询事务内变更的数据并保存为快照,不提交&回滚事务; 老方法开启事务执行完,查询事务内变更的数据并与新方法的结果快照进行比对,提交事务。 | 1. 同步串行执行,耗时高; 2. 回滚事务可能产生告警; 3. 只适合在单个服务内重构时使用,跨服务重构时 除非改造写接口,返回结果快照。 |
其他形式的流量入口(定时任务or消费组等),需要区分任务类型,对于异步写的场景,也可以采用以上方案diff两套数据源或diff结果快照。
流量diff,理论上需要覆盖所有的读写接口。实际读接口实时、异步比对的成本更低。某些基础元数据的业务场景,仅diff读也行:读不一致说明写有问题,读一致,写肯定一致的情况;无需再diff写。
代码合并打包
以微服务的方式开发,以单体服务的方式运行。
对于编译型语言,也称为合并编译,需要在编译阶段 解决命名冲突、依赖冲突,确定唯一的入口函数等,编译成一个二进制的可执行文件。
而像Java这类半编译半解释型语言,需要借助maven-shade-plugin/maven-assembly-plugin插件,构建的jar文件包含所有依赖,同时支持重命名某些依赖的包。
- 要避免property文件互相覆盖,可以使用AppendingTransformer来对文件内容追加合并。
- 支持指定唯一的入口类。
对于已落地服务治理的团队,该方式更复杂的是:A和B合并后,服务注册 要注册为合并后的整体;A和B之前的调用方在服务发现时,获取服务列表也是“合并后整体”的。
两个代码仓库合并打包,原服务的动态配置、限流/告警策略等,是否使用原服务的app标识进行获取、服务注册发现 是否使用目标服务的app标识等问题,核心需要本地化基建的支持。
服务合并部署
对于编译型语言,例如Go plugin支持将Go包编译为共享库(.so)的形式单独发布,主程序可以在运行时动态加载这些编译为动态共享库文件的go plugin。但要求依赖版本、Go编译版本都一致。
而Java,使用类加载隔离、实现多个服务的依赖隔离,可以在同一个JVM实例中部署多个服务。
但由于合并代码后,两个服务会共享一个进程,服务占用的资源、CPU消耗、磁盘占用等均会叠加,所以资源利用率低、磁盘、CPU、内存占用小的服务合并更有优势。
如果多个服务使用同一端口,会发生端口竞争,暴露端口时最好使用随机端口。
相关文章:
微服务合并
有的团队为了节约机器成本、有的团队为了提升研发效率、有的团队为了降低人均服务数 微服务合并,可以从多个角度入手 代码重构融合:人工拷贝代码、解决冲突,然后分阶段实施迁移重构。代码合并打包:将多个代码仓库,拉取…...

Shell脚本基础:用Bash自动化任务
Shell脚本基础:用Bash自动化任务 在Linux运维中,手动执行重复性任务既耗时又容易出错,而Shell脚本则为自动化提供了强大支持。 从基础概念到实用案例,逐步掌握用Bash实现自动化的核心技能。Shell脚本是Linux自动化的基石…...

基于W2605C语音识别合成芯片的智能语音交互闹钟方案-AI对话享受智能生活
随着科技的飞速发展,智能家居产品正逐步渗透到我们的日常生活中,其中智能闹钟作为时间管理的得力助手,也在不断进化。基于W2605C语音识别与语音合成芯片的智能语音交互闹钟,凭借其强大的联网能力、自动校时功能、实时天气获取、以…...

【Java项目】基于Spring Boot的网上商城购物系统
【Java项目】基于Spring Boot的网上商城购物系统 技术简介:采用Java技术、Spring Boot框架、MySQL数据库等实现。 系统简介:系统实现管理员:首页、个人中心、用户管理、商品分类管理、商品信息管理、订单评价管理、系统管理、订单管理&#x…...

开放标准(RFC 7519):JSON Web Token (JWT)
开放标准:JSON Web Token 前言基本使用整合Shiro登录自定义JWT认证过滤器配置Config自定义凭证匹配规则接口验证权限控制禁用session缓存的使用登录退出单用户登录Token刷新双Token方案单Token方案 前言 JSON Web Token (JWT) 是一种开放标准…...

JBoltAI_SpringBoot如何基于Deepseek官网API区分 R1大模型深度思考和具体回答的内容?
R1大模型推出后,Deepseek官网的API也更新了,我们可以看到 chat 接口的响应数据结果里多了一个reasoning_content 字段 于是我们的JBoltAI SDK 以及 SpringBoot版以及Jfinal版JBoltAI Platform 迅速跟进,提供了对深度思考的支持:…...
YOLOv11-ultralytics-8.3.67部分代码阅读笔记-model.py
model.py ultralytics\models\yolo\model.py 目录 model.py 1.所需的库和模块 2.class YOLO(Model): 3.class YOLOWorld(Model): 1.所需的库和模块 # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/licensefrom pathlib import Pathfrom ult…...

MySQL 事务笔记
MySQL 事务笔记 目录 事务简介事务操作事务四大特性并发事务问题事务隔离级别总结 事务简介 事务(Transaction)是数据库操作的逻辑单元,由一组不可分割的SQL操作组成。主要用于保证: 多个操作的原子性(要么全部成功…...

react使用拖拽,缩放组件,采用react-rnd解决
项目中需求,要求给商品图片添加促销标签,并且可拉伸大小,和拖拽位置 最后选择用react-rnd来实现 话不多说,直接上代码!!! 1.在项目根目录下执行以下代码,引入react-rnd yarn add r…...

【C++基础】什么是C++?
本文收录于 《C编程入门》专栏,从零基础开始,介绍C编程入门相关的内容,欢迎关注,谢谢! 文章目录 一、前言二、发展简史三、主要特性四、应用场景五、第一个C程序六、总结 一、前言 为了让初学者快速的了解C语言&#…...
3 算法1-3 火星人
题目描述 一个火星人用一个人类的手演示了如何用手指计数。如果把五根手指――拇指、食指、中指、无名指和小指分别编号为 1,2,3,4 和 5,当它们按正常顺序排列时,形成了 5 位数 12345,当你交换无名指和小指的位置时,会形成 5 位数…...

【原创工具】同文件夹PDF文件合并 By怜渠客
【原创工具】同文件夹PDF文件合并 By怜渠客 原贴:可批量合并多个文件夹内的pdf工具 - 吾爱破解 - 52pojie.cn 他这个存在一些问题,并非是软件内自主实现的PDF合并,而是调用的pdftk这一工具,但楼主并没有提供pdftk,而…...

数据结构-直接插入和希尔排序
这次,我们来讲数据结构的排序的直接插入。 一:排序的思想:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 相当于,我们打牌如上图…...
vue3表单验证的时候访问接口如果有值就通过否则不通过.主动去触发校验
页面有个身份证号码的校验。校验完身份证格式是否符合之后还要去访问接口查询这个用户是否存在。如果存在才通过验证。否则就校验不通过 <el-form ref"ruleFormRef" :model"form" label-width"140px" label-position"right" label…...

Trae根据原型设计稿生成微信小程序密码输入框的踩坑记录
一、需求描述 最近经常使用Trae生成一些小组件和功能代码(对Trae赶兴趣的可以看之前的文章《TraeAi上手体验》),刚好在用uniapp开发微信小程序时需要开发一个输入密码的弹框组件,于是想用Trae来实现。原型设计稿如下:…...

【数据结构】 最大最小堆实现优先队列 python
堆的定义 堆(Heap)是一种特殊的完全二叉树结构,通常分为最大堆和最小堆两种类型。 在最大堆中,父节点的值总是大于或等于其子节点的值; 而在最小堆中,父节点的值总是小于或等于其子节点的值。 堆常用于实…...
基于多层感知机(MLP)实现MNIST手写体识别
实现步骤 下载数据集处理好数据集确定好模型(初始化模型参数等等)确定优化函数(损失函数也称为目标函数)和优化方法(一般选用随机梯度下降 SDG )进行模型的训练进行模型的评估 import torch import torch…...
QT和有道词典有冲突,导致内存溢出,闪退。
提示:本文为学习记录,若有疑问,请联系作者。 前言 具体详细查看此博主:原文链接 在使用Qt Designer时,如果开启了有道词典,会导致Qt Designer崩溃。估计应该是把有道词典屏幕取词功能打开后,有…...
4. 示例:创建带约束的随机地址生成器(范围0x1000-0xFFFF)
文章目录 前言代码示例:运行方法:查看结果:关键功能说明:扩展功能建议: 前言 以下是一个完整的SystemVerilog测试平台示例,包含约束随机地址生成、日志输出和波形生成功能: 代码示例࿱…...

VSCode轻松调试运行C#控制台程序
1.背景 我一直都是用VS来开发C#项目的,用的比较顺手,也习惯了。看其他技术文章有介绍VS Code更轻量,更方便。所以我专门花时间来使用VS Code,看看它是如何调试代码、如何运行C#控制台。这篇文章是一个记录的过程。 2.操作 2.1 V…...

C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
基于 HTTP 的单向流式通信协议SSE详解
SSE(Server-Sent Events)详解 🧠 什么是 SSE? SSE(Server-Sent Events) 是 HTML5 标准中定义的一种通信机制,它允许服务器主动将事件推送给客户端(浏览器)。与传统的 H…...
jieba实现和用RNN实现中文分词的区别
Jieba 分词和基于 RNN 的分词在技术路线、实现机制、性能特点上有显著差异,以下是核心对比: 1. 技术路线对比 维度Jieba 分词RNN 神经网络分词范式传统 NLP(规则 统计)深度学习(端到端学习)核心依赖词典…...
软考 系统架构设计师系列知识点之杂项集萃(81)
接前一篇文章:软考 系统架构设计师系列知识点之杂项集萃(80) 第145题 商业智能是企业对商业数据的搜集、管理和分析的系统过程,主要技术包括()。 A. 数据仓库、联机分析和数据挖掘 B. 数据采集、数据清洗…...

代码随想录算法训练营第60期第六十天打卡
大家好,今天因为有数学建模比赛的校赛,今天的文章可能会简单一点,望大家原谅,我们昨天主要讲的是并查集的题目,我们复习了并查集的功能,我们昨天的题目其实难度不小,尤其是后面的有向图…...
瀚文机械键盘固件开发详解:HWKeyboard.cpp文件解析与应用
🔥 机械键盘固件开发从入门到精通:HWKeyboard模块全解析 作为一名嵌入式开发老司机,今天带大家拆解一个完整的机械键盘固件代码。即使你是单片机小白,看完这篇教程也能轻松理解机械键盘的工作原理,甚至自己动手复刻一…...