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

context 浅析

在缺少直接调用关系的两个函数之间传递数据,一般都会考虑使用 context,而 context 也被用来存储整个请求链路的公参信息,用户 uid、链路 traceID、特定的业务参数等。函数第一个参数类型设置为 context.Context 也是 Go 的默认写法,如果你对是否指定 ctx 作为函数的第一个入参,感觉到模棱两可,那就指定它吧。

树状链路结构

context 的惯用模式是覆写,比如下面的 Printable 函数,参数 ctx 在函数内部被覆写了。而这个操作在当前的 context 链路上又追加上了一个节点,其实也是将 context 切换到一个新的 context 上。通过这种模式,每个方法都有了自己独立的 context 变量,并且可以查找到到上级的 context,整个调用链路都可以通过 context 来还原。

func Printable(ctx context.Context) {ctx = context.WithValue(ctx, "key", "value")// ......
}

下面这个绿色的 ctx,通过它可以获取到红色的父 ctx 和蓝色的子 ctx。创建子 ctx 的方式就是官方提供的 ctx 覆写的方式。树结构的每一条链路都是链表结构,每个 context 内部记录了指向父节点的指针。函数 WithValue 的注释有这样一段描述:WithValue returns a copy of parent in which the value associated with key is val. 但 WithValue 传递的参数类型实际是指针,这里应该只是想强调指针引用的拷贝。
在这里插入图片描述
除了通过当前节点找到父节点,还需要能查找到当前节点的所有子节点。但通过 WithValue 创建的节点并没有保存子节点的信息,也就无法查找到子节点列表,WithValue 被设计用来存储当前链路的值,查找某个具体的 key 值时,需要逐层向父节点查找,当前节点此时此刻也不包含任何子节点。

下图最左边的蓝色 ctx 查找某个 key 值时,会逐步向上查找。假如红色和绿色的 ctx 设置了相同的 key 值,会返回绿色 ctx 的 value,因为这种链路的层次关系,红色的 key 值会被覆盖掉。通过这样的设计,ctx 中的变量具有了作用域范围,红色 ctx 不能访问绿色 ctx 中的值,绿色 ctx 可以“覆盖”红色 ctx 的值。
在这里插入图片描述

孩子节点

WithValue 创建的 ctx 中没有维护孩子节点的信息,所以,接下来我们使用 WithCancel 对树形链路做分析。 cancelCtx 结构体的 children 存储了孩子节点的信息。children 是 map 类型,对应的 value 是空的结构体类型,而空的结构体不占用任何内存空间,所以 key 是关键,key 是 canceler 接口类型。

children 不支持并发读写,err 也需要并发保护,cancelCtx 通过 sync.Mutex 来控制并发。atomic.Value 本身就只原子类型,理论上是不需要加锁保护的。

// A cancelCtx can be canceled. When canceled, it also cancels any children
// that implement canceler.
type cancelCtx struct {Contextmu       sync.Mutex            // protects following fieldsdone     atomic.Value          // of chan struct{}, created lazily, closed by first cancel callchildren map[canceler]struct{} // set to nil by the first cancel callerr      error                 // set to non-nil by the first cancel call
}

WithCancel 在新建节点的时候,首先要查找到对应的父节点,然后注册到父节点的 children 中,这样就建立了父子节点的对应关系。关键是查找到对应的父节点,因为父节点可能不是 WithCancel 函数传入的 ctx,而是“血型”匹配的父节点,下图蓝色的 cancelCtx 就找不到对应的父节点。

withCancel.1
再比如下图的右子树,两个浅黄色的 cancelCtx 并不存在父子关系,因为中间被 valueCtx 给隔开了。所以,关键点是判断 WithCancel 调用时的 parent 的参数类型。两个 cancelCtx 节点能否建立父子关系,首先需要类型匹配,其次需要父节点是有效的。

我们可以理解为 cancelCtx 其实是局部树,它在整个 context 树状结构中是独立的一颗颗小子树。这样的设计方式,应该和 cancelCtx 的要处理的场景有关系,毕竟 cancelCtx 是被用来处理小范围内的调用取消控制的。
在这里插入图片描述

WithValue 参考扩展

前文已经介绍过,WithValue 创建的节点并不会保存子节点的信息。但我们可以做扩展,让 WithValue 支持保存父子节点的关系。有了这层关系,我们可以将整个服务的调用链通过 ctx 关联起来,可视化地将树形结构显示出来。竖向表示串联逻辑,横向表示包含逻辑,下图中的“历史记录”和“同地域”表示并行逻辑。

在这里插入图片描述
微服务通过在入口生成统一的 traceID 来关联所有的服务,通过 traceID 来排查链路调用的问题。但通过 traceID 查询到的一条条日志缺少业务逻辑聚合关系,表面上是按服务维度进行划分的,但粒度太大了。

我们可以利用 context 实现业务逻辑层面的粒度划分,比如将整个业务域划分成召回、过滤、排序三个大逻辑,每个逻辑内部再继续划分成多个小逻辑,整个链路共用同一个 traceID,但每个业务域内生成特有的 ID 来标志对应的业务域。最终,通过业务逻辑的调用图将日志信息可视化展示出来。

我们参考 WithValue 的实现,当进入到召回逻辑时,我们启用一个业务域,在 ctx 中设置当前的业务域为“召回”,当进入到“过滤逻辑时”,我们将当前的业务域设置为“过滤”,以此类推,我们将整个链路通过树的结构连接起来。这样,一个可视化的日志排查链路就设计好了。

树形结构的表示

在 api 的交互中,要表示一个树形结构,数据结构该如何组织呢?

业务执行流程都是串行向下的,但可能存在某一阶段多路并行的情况。比如下图中黄色的圈,表示异步执行多路逻辑。按照 context 的组织思路,context 是一个树状的组织结构,子节点仅能唯一确认一个父节点,不能对应多个父节点。所以,图中红色的节点就比较尴尬,但又实际存在。

在这里插入图片描述

我们先确认最终的数据结构,基于这个数据结构,就可以简单连线构造出上面的图形。而且,根据现在的结果去推导实现的过程,思路就会开阔起来。让我想到一个Question:如何提出一个好的问题。

type node struct {*Mchildren []*T
}

上面是伪代码的描述,node 表示图中的一个节点,*M表示节点的属性,其中 children 用来表示节点有哪些子节点。最后,我们将所有的节点和子节点连接起来,就可以构成上面的图形。

回到图示,context 结构中,蓝色的子节点包含黄色,以及红色(右图),只是我们用上图的形式做了展示(左图)。黄色的连线逻辑就变成:有父节点,没有子节点,且父节点还指向了下一个流程的红色节点。

相关文章:

context 浅析

在缺少直接调用关系的两个函数之间传递数据,一般都会考虑使用 context,而 context 也被用来存储整个请求链路的公参信息,用户 uid、链路 traceID、特定的业务参数等。函数第一个参数类型设置为 context.Context 也是 Go 的默认写法&#xff0…...

Bandizip已管理员身份运行

系列文章目录 文章目录 系列文章目录前言一、Bandzib是什么?二、使用步骤1.引入库 前言 在解压krita源码包时Bandizip报错 一、Bandzib是什么? bandzip官网 Bandizip 是一款压缩软件,它支持Zip、7-Zip 和 RAR 以及其它压缩格式。它拥有非…...

LiveCharts2 初步认识

文章目录 1 LiveCharts2 是什么?2 LiveCharts2 可以做什么?3 简单使用LiveCharts2 ,实现动态曲线图 1 LiveCharts2 是什么? GitHub:https://github.com/beto-rodriguez/LiveCharts2 官网: https://lvchar…...

Java设计模式 11-代理模式

代理模式 一、 代理模式(Proxy) 1、代理模式的基本介绍 代理模式:为一个对象提供一个替身,以控制对这个对象的访问。即通过代理对象访问目标对象.这样做的好处是: 可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。被代理的对象…...

Python综合案例-小费数据集的数据分析(详细思路+源码解析)

目录 1. 请导入相应模块并获取数据。导入待处理数据tips.xls,并显示前5行。 2、分析数据 3.增加一列“人均消费” 4查询抽烟男性中人均消费大于5的数据 5.分析小费金额和消费总额的关系,小费金额与消费总额是否存在正相关关系。画图观察。 6分析男女顾…...

软件安全测试

软件安全性测试包括程序、网络、数据库安全性测试。根据系统安全指标不同测试策略也不同。 1.用户程序安全的测试要考虑问题包括: ① 明确区分系统中不同用户权限; ② 系统中会不会出现用户冲突; ③ 系统会不会因用户的权限的改变造成混乱; ④ 用户登陆密码是否…...

Scala模式匹配

Scala中有一个非常强大的模式匹配机制,应用也非常广泛, 例如: 判断固定值 类型查询 快速获取数据 简单模式匹配 一个模式匹配包含了一系列备选项,每个备选项都开始于关键字 case。且每个备选项都包含了一个模式及一到多个表达式。箭头符号 > 隔开…...

银行数仓分层架构

一、为什么要对数仓分层 实现好分层架构,有以下好处: 1清晰数据结构: 每一个数据分层都有对应的作用域,在使用数据的时候能更方便的定位和理解。 2数据血缘追踪: 提供给业务人员或下游系统的数据服务时都是目标数据&…...

Go并发编程的学习代码示例:生产者消费者模型

文章目录 前言代码仓库核心概念main.go(有详细注释)结果总结参考资料作者的话 前言 Go并发编程学习的简单代码示例:生产者消费者模型。 代码仓库 yezhening/Programming-examples: 编程实例 (github.com)Programming-examples: 编程实例 (g…...

求a的n次幂

文章目录 求a的n次幂程序设计程序分析求a的n次幂 【问题描述】要求利用书上介绍的从左至右二进制幂算法求a的n次幂; 【输入形式】输入两个正整数,一个是a,一个是n,中间用空格分开 【输出形式】输出一个整数 【样例输入】2 10 【样例输出】1024 【样例输入】3 4 【样例输出】…...

word脚标【格式:第X页(共X页)】

不得不吐槽一下这个论文,真的我好头疼啊。我又菜又不想改。但是还是得爬起来改 (是谁大半夜不能睡觉加班加点改格式啊) 如何插入页码。 格式、要求如下: 操作步骤: ①双击页脚,填好格式,宋体小四和居中都…...

Linux --- 软件安装、项目部署

一、软件安装 1.1、软件安装方式 在Linux系统中,安装软件的方式主要有四种,这四种安装方式的特点如下: 1.2、安装JDK 上述我们介绍了Linux系统软件安装的四种形式,接下来我们就通过第一种(二进制发布包)形式来安装 JDK。 JDK…...

MATLAB应用笔记

其他 1、NaN值 MATLAB判断数据是否为NaN可以直接使用函数:isnan() 三、数据分析 1、相关性 均值、方差、协方差、标准差、相关系数 mean() %均值 nanmean()%去除NAN值求均值 var() %方差 cov() %协方差 std() %标准差 corrcoef(B,b) %R 相关系数plot()…...

ERTEC200P-2 PROFINET设备完全开发手册(6-2)

6.2 诊断与报警实验 首先确认固件为 App1_STANDARD, 将宏定义改为: #define EXAMPL_DEV_CONFIG_VERSION 1 参照第6节的内容,编译和调试固件,并在TIA Portal 中建立RT项目。启动固件后,TIA Portal 切换到在线,可以看…...

算法套路八——二叉树深度优先遍历(前、中、后序遍历)

算法套路八——二叉树深度优先遍历(前、中、后序遍历) 算法示例:LeetCode98:验证二叉搜索树 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下: 节点的左子树只…...

视频批量剪辑:如何给视频添加上下黑边并压缩视频容量。

视频太多了,要如何进行给视频添加上下黑边并压缩视频容量?今天就由小编来教教大家要如何进行操作,感兴趣的小伙伴们可以来看看。 首先,我们要进入视频剪辑高手主页面,并在上方板块栏里选择“批量剪辑视频”板块&#…...

那些你需要知道的互联网广告投放知识

作为一个合格的跨境电商卖家,我们除了有好的产品之外,还要知道怎么去营销我们自己的产品。没有好的推广,即使你的产品有多好别人也是很难看得到的。今天龙哥就打算出一期基础的互联网广告投放科普,希望可以帮到各位增加多一点相关…...

【hello Linux】进程程序替换

目录 1. 程序替换的原因 2. 程序替换原理 3. 替换函数 4. 函数解释 5. 命名理解 6.简陋版shell的制作 补充: Linux🌷 1. 程序替换的原因 进程自创建后只能执行该进程对应的程序代码,那么我们若想让该进程执行另一个“全新的程序”这 便要用…...

【网络应用开发】实验4——会话管理

目录 会话管理预习报告 一、实验目的 二、实验原理 三、实验预习内容 1. 什么是会话,一个会话的生产周期从什么时候,到什么时候结束? 2. 服务器是如何识别管理属于某一个特定客户的会话的? 3. 什么是Cookie,它的…...

Linux服务器怎么分区

Linux服务器怎么分区 我是艾西,linux系统除了从业某个行业经常要用到的程序员比较熟悉,对于小白或只会用Windows系统的小伙伴还是会比较难上手的。今天艾西简单的跟大家聊聊linux系统怎么分区,让身为小白的你也能一眼看懂直接上手操作感受程序…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

MySQL 部分重点知识篇

一、数据库对象 1. 主键 定义 &#xff1a;主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 &#xff1a;确保数据的完整性&#xff0c;便于数据的查询和管理。 示例 &#xff1a;在学生信息表中&#xff0c;学号可以作为主键&#xff…...

MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用

文章目录 一、背景知识&#xff1a;什么是 B-Tree 和 BTree&#xff1f; B-Tree&#xff08;平衡多路查找树&#xff09; BTree&#xff08;B-Tree 的变种&#xff09; 二、结构对比&#xff1a;一张图看懂 三、为什么 MySQL InnoDB 选择 BTree&#xff1f; 1. 范围查询更快 2…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

第八部分:阶段项目 6:构建 React 前端应用

现在&#xff0c;是时候将你学到的 React 基础知识付诸实践&#xff0c;构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段&#xff0c;你可以先使用模拟数据&#xff0c;或者如果你的后端 API&#xff08;阶段项目 5&#xff09;已经搭建好&#xff0c;可以直接连…...

【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解

一、前言 在HarmonyOS 5的应用开发模型中&#xff0c;featureAbility是旧版FA模型&#xff08;Feature Ability&#xff09;的用法&#xff0c;Stage模型已采用全新的应用架构&#xff0c;推荐使用组件化的上下文获取方式&#xff0c;而非依赖featureAbility。 FA大概是API7之…...