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

CNI 网络流量分析(六)Calico 介绍与原理(一)

文章目录

  • CNI 网络流量分析(六)Calico 介绍与原理(一)
    • 介绍
    • 安装
    • Calico-node
      • 初始化
      • Calico-node 服务
        • Felix
        • confd
        • allocate-tunnel-addrs
        • monitor-addresses
        • monitor-token
        • status-reporter
        • bird
      • calico-kube-controllers

CNI 网络流量分析(六)Calico 介绍与原理(一)

介绍

Calico是一套开源的网络和网络安全解决方案,用于容器、虚拟机、宿主机之前的网络连接,它是一个纯三层的虚拟化网络解决方案,它把每个节点都作为一个虚拟路由器,并把每个节点上的Pod当作是节点路由器后的一个终端设备并为其分配一个IP地址。各节点路由器通过BGP协议生成路由规则,从而实现不通节点上Pod间的通信。

与Flannel相比,Calico的一个显著优势是对网络策略的支持,它允许用户定义访问控制规则以管控进出Pod的数据报文,从而为Pod间的通信施加安全策略。

BGP是一个去中心化自治路由协议,它通过维护IP路由表或“前缀”来实现自治系统之间的可达性,通常作为大规模数据中心维护不同自治系统之间路由信息的矢量路由协议。Linux内核原生支持BGP,因此可以把一台Linux主机配置为边界网关。

Calico把每个节点上Pod组成的网络视为一个自治系统(AS),而每个节点就相当于自治系统的边界网关。各节点之间通过BGP协议交换路由信息并生成路由规则。但并非所有的网络环境都能支持BGP,而且BGP路由模型要求所有节点位于同一个二层网络中,所以Calico还支持基于IPIP和VXLAN的Overlay网络模型。

另外,类似于Flannel的 VXALN后端启用Directrouting时的网络模型,Calico也支持混合使用路由和Overlay网络模型,BGP路由模型用于二层网络的高性能通信,IPIP或VXLAN用于跨二层网络节点间Pod报文的转发

Calico可以将关键配置抽象为资源类型,并允许用户按需自定义资源对象已完成系统配置。
如 pod 对应 WorkloadEndpoint,同名的 node,networkpolicy 等,都有 calico 独特的结构

apiVersion: projectcalico.org/v3
items:
- apiVersion: projectcalico.org/v3kind: WorkloadEndpointmetadata:creationTimestamp: "2023-02-06T13:03:01Z"labels:projectcalico.org/namespace: defaultprojectcalico.org/orchestrator: k8sprojectcalico.org/serviceaccount: defaultname: node111-k8s-pod1-eth0namespace: defaultresourceVersion: "4288996"uid: 2fb01a9c-2796-4ef5-aea1-a3deb12c64fespec:containerID: 96999978a9691f840410abadc6751f8a99bf1840df882242dcb59554c922b2c0endpoint: eth0interfaceName: calice0906292e2ipNetworks:- 10.244.153.204/32node: node111orchestrator: k8spod: pod1ports:- hostIP: ""hostPort: 0name: nginx-portport: 80protocol: TCPprofiles:- kns.default- ksa.default.defaultserviceAccountName: default

安装

获取 yaml

wget https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml

修改并 apply,默认是 ipip 类型
使用 bgp

- name: CALICO_IPV4POOL_IPIP
value: Always
- name: CALICO_AUTODETECTION_METHOD
value: interface=eth0

安装完成后,cni 配置如下

/etc/cni/net.d/10-calico.conflist 
{"name": "k8s-pod-network","cniVersion": "0.3.1","plugins": [{"type": "calico","log_level": "info","log_file_path": "/var/log/calico/cni/cni.log","datastore_type": "kubernetes","nodename": "node111","mtu": 0,"ipam": {"type": "calico-ipam"},"policy": {"type": "k8s"},"kubernetes": {"kubeconfig": "/etc/cni/net.d/calico-kubeconfig"}},{"type": "portmap","snat": true,"capabilities": {"portMappings": true}},{"type": "bandwidth","capabilities": {"bandwidth": true}}]
}

部署共有一个 deployment calico-kube-controller,一个 ds calico-node。

Calico-node

Calico-node 作为 cni 以 ds 形式部署在每一个节点

初始化

根据 pod 的 initContainers:

  1. calico-ipam -upgrade
    -upgrade 如果为 true 将在节点上迁移 host-local 到 calico-ipam;获取 k8s 权限
  • 获取 node 信息,使用 host-local 分配的子网
  • 获取 隧道 ip 并 通过 IPAM().AssignIP 进行分配
            tunIp := ip.To4()tunIp[3]++ // 最后一位加 1,即 10.244.0.1 对于 10.244.0.0/16
  • 从 host-local 本地存储的 pod IP 信息,再获取 pod 列表进行分析并 通过 IPAM().AssignIP 进行分配
  • 清空 host-local 本地存储
  1. /opt/cni/bin/install
  • 通过 env 获取配置
CNIConfName: 10-calico.conflist
CNINetworkConfig: cni 配置内容
SLEEP:False
UpdateCNIBinaries:True
  • 利用 k8s 配置文件生成 k8s client
  • 拷贝镜像中 二进制到 /opt/cni/bin/
  • 将 k8s 认证信息存在 /etc/cni/net.d/calico-kubeconfig
  • 生成 cni 配置在 /etc/cni/net.d/10-calico.conflist
  • 不停循环检查 etcd 认证是否更新,更新了存在 /etc/cni/net.d/calico-tls/
  1. calico-node -init -best-effort
    配置节点内容,参数很多,根据不同参数对 node 做配置
    如默认的 -init -best-effort:确保 bpf 文件和 cgroupv2 系统挂载(cat /proc/mounts |grep bpf)
    如有 从 /etc/calico/felix.cfg 配置运行 felix 等等

Calico-node 服务

Liveness 和 readiness 通过 /bin/calico-node -felix-live -bird-live 进行检查
关闭时 /bin/calico-node -shutdown

启动时运行 start_runit 脚本

#!/bin/sh
# From https://github.com/faisyl/alpine-runit
env > /etc/envvars/etc/rc.local
retval=$?
if [ $retval -ne 0 ];
thenecho >&2 "Calico node failed to start"exit $retval
fi# Export the nodename set by the startup procedure. 
export NODENAME=$(cat /var/lib/calico/nodename)RUNSVDIR=$(/usr/bin/which runsvdir)                  // /usr/local/bin/runsvdir
exec ${RUNSVDIR} -P /etc/service/enabled

runit 当服务器启动时启动定义好的服务,监控运行的服务,当服务中断时,将服务拉起;
如 runsvdir -P /etc/service/enabled 即 pod 启动后运行和监控 /etc/service/enabled 服务。

/etc/service/enabled 路径下有以下文件夹,即有以下服务

allocate-tunnel-addrs  bird6  confd  monitor-addresses
bird                       cni    felix  node-status-reporter

比如其中 allocate-tunnel-addrs 目录下有 run 脚本

#!/bin/sh
exec 2>&1
exec calico-node -allocate-tunnel-addrs

实际运行 calico-node -allocate-tunnel-addrs

查看进程,8 个进程

root     2235412  1.1  0.7 2042928 62252 ?       Sl   Feb06  22:55 calico-node -felix
root     2235413  0.0  0.6 1673500 53488 ?       Sl   Feb06   0:12 calico-node -allocate-tunnel-addrs
root     2235414  0.0  0.6 1673244 50064 ?       Sl   Feb06   0:12 calico-node -status-reporter
root     2235415  0.0  0.6 1673756 51672 ?       Sl   Feb06   0:13 calico-node -monitor-addresses
root     2235416  0.0  0.6 1821220 52772 ?       Sl   Feb06   0:13 calico-node -confd
root     2235417  0.0  0.5 1673500 48024 ?       Sl   Feb06   0:08 calico-node -monitor-token
root     2235714  0.0  0.0   1896  1452 ?        S    Feb06   0:27 bird -R -s /var/run/calico/bird.ctl -d -c /etc/calico/confd/config/bird.cfg
root     2235715  0.0  0.0   1908  1456 ?        S    Feb06   0:23 bird6 -R -s /var/run/calico/bird6.ctl -d -c /etc/calico/confd/config/bird6.cfg

主要看这些服务

Felix

Felix是一个守护程序,在每个 endpoints 的节点上运行。Felix 负责编制路由和 ACL 规则等,以便为该主机上的 endpoints 资源正常运行提供所需的网络连接
主要实现一下工作

  • 管理网络接口,Felix 将有关接口的一些信息写到内核,以使内核能够正确处理该 endpoint 发出的流量。 特别是,它将确保主机正确响应来自每个工作负载的ARP请求,并将为其管理的接口启用IP转发支持。它还监视网络接口的出现和消失,以便确保针对这些接口的编程得到了正确的应用。
  • 编写路由,Felix负责将到其主机上endpoints的路由编写到Linux内核FIB(转发信息库)中。 这可以确保那些发往目标主机的endpoints的数据包被正确地转发。
  • 编写 ACLs,Felix还负责将ACLs编程到Linux内核中。 这些ACLs用于确保只能在endpoints之间发送有效的网络流量,并确保endpoints无法绕过Calico的安全措施。
  • 报告状态,Felix 负责提供有关网络健康状况的数据。 特别是,它将报告配置其主机时发生的错误和问题。 该数据会被写入etcd,以使其对网络中的其他组件和操作才可见
  1. Felix 启动配置 /etc/calico/felix.cfg
[global]
MetadataAddr = None
LogFilePath = None
LogSeverityFile = None
LogSeveritySys = None
  1. 从 env 加载配置比较重要的有
DatastoreType: Kubernetes
  1. 开启 http 服务,上报健康状态供 liveness and readiness 查询 /bin/calico-node -felix-live

  2. 解析 IP Pool 资源,集群启动时创建了 IPPool 资源

kubectl get IPPool -oyaml
apiVersion: v1
items:
- apiVersion: crd.projectcalico.org/v1kind: IPPoolmetadata:name: default-ipv4-ippool...spec:allowedUses:- Workload- TunnelblockSize: 26cidr: 10.244.0.0/16ipipMode: Always                          // ipipMode, 且 ippool 10.244.0.0/16natOutgoing: truenodeSelector: all()vxlanMode: Never
kind: List
metadata:resourceVersion: ""selfLink: ""
  1. 如果配置了 calico-typha,则启动相应 client,在节点数比较多的情况下,Felix 可通过 Typha 直接和 ETCD 进行数据交互

  2. Dataplane

    dpDriver, dpDriverCmd = dp.StartDataplaneDriver(configParams.Copy(), // Copy to avoid concurrent access.healthAggregator,configChangedRestartCallback,fatalErrorCallback,k8sClientSet)
  • 通过 kube-ipvs0 判断是否是 ipvs,如果 BPF 开启的话,ipvs 改为 false。
  • 如果 BPF 开启的话,确认 BPF 程序 mark bits 在允许范围内 IptablesMarkMask:0xffff0000
  • 获取到可用 mark 范围 iptables mark bits acceptMark=0x10000 endpointMark=0xfff00000 endpointMarkNonCali=0x100000 passMark=0x20000 scratch0Mark=0x40000 scratch1Mark=0x80000
    即:ACCEPT 标记 0x10000,endpoint 标记为 0xfff00000 等
  • 循环保证 IPtables 的配置
        intDP := intdataplane.NewIntDataplaneDriver(dpConfig)intDP.Start()

具体配置分析可见 https://blog.csdn.net/zhonglinzhang/article/details/97630093

confd

主要任务:监控 Calico 数据存储以了解 BGP 配置和全局默认值(例如 AS 编号、日志记录级别和 IPAM 信息)的更改。开源、轻量级的配置管理工具。

Confd 根据数据存储中数据的更新动态生成 BIRD 配置文件。当配置文件发生变化时,confd 会触发 BIRD 加载新文件。

监控文件目录,该文件目录下,其中 template 提供 配置 bird 的模板,conf.d 生成配置文件的 toml,config 是生成实际的 配置

conf.d        config        templates

然后进程 bird -R -s /var/run/calico/bird.ctl -d -c /etc/calico/confd/config/bird.cfg 去更新 bird。

allocate-tunnel-addrs

  • 保证隧道 ip 正确,ipip wireguard 或 vxlan;
func reconcileTunnelAddrs
  • 通过 calicoclient 获取 ippool 和 node 信息
    blockSize: 26           // 每个网段的 ip 数量cidr: 10.244.0.0/16    // ippoolipipMode: Always       // ipip 模式natOutgoing: truenodeSelector: all()    // 所有节点都用该 ippool
  • 通过 cidr + blockSize,切分 ippool,并为该节点分配一个 ip 段,并请求一个 ip 作为隧道 ip
  • 将获取的 ip 地址更新到 node 上
spec:addresses:- address: 192.168.100.111/24type: CalicoNodeIP- address: 172.18.22.111type: InternalIPbgp:ipv4Address: 192.168.100.111/24ipv4IPIPTunnelAddr: 10.244.153.192          // 拿到的是 10.244.153.192/26 网段orchRefs:- nodeName: node111orchestrator: k8s
status:podCIDRs:- 10.244.0.0/24
  • 一直跑 syncer 监听 node 变化和 ippool 变化。

monitor-addresses

一直检查业务网卡的 ip 是否变化,检查默认频率 1min,如果变化,就对应更新 node 信息

  addresses:- address: 192.168.100.111/24type: CalicoNodeIP- address: 172.18.22.111type: InternalIPbgp:ipv4Address: 192.168.100.111/24ipv4IPIPTunnelAddr: 10.244.153.192

monitor-token

间隔随机时间刷新 sa token

tokenRequest, err := t.clientset.CoreV1().ServiceAccounts(t.namespace).CreateToken(context.TODO(), t.serviceAccountName, tr, metav1.CreateOptions{})

status-reporter

循环上报状态

bird

BIRD:BGP协议客户端,负责将Felix生成的路由信息载入内核并通告到整个网络中

BGP路由反射器:Calico的BGP路由模型默认采用节点网格模式(node-to-node mesh),随着节点数量的增加,节点之间的连接数量会快速增长,给集群网络带来较大的压力。因此,一般建议大规模集群使用BGP路由反射器模式进行路由学习,BGP的点到点通信也就转换为与中心节点的单路通信模型。另外,处于冗余考虑,生产环境应该配置多个BGP路由反射器。对于Calico来说,BGP客户端程序除了作为客户端使用,也可以配置为路由反射器。

calico-kube-controllers

负责把k8s的各种变化更新到calico网络中

  • 初始化 controller ,分别创建 podController,namespaceController,policyController,nodeController,serviceAccountController 和对应的 informer。
controllerCtrl.InitControllers(ctx, runCfg, k8sClientset, calicoClient)podController := pod.NewPodController(ctx, k8sClientset, calicoClient, *cfg.Controllers.WorkloadEndpoint, podInformer)namespaceController := namespace.NewNamespaceController(ctx, k8sClientset, calicoClient, *cfg.Controllers.Namespace)policyController := networkpolicy.NewPolicyController(ctx, k8sClientset, calicoClient, *cfg.Controllers.Policy)nodeController := node.NewNodeController(ctx, k8sClientset, calicoClient, *cfg.Controllers.Node, nodeInformer, podInformer)serviceAccountController := serviceaccount.NewServiceAccountController(ctx, k8sClientset, calicoClient, *cfg.Controllers.ServiceAccount)
  • 初始化监控
  • 启动,启动后 watch 上面资源的变化
    • Pod 资源变化时,将 pod 转为 workloadendpoint 存储
    • 监听 namespace,创建对应的 profile
    • nodeController 也监听 pod 变化
    • 监听 serviceAccount,创建对应的 profile
    • 监听 networkpolicy,转为 calico NetworkPolicy 存储

相关文章:

CNI 网络流量分析(六)Calico 介绍与原理(一)

文章目录CNI 网络流量分析(六)Calico 介绍与原理(一)介绍安装Calico-node初始化Calico-node 服务Felixconfdallocate-tunnel-addrsmonitor-addressesmonitor-tokenstatus-reporterbirdcalico-kube-controllersCNI 网络流量分析&am…...

机器视觉_HALCON_示例实践_1.检测圆形

文章目录一、引言二、检测圆形三、总结一、引言 前面的文(用户指南/快速向导)差不多已经把HALCON的基本内容讲完了,并且在学习过程中还跑过一个简单示例——在单一背景下定位回形针。示例跑过,顿时觉得自己行了,但如果…...

使用yolov5训练数据集笔记

准备工作 1. 安装labelimg labelimg:主要用于目标检测的目标框绘制,得到关于我们训练的边框位置、类别等数据 pip install labelimg2. 下载yolov5源码 我使用的是v7.0版本,直接下载即可,下载后解压出来 2.1 安装yolov5运行依赖包 进入…...

常用类详解(三)StringBuilder

(1)一个可爱的字符序列。此类提供一个与StringBuffer兼容的API,但不保证同步(StringBuilder不是线程安全的),该类被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候。如果可能,建议优先采用该类&#x…...

OpenCV 文字绘制----cv::putText详解

opencv中除了提供绘制各种图形的函数外,还提供了一个特殊的绘制函数——在图像上绘制文字。这个函数cv::putText()。 具体形式如下: void cv::putText( cv::Mat& img, // 待绘制的图像 const string& text, // 待绘制的文字 cv::Point origin…...

同IP多个端口域名同时进行目录爆破

背景 目录爆破是信息收集不可缺的一部分 在渗透过程中,扫描地址时发现同IP下存在多个端口,且每个端口均属于域名,仅仅端口号不同 需求 同一个IP下,同时收集多个不同端口的域名目录爆破进行信息收集,且简单便捷(一行代码) 用到的工具 gobuster 下载地址:https://…...

react+antd+Table里切换Switch改变状态onChange 传参

场景&#xff1a;table列表里面&#xff0c;操作用Switch切换状态。对应列改变操作在colums里面// 表格行const colums: ColumnsType<potentialType> [{title: useLocale(创建时间),dataIndex: creation_date,key: creation_date,align: center,render: (v: string, rec…...

《底层逻辑:看清这个世界的底牌》读后感

书名《底层逻辑&#xff1a;看清这个世界的底牌》作者刘润简介如果只教给你各行各业的“干货”&#xff08;方法论&#xff09;&#xff0c;那只是“授人以鱼”&#xff0c;一旦环境出现任何变化&#xff0c;“干货”就不再适用。但如果教给你的是底层逻辑&#xff0c;那就是“…...

【2023】Prometheus-Blackbox_exporter使用

目录1.下载及安装blackbox_exporter2.修改配置文件设置监控内容2.1.使用http方式作为探测3.与prometheus集成4.导入blackbox仪表盘进行观测1.下载及安装blackbox_exporter 下载安装包 wget https://github.com/prometheus/blackbox_exporter/releases/download/v0.23.0/black…...

嵌入式Linux学习经典书籍-学完你就是高手

很多刚入门的朋友一直都有人问我要学习资料&#xff0c;嵌入式实在太杂&#xff0c;网上很多人写的太不负责了&#xff0c;本书单综合了本人以及一些朋友多年的经验整理而成。 本人见识和阅读量有限&#xff0c;本书单可能有不对的地方&#xff0c;欢迎朋友指正&#xff0c;交…...

网络基础-基础网络命令

文章目录路由命令查询添加路由1.添加访问某台主机的静态路由2.添加访问某个网络的静态路由3.添加默认网关&#xff1a;删除设计关键字路由2参考路由 命令查询 通过 route --help 或man route 查询 添加路由 1.添加访问某台主机的静态路由 route add -host [目标主机IP地址…...

域对象共享数据

处理请求的过程&#xff1a;获取请求参数&#xff0c;调用service处理业务逻辑&#xff0c;往域对象中共享数据&#xff0c;最后实现渲染页面跳转。请求域中共享数据ModelAndView向request域对象共享数据ModelAndView&#xff1a;往域对象共享数据&#xff0c;并实现页面跳转和…...

【基于jeeSite框架】SpringBoot+poi+Layui自定义列表导出

文章目录功能效果思路代码前台后台easyPoi,easyExcel&#xff0c;poi三者的区别poipoi依赖导出ExcelHSSF方式导出XSSF方式导出SXSSF方式导出导入excelHSSF方式导入XSSF方式导入SXSSF方式导入easyPoi依赖包采用注解导出导入easyExcel依赖采用注解导出导入API文档easyPoi操作文档…...

使用 RGB 值设置颜色

使用 RGB 值设置颜色 另一种可以在 CSS 中表示颜色的方法是使用 RGB 值。 RGB 即红色、绿色、蓝色&#xff08;英语&#xff1a;Red, Green, Blue&#xff09;。 ● 红色&#xff08;R&#xff09;0 到 255 间的整数&#xff0c;代表颜色中的红色成分。。 ● 绿色&#xff08;G…...

【python学习笔记】:5个高效编程技巧

01 交换变量​​​​​​​ >>>a3 >>>b6 这个情况如果要交换变量在c中&#xff0c;肯定需要一个空变量。但是python不需要&#xff0c;只需一行&#xff0c;大家看清楚了​​​​​​​ >>>a,bb,a >>>print(a)>>>6 >>&g…...

IP多播技术详解

文章目录前言IP多播技术的相关基本概念IP多播地址和多播组在局域网上进行硬件多播IP多播地址和多播MAC地址映射关系在因特网上进行IP多播网际组管理协议IGMP多播路由选择协议前言 随着计算机网络的发展和个人计算机的普及&#xff0c;人们能够方便的在网络上畅游&#xff0c;进…...

华为OD机试真题Python实现【数组排序】真题+解题思路+代码(20222023)

🔥系列专栏 华为OD机试(Python)真题目录汇总华为OD机试(JAVA)真题目录汇总华为OD机试(C++)真题目录汇总华为OD机试(JavaScript)真题目录汇总文章目录 🔥系列专栏题目输入输出示例一输入输出解题思路核心知识点Python 代码实现代码运行结果版权说明</...

丹麦市政当局通过 NetIQ 身份和访问管理解决方案,提高安全合规性

丹麦市政当局通过 NetIQ 身份和访问管理解决方案&#xff0c;提高安全合规性 概览 公司&#xff1a;普华永道 行业&#xff1a;咨询 地点&#xff1a;丹麦 挑战 创建一个通用框架&#xff0c;以便丹麦市政当局可以无需内部专业知识的前提下利用高级身份和访问管理 使用的…...

内网渗透学习官方文档

内网渗透0x00 kerberos协议0x01 ntlm协议0x02 管道0x03 smb协议0x04 windows访问控制0x05 令牌窃取0x06 SPN扫描&kerberoast0x07 黄金票据0x08 白银票据0x09 MS140680x10 NTDS.DIT && sam0x11 NTLM Relay0x12 MS08-0680x13 CVE-2019-13840x00 kerberos协议 kerber…...

如何编写接口测试用例?

接口测试用例如何编写&#xff1f;下面简单给大家讲解一下。 接口测试用例是目前软件开发中不可或缺的一个重要部分&#xff0c;因此编写接口测试用例同样重要。 接口测试用例的作用非常明显&#xff0c;它能够帮助我们了解产品正在考验、调整它如何表现在特定情境之下、产品是…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

Webpack性能优化:构建速度与体积优化策略

一、构建速度优化 1、​​升级Webpack和Node.js​​ ​​优化效果​​&#xff1a;Webpack 4比Webpack 3构建时间降低60%-98%。​​原因​​&#xff1a; V8引擎优化&#xff08;for of替代forEach、Map/Set替代Object&#xff09;。默认使用更快的md4哈希算法。AST直接从Loa…...