当前位置: 首页 > article >正文

MOSN(Modular Open Smart Network)-05-MOSN 平滑升级原理解析

前言

大家好,我是老马。

sofastack 其实出来很久了,第一次应该是在 2022 年左右开始关注,但是一直没有深入研究。

最近想学习一下 SOFA 对于生态的设计和思考。

sofaboot 系列

SOFAStack-00-sofa 技术栈概览

MOSN(Modular Open Smart Network)-00-简单聊一聊

MOSN(Modular Open Smart Network)-01-是一款主要使用 Go 语言开发的云原生网络代理平台

MOSN(Modular Open Smart Network)-02-核心概念

MOSN(Modular Open Smart Network)-03-流量劫持

MOSN(Modular Open Smart Network)-04-TLS 安全链路

MOSN(Modular Open Smart Network)-05-MOSN 平滑升级原理解析

MOSN(Modular Open Smart Network)-06-MOSN 多协议机制解析

MOSN(Modular Open Smart Network)-07-Sidecar 模式

MOSN(Modular Open Smart Network)-08-MOSN 扩展机制解析

平滑升级原理解析

如何在升级 Sidecar(MOSN)的时候而不影响业务,对于存量的长连接如何迁移,本文将为你介绍 MOSN 的解决之道。

Service Mesh 中 Sidecar 运维一直是一个比较棘手的问题,数据平面的 Sidecar 升级是常有的事情,如何在升级 Sidecar(MOSN)的时候而不影响业务,对于存量的长连接如何迁移,本文将为你介绍 MOSN 的解决之道。

背景

本文介绍 MOSN 支持平滑升级的原因和解决方案,对于平滑升级的一些基础概念,大家可以通过 Nginx vs Enovy vs Mosn 平滑升级原理解析了解。

先简单介绍一下为什么 Nginx 和 Envoy 不需要具备 MOSN 这样的连接无损迁移方案,主要还是跟业务场景相关,Nginx 和 Envoy 主要支持的是 HTTP1 和 HTTP2 协议,HTTP1使用 connection: Close,HTTP2 使用 Goaway Frame 都可以让 Client 端主动断链接,然后新建链接到新的 New process,但是针对 Dubbo、SOFA PRC 等常见的多路复用协议,它们是没有控制帧,Old process 的链接如果断了就会影响请求的。

一般的升级做法就是切走应用的流量,比如自己UnPub掉服务,等待一段时间没有请求之后,升级MOSN,升级好之后再Pub服务,整个过程比较耗时,并且会有一段时间是不提供服务的,还要考虑应用的水位,在大规模场景下,就很难兼顾评估。

MOSN 为了满足自身业务场景,开发了长连接迁移方案,把这条链接迁移到 New process 上,整个过程对 Client 透明,不需要重新建链接,达到请求无损的平滑升级。

MOSN 的请求无损的平滑升级过程

正常流程

正常流程

  1. Client 发送请求 Request 到 MOSN
  2. MOSN 转发请求 Request 到 Server
  3. Server 回复响应 Response 到 MOSN
  4. MOSN 回复响应 Response 到 Client

上图简单介绍了一个请求的正常流程,我们后面需要迁移的是 TCP1 链接,也就是 Client 到 MOSN 的连接,MOSN 到 Server 的链接 TCP2 不需要迁移,因为 MOSN 访问 Server 是根据 LoadBalance 选择,我们可以主动控制断链建链。

平滑升级流程

触发条件

有两个方式可以触发平滑升级流程:

  1. MOSN 对 SIGHUP 做了监听,发送 SIGHUP 信号给 MOSN 进程,通过 ForkExec 生成一个新的 MOSN 进程。
  2. 直接重新启动一个新 MOSN 进程。

为什么提供两种方式?最开始我们支持的是方法1,也就是 nginx 和 Envoy 使用的方式,这个在虚拟机或者容器内替换 MOSN 二级制来升级是可行的,但是我们的场景需要满足容器间的升级,所以需要新拉起一个容器,就需要重新启动一个新的 MOSN 进程来做平滑升级,所以后续又支持了方法2。容器间升级还需要 operator 的支持,本文不展开叙述。

交互流程

交互流程

交互流程时序图

首先,老的 MOSN 在启动最后阶段会启动一个协程运行 ReconfigureHandler() 函数监听一个 Domain Socket(reconfig.sock), 该接口的作用是让新的 MOSN 来感知是否存在老的 MOSN。

func ReconfigureHandler() {
l, err := net.Listen("unix", types.ReconfigureDomainSocket)for {
uc, err := ul.AcceptUnix()
_, err = uc.Write([]byte{0})
reconfigure(false)
}
}

触发平滑升级流程的两种方式最终都是启动一个新的 MOSN 进程,然后调用GetInheritListeners(),通过 isReconfigure() 函数来判断本机是否存在一个老的 MOSN(就是判断是否存在 reconfig.sock 监听),如果存在一个老的 MOSN,就进入迁移流程,反之就是正常的启动流程。

// 保留了核心流程
func GetInheritListeners() ([]net.Listener, net.Conn, error) {
if !isReconfigure() {
return nil, nil, nil
}l, err := net.Listen("unix", types.TransferListenDomainSocket)
uc, err := ul.AcceptUnix()
_, oobn, _, _, err := uc.ReadMsgUnix(buf, oob)
file := os.NewFile(fd, "")
fileListener, err := net.FileListener(file)
return listeners, uc, nil
}

如果进入迁移流程,新的 MOSN 将监听一个新的 Domain Socket(listen.sock),用于老的 MOSN 传递 listen FD 到新的 MOSN。FD 的传递使用了sendMsg 和 recvMsg。在收到 listen FD 之后,调用 net.FileListener() 函数生产一个 Listener。此时,新老 MOSN 都同时拥有了相同的 Listen 套接字。

// FileListener returns a copy of the network listener corresponding
// to the open file f.
// It is the caller's responsibility to close ln when finished.
// Closing ln does not affect f, and closing f does not affect ln.
func FileListener(f *os.File) (ln Listener, err error) {
ln, err = fileListener(f)
if err != nil {
err = &OpError{Op: "file", Net: "file+net", Source: nil, Addr: fileAddr(f.Name ()), Err: err}
}
return
}

这里的迁移和 Nginx 还是有一些区别,Nginx 是 fork 的方式,子进程自动就继承了 listen FD,MOSN 是新启动的进程,不存在父子关系,所以需要通过 sendMsg 的方式来传递。

在进入迁移流程和 Listen 的迁移过程中,一共使用了两个 Domain Socket:

  • reconfig.sock 是 Old MOSN 监听,用于 New MOSN 来判断是否存在
  • listen.sock 是 New MOSN 监听,用于 Old MOSN 传递 listen FD

两个 sock 其实是可以复用的,也可以用 reconfig.sock 进行 listen 的传递,由于一些历史原因搞了两个,后续可以优化为一个,让代码更精简易读。

这儿再看看 Old MOSN 的处理,在收到 New MOSN 的通知之后,将进入reconfigure(false) 流程,首先就是调用 sendInheritListeners() 传递 listen FD,原因上面内容已经描述,最后调用 WaitConnectionsDone() 进入存量长链接的迁移流程。

// 保留了核心流程
func reconfigure(start bool) {
if start {
startNewMosn()
return
}
// transfer listen fd
if notify, err = sendInheritListeners(); err != nil {
return
}
// Wait for all connections to be finished
WaitConnectionsDone(GracefulTimeout)os.Exit(0)
}

在 Listen FD 迁移之后,New MOSN 通过配置启动,然后在最后启动一个协程运行TransferServer(),将监听一个新的 DomainSocket(conn.sock),用于后续接收 Old MOSN 的长连接迁移。迁移的函数是 transferHandler()

func TransferServer(handler types.ConnectionHandler) {
l, err := net.Listen("unix", types.TransferConnDomainSocket)utils.GoWithRecover(func() {
for {
c, err := l.Accept()
go transferHandler(c, handler, &transferMap)}
}, nil)
}

Old MOSN 将通过 transferRead()transferWrite() 进入最后的长链接迁移流程,下面主要分析这块内容。

总结

长连接的 FD 迁移是比较常规的操作,sendMsg 和 connection repair 都可以。

在整个过程中最麻烦的是应用层数据的迁移,一般想法就是把应用层的数据结构等都迁移到新的进程,比如已经读取的协议 HEAD 等结构体,但这就导致你的迁移过程会很复杂,每个协议都需要单独处理。

MOSN 的方案是把迁移放到了 IO 层,不关心应用层具体是什么协议,我们迁移最原始的 TCP 数据包,然后让 New MOSN 来 codec 这个数据包来拼装 HEAD 等结构体,这个过程

相关文章:

MOSN(Modular Open Smart Network)-05-MOSN 平滑升级原理解析

前言 大家好,我是老马。 sofastack 其实出来很久了,第一次应该是在 2022 年左右开始关注,但是一直没有深入研究。 最近想学习一下 SOFA 对于生态的设计和思考。 sofaboot 系列 SOFAStack-00-sofa 技术栈概览 MOSN(Modular O…...

Flink介绍与安装

Apache Flink是一个在有界数据流和无界数据流上进行有状态计算分布式处理引擎和框架。Flink 设计旨在所有常见的集群环境中运行,以任意规模和内存级速度执行计算。 一、主要特点和功能 1. 实时流处理: 低延迟: Flink 能够以亚秒级的延迟处理数据流,非常…...

【gradio】从零搭建知识库问答系统-Gradio+Ollama+Qwen2.5实现全流程

从零搭建大模型问答系统-GradioOllamaQwen2.5实现全流程(一) 前言一、界面设计(计划)二、模块设计1.登录模块2.注册模块3. 主界面模块4. 历史记录模块 三、相应的接口(前后端交互)四、实现前端界面的设计co…...

PowerBI,用度量值实现表格销售统计(含合计)的简单示例

假设我们有产品表 和销售表 我们想实现下面的效果 表格显示每个产品的信息,以及单个产品的总销量 有一个切片器能筛选各个门店的产品销量 还有一个卡片图显示所筛选条件下,所有产品的总销量 实现方法: 1.我们新建一个计算表,把…...

Mac 常用命令

一、文件操作(必知必会)​ ​1. 快速导航 cd ~/Documents # 进入文档目录 cd .. # 返回上级目录 pwd # 显示当前路径 2. ​文件管理 touch new_file.txt # 创建空文件 mkdir -p project/{src,docs} # 递归创建目录 cp …...

26考研——查找_树形查找_二叉排序树(BST)(7)

408答疑 文章目录 三、树形查找二叉排序树(BST)二叉排序树中结点值之间的关系二叉树形查找二叉排序树的查找过程示例 向二叉排序树中插入结点插入过程示例 构造二叉排序树的过程构造示例 二叉排序树中删除结点的操作情况一:被删除结点是叶结点…...

美摄科技开启智能汽车车内互动及娱乐解决方案2.0

在科技飞速发展的今天,汽车已不再仅仅是简单的代步工具,而是逐渐演变为集出行、娱乐、社交于一体的智能移动空间。美摄科技,作为前沿视觉技术与人工智能应用的领航者,凭借其卓越的技术实力和创新精神,携手汽车行业&…...

【行驶证识别】批量咕嘎OCR识别行驶证照片复印件图片里的文字信息保存表格或改名字,基于QT和腾讯云api_ocr的实现方式

项目背景 在许多业务场景中,如物流管理、车辆租赁、保险理赔等,常常需要处理大量的行驶证照片复印件。手动录入行驶证上的文字信息,像车主姓名、车辆型号、车牌号码等,不仅效率低下,还容易出现人为错误。借助 OCR(光学字符识别)技术,能够自动识别行驶证图片中的文字信…...

Vue-admin-template安装教程

#今天配置后台管理模板发现官方文档的镜像网站好像早失效了,自己稍稍总结了一下方法# 该项目环境需要node17及以下,如果npm install这一步报错可能是这个原因 git clone https://github.com/PanJiaChen/vue-admin-template.git cd vue-admin-template n…...

21.Excel自动化:如何使用 xlwings 进行编程

一 将Excel用作数据查看器 使用 xlwings 中的 view 函数。 1.导包 import datetime as dt import xlwings as xw import pandas as pd import numpy as np 2.view 函数 创建一个基于伪随机数的DataFrame,它有足够多的行,使得只有首尾几行会被显示。 df …...

LabVIEW FPGA与Windows平台数据滤波处理对比

LabVIEW在FPGA和Windows平台均可实现数据滤波处理,但两者的底层架构、资源限制、实时性及应用场景差异显著。FPGA侧重硬件级并行处理,适用于高实时性场景;Windows依赖软件算法,适合复杂数据处理与可视化。本文结合具体案例&#x…...

【NLP 48、大语言模型的神秘力量 —— ICL:in context learning】

目录 一、ICL的优势 1.传统做法 2.ICL做法 二、ICL的发展 三、ICL成因的两种看法 1.meta learning 2.Bayesian Inference 四、ICL要点 ① 语言模型的规模 ② 提示词prompt中提供的examples数量和顺序 ③ 提示词prompt的形式(format) 五、fine-tune VS I…...

vue 中渲染 markdown 格式的文本

文章目录 需求分析第一步:安装依赖第二步:创建 Markdown 渲染组件第三步,使用实例扩展功能1. 代码高亮:2. 自定义渲染规则:需求 渲染 markdown 格式的文本 分析 在Vue 3中实现Markdown渲染的常见方法。通常有两种方式:使用现有的Markdown解析库,或者自己编写解析器…...

工业4G路由器赋能智慧停车场高效管理

工业4G路由器作为智慧停车场管理系统通信核心,将停车场内的各个子系统连接起来,包括车牌识别系统、道闸控制系统、车位检测系统、收费系统以及监控系统等。通过4G网络,将这些系统采集到的数据传输到云端服务器或管理中心,实现信息…...

卡尔曼滤波入门(二)

核心思想 卡尔曼滤波的核心就是在不确定中寻找最优,那么怎么定义最优呢?答案是均方误差最小的,便是最优。 卡尔曼滤波本质上是一种动态系统状态估计器,它回答了这样一个问题: 如何从充满噪声的观测数据中&#xff0c…...

企业如何平稳实现从Tableau到FineBI的信创迁移?

之前和大家分享了《如何将Tableau轻松迁移到Power BI》。但小编了解到,如今有些企业更愿意选择国产BI平台。为此,小编今天以Fine BI为例子,介绍如何从Tableau轻松、低成本地迁移到国产BI平台。 在信创政策全面推进的背景下,企业数…...

蓝桥与力扣刷题(蓝桥 蓝桥骑士)

题目:小明是蓝桥王国的骑士,他喜欢不断突破自我。 这天蓝桥国王给他安排了 N 个对手,他们的战力值分别为 a1,a2,...,an,且按顺序阻挡在小明的前方。对于这些对手小明可以选择挑战,也可以选择避战。 身为高傲的骑士&a…...

前端学习笔记--CSS

HTMLCSSJavaScript 》 结构 表现 交互 如何学习 1.CSS是什么 2.CSS怎么用? 3.CSS选择器(重点,难点) 4.美化网页(文字,阴影,超链接,列表,渐变。。。) 5…...

阶段一:Java基础语法

目标:掌握Java的基本语法,理解变量、数据类型、运算符、控制结构等。 1. Java开发环境搭建 安装JDK配置环境变量编写第一个Java程序 代码示例: // HelloWorld.java public class HelloWorld { // 定义类名为 HelloWorldpublic static vo…...

31天Python入门——第15天:日志记录

你好,我是安然无虞。 文章目录 日志记录python的日志记录模块创建日志处理程序并配置输出格式将日志内容输出到控制台将日志写入到文件 logging更简单的一种使用方式 日志记录 日志记录是一种重要的应用程序开发和维护技术, 它用于记录应用程序运行时的关键信息和…...

深度学习框架PyTorch——从入门到精通(10)PyTorch张量简介

这部分是 PyTorch介绍——YouTube系列的内容,每一节都对应一个youtube视频。(可能跟之前的有一定的重复) 创建张量随机张量和种子张量形状张量数据类型 使用PyTorch张量进行数学与逻辑运算简单介绍——张量广播关于张量更多的数学操作原地修改…...

前端批量导入方式

webpack批量导入 webpack中使用 require.context 实现自动导入 const files require.context(./modules, false, /\.ts$/); const modules {}; files.keys().forEach((key) > {if (key ./index.ts) { return; }modules[key.replace(/(\.\/|\.ts)/g, )] files(key).def…...

使用ucharts写的小程序,然后让圆环中间的空白位置变大

将ringWidth属性调小 extra: { ring: { ringWidth: 20, activeOpacity: 1.5, activeRadius: 10, offsetAngle: 0, labelWidth: 15, border: true, borderWidth: 0, borderColor: #F…...

GPT-4o Image

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...

SpringMVC请求与响应深度解析:从核心原理到高级实践

一、SpringMVC架构与核心组件剖析 SpringMVC是基于Java的MVC设计模型实现的轻量级Web框架,其核心架构围绕前端控制器模式构建。以下是核心组件及其作用: DispatcherServlet 作为前端控制器,所有请求首先到达此处。它负责请求分发、协调组件协…...

大模型量化框架GPTQModel的基本使用方法

接上一篇博客:AutoGPTQ报torch._C._LinAlgError: linalg.cholesky: The factorization could not be completed的解决办法-CSDN博客 如果Llama factory量化一直报错,可以改用其他的量化框架,例如GPTQ:https://github.com/ModelCl…...

C++:函数(通识版)

一、函数的基础 1.什么是函数?(独立的功能单位) 函数是C中封装代码逻辑的基本单元,用于执行特定任务。 作用:代码复用、模块化、提高可读性。 2、函数的基本结构 返回类型 函数名(参数列表) {// 函数体return 返回值…...

Spring AI相关的面试题

以下是150道Spring AI相关的面试题目及答案: ### Spring AI基础概念类 **1. 什么是Spring AI?** Spring AI是Spring框架的扩展,旨在简化人工智能模型在Java应用中的集成与使用,提供与Spring生态无缝衔接的工具和抽象&#xff0c…...

无线安灯按钮盒汽车零部件工厂的故障告警与人员调度专家

在汽车零部件制造领域,生产线故障与物料短缺等问题往往引发连锁反应,导致停机损失与成本激增。传统人工巡检与纸质工单模式已难以满足高效生产需求,而无线安灯按钮盒的智能化应用,正成为破解这一难题的关键利器。 一、精准告警&am…...

登录接口带验证码自动化(tesseract-OCR)

登录接口是很多网站和应用程序中必不可少的一部分。为了增加安全性,很多登录接口还会加入验证码的验证步骤,以防止恶意登录行为。 通常,遇到这样情况时有以下解决办法 1、使用万能验证码:如果遇到前台输入的是万能验证码&#xf…...