kube-proxy的iptables工作模式分析

系列文章目录

iptables基础知识


文章目录

  • 系列文章目录
  • 前言
  • 一、kube-proxy介绍
    • 1、kube-proxy三种工作模式
    • 2、iptables中k8s相关的链
  • 二、kube-proxy的iptables模式剖析
    • 1.集群内部通过clusterIP访问到pod的流程
      • 1.1.流程分析
    • 2.从外部访问内部service clusterIP后端pod的流程
      • 2.1. 流程分析
    • 3、外部通过nodeport访问后端pod的流程
      • 3.1.当externalTrafficPolicy默认为cluster配置时且从本机访问后端pod流程
      • 3.2.当externalTrafficPolicy为Local配置时且从本机访问后端pod流程
  • 三、iptables与ipvs区别


前言

在一个k8s集群中,微服务以 Pod形式 运行在我们的集群中,这些 Pod 的副本通过Service 服务暴露,当一个外部请求到达 Service 的虚拟 IP 时,如何将请求转发到其中一个底层 Pod?这便是本篇文章的核心思想。


一、kube-proxy介绍

在这里插入图片描述

kube-proxy是k8s网络代理核心组件,部署在每个Node节点上,主要维护节点上的网络规则。它是实现service的通信与负载均衡机制的重要组件
kube-proxy负责为pod创建代理服务,通过watch机制会根据 service 和 endpoints,node资源对象的改变来实时刷新iptables或者ipvs规则
使发往 Service 的流量(通过ClusterIP和NodePort)负载均衡到正确的后端Pod。

1、kube-proxy三种工作模式

userspace(目前已经弃用)请求是从用户态-->内核态-->用户态,转发是在用户态进行的,效率不高且容易丢包
iptables(默认工作模式)相比于userspace免去了一次内核态-->用户态的切换1、kube-proxy通过Api-server的watch接口实时监测service和endpoint对象的变化,当有service创建时,kube-proxy在iptables中追加新的规则2、在该模式下,kube-proxy为service后端的每个pod创建对应的iptables规则,直接将发向cluster ip的请求重定向到一个pod ip3、在该模式下,kube-proxy不承担四层代理的角色,只负责创建iptables规则补充:在iptables模式下,会根据service以及endpoints对象的改变来实时刷新规则,kube-proxy使用了iptables的filter表和nat表,并对 iptables 的链进行了扩充,自定义了 KUBE-SERVICES、KUBE-EXTERNAL-SERVICES、KUBE-NODEPORTS、KUBE-POSTROUTING、KUBE-MARK-MASQ、KUBE-MARK-DROP、KUBE-FORWARD 七条链。另外还新增了以“KUBE-SVC-xxx”和“KUBE-SEP-xxx”开头的数个链,除了创建自定义的链以外还将自定义链插入到已有链的后面以便劫持数据包。
ipvs1、kube-proxy ipvs模式是基于NAT实现的,对访问k8s service的请求进行虚拟ip到pod ip的转发工作原理:当创建一个svc后,ipvs模式的kube-proxy会做以下三件事:1、确保kube-ipvs0网卡的存在。因为ipvs的netfilter钩子挂载input链.需要把svc的访问IP绑定在该网卡上让内核觉得虚IP就是本机IP,从而进入input链。2、把svc的访问ip绑定在该网卡上3、通过socket调用,创建ipvs的虚拟服务和真实服务,分别对应svc和endpoints注意事项:ipvs用于流量转发,无法处理kube-proxy中的其他问题,例如把包过滤、SNAT等。因此在以下四种情况下kube-proxy依赖iptables:1、kube-proxy配置启动参数masquerade-all=true,即集群中所有经过kube-proxy的包都做一次SNAT;2、kube-proxy启动参数指定集群IP地址范围;3、支持loadbalance类型的服务4、支持nodeport类型的服务

2、iptables中k8s相关的链

名称含义
KUBE-SERVICES是服务数据包的入口点。它的作用是匹配 目标 IP:port 并将数据包分派到对应的 KUBE-SVC-* 链
KUBE-SVC-*充当负载均衡器,将数据包分发到 KUBE-SEP-* 链。KUBE-SEP-* 的数量等于后面的端点数量 服务。选择哪个 KUBE-SEP-* 是随机决定的
KUBE-SEP-*表示 Service EndPoint。它只是执行 DNAT,将 服务 IP:端口,以及 Pod 的端点 IP:端口
KUBE-MARK-MASQ将 Netfilter 标记添加到发往该服务的数据包中,该标记 源自集群网络之外。带有此标记的数据包将被更改 在 POSTROUTING 规则中使用源网络地址转换 (SNAT) 和 node 的 IP 地址作为其源 IP 地址
KUBE-MARK-DROP为没有目的地的数据包添加 Netfilter 标记 此时已启用 NAT。这些数据包将在 KUBE-FIREWALL 中被丢弃 链
KUBE-FW-*chain 在 service 部署时执行 LoadBalancer 类型,则 将目标 IP 与服务的负载均衡器 IP 匹配,并分配 数据包到对应的 KUBE-SVC-* 链或 KUBE-XLB-* 链的 KEY-XLB-* 链
KUBE-NODEPORTS发生在服务部署在 NodePort 和 LoadBalancer 的 LoadPort 共享 LoadPort 和 LoadBalancer 的有了它,外部源可以访问该服务 按 Node Port 的 NODE 端口。它匹配节点端口并分发 数据包到对应的 KUBE-SVC-* 链或 KUBE-XLB-* 链 的 KEY-XLB-* 链 的
KUBE-XLB-*在 externalTrafficPolicy 设置为 Local 时工作。有了这个 链式编程,如果节点没有相关端点,则数据包将被丢弃 保留

二、kube-proxy的iptables模式剖析

首先请查看顶部文章链接iptables基本知识,对出入栈、四表五链有个认知,然后再看下文
包含整改service模式的流程图
iptable工作流程图
只包含cluster IP、NodePort模式的流程图
在这里插入图片描述
流程图结合iptables示例图
在这里插入图片描述

结合上述流程图,主要分两部分对kube-proxy的iptables模式进行剖析

1.集群内部通过clusterIP访问到pod的流程

资源准备,如下图所示
在这里插入图片描述
需求: 当在集群pod1访问curl http://10.102.172.63:8088时,请求是怎么到达后端pod2的?

1.1.流程分析

确定kube-proxy的工作模式两种方式

[root@master ~]# curl http://127.0.0.1:10249/proxyMode
iptables[root@master ~]# kubectl get configmaps -n kube-system kube-proxy -oyaml |grep modemode: "" #默认为空就是iptables模式

a、进入到pod1,执行curl请求

[root@master ~]# kubectl exec -it -n xx xx-xx-6c57d9ddc6-2495v bash
bash-4.2$ curl http://10.102.172.63:8088

xshell多开一个窗口,登录到pod1宿主机,查看iptables规则
b、因为从上述iptables流程图可知,当请求从集群内部发出时,先进入的是NAT表中的OUTPUT链---->到达KUBE-SERVICE自定义链

那么在pod1宿主机中查看output链规则如下所示
[root@xmhl-std12 ~]# iptables -t nat -S |grep -i output
-P OUTPUT ACCEPT
-A OUTPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES   #此链就是入口链
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER

c、因为是clusterIP模式,因此在KUBE-SERVICES链查找到ClusterIP-10.102.172.63,然后根据结果将其转发到KUBE-SVC-*链

判断是否发生IP伪装(masquerade all)
从下面可以看到当数据包来自内部 Pod 时,即源 IP 仍然是pod ip。因此未发生转换,则直接到kube-svc-*链
bash-4.2$ curl -s 10.102.172.63:8088 | grep client
bash-4.2$ client_address=10.244.193.194#查看kube-svc-*链是否存在  
[root@master ~]# iptables -nv -t nat -L KUBE-SERVICES |grep 'zz-trace'0     0 KUBE-SVC-LWBZJHXSVINAPFYY  tcp  --  *      *       0.0.0.0/0            10.102.172.63        /* xos/zz-trace-analyze:web cluster IP */ tcp dpt:8088

d、访问 KUBE-SVC*链 使用随机数负载均衡,将请求转发到kube-sep-*链中

#注意事项假如这个KUBE-SVC-LWBZJHXSVINAPFYY链里面定义了3条规则第一条规则有0.33333333349的概率匹配,也就是1/3的概率命中,第一条没命中的话第二条规则有1/2的概率命中,也就是2/3 * 1/2 = 1/3,第二条没命中的话就去第3条了。很明显,这里是在做负载均衡,那我们可以确认这3条规则后面的target就是这个service代理的3个pod相关的规则了[root@master ~]# iptables -nv -t nat -L KUBE-SVC-LWBZJHXSVINAPFYY
Chain KUBE-SVC-LWBZJHXSVINAPFYY (1 references)pkts bytes target     prot opt in     out     source               destination         0     0 KUBE-SEP-SU7QRQC2MJZZVHTR  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* xos/zz-trace-analyze:web */

e、每个 KUBE-SEP-* 链分别代表一个 Pod 或终端节点

重点
它包括两个操作:1) 从 Pod 转义的数据包是使用主机的 docker0 IP 进行源 NAT 处理的。 2) 进入 Pod 的数据包使用 Pod 的 IP 进行 DNAT 处理,然后路由到后端 Pod

查询如下所示: 从结果可以清晰的看到 pod1请求pod2的svc后,进入到pod2的数据包使用 Pod 的 IP 进行了 DNAT 处理,直接到达了pod2的目标pod

[root@master ~]# iptables -nv -t nat -L KUBE-SEP-SU7QRQC2MJZZVHTR
Chain KUBE-SEP-SU7QRQC2MJZZVHTR (1 references)pkts bytes target     prot opt in     out     source               destination         0     0 KUBE-MARK-MASQ  all  --  *      *       10.244.8.182         0.0.0.0/0            /* xos/zz-trace-analyze:web */0     0 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            /* xityos/zz-trace-analyze:web */ tcp to:10.244.8.182:18080

f、之后nat表的OUTPUT链中的规则结束,进入filter的OUTPUT链

[root@master ~]# iptables -t filter -S |grep OUTPUT
-P OUTPUT ACCEPT
-A OUTPUT -m conntrack --ctstate NEW -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A OUTPUT -j KUBE-FIREWALL  #即nat表的OUTPUT链完成后进入到filter表中的OUTPUT链

g、可以看到所有新建的连接(ctstate NEW)都会匹配第一条规则KUBE-SERVICES,而当查看filter表中的KUBE-SERVICES链时,会发现这是一条空链。所以重点看第二条规则KUBE-FIREWALL

[root@master ~]# iptables -nv -t filter -L KUBE-FIREWALL
Chain KUBE-FIREWALL (2 references)pkts bytes target     prot opt in     out     source               destination         0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* kubernetes firewall for dropping marked packets */ mark match 0x8000/0x80000     0 DROP       all  --  *      *      !127.0.0.0/8          127.0.0.0/8          /* block incoming localnet connections */ ! ctstate RELATED,ESTABLISHED,DNAT可以看到,所有被标记了0x8000/0x8000的数据包都会被直接DROP掉,而我们的数据包一路走过来没有被标记,所以不会被DROP。
这样一来filter的OUTPUT规则也走完了,终于进入了下一个阶段 -- POSTROUTRING链

h、POSTROUTING链涉及到2个表:mangle和nat,mangle表一般不使用,所以只需要关注nat表的POSTROUTING规则

[root@master ~]# iptables -nv -t nat -L |grep POSTROUTING
Chain POSTROUTING (policy ACCEPT 26679 packets, 2287K bytes)11M  982M KUBE-POSTROUTING  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* kubernetes postrouting rules */
Chain KUBE-POSTROUTING (1 references)

i、先进入target,KUBE-POSTROUTING

[root@master ~]# iptables -nv -t nat -L KUBE-POSTROUTING
Chain KUBE-POSTROUTING (1 references)pkts bytes target     prot opt in     out     source               destination         
27635 2364K RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0            mark match ! 0x4000/0x400047  2820 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            MARK xor 0x400047  2820 MASQUERADE  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* kubernetes service traffic requiring SNAT */此时会发现这条规则会把所有标记了0x4000/0x4000的数据包全部MASQUERADE SNAT,由于我们的数据包没有被标记过,所以不匹配这条规则。
当数据包匹配到MASQUERADE的话,当前表的剩余规则将不再匹配。

至此,集群内部通过clusterIP访问到pod的链路流程剖析完成,整理一下整个过程

数据包经历的链路:数据包 --> nat的OUTPUT--> nat的KUBE-SERVICES --> nat的KUBE-SVC-LWBZJHXSVINAPFYY--> nat的KUBE-SEP-SU7QRQC2MJZZVHTR(多选1,随机负载均衡,被DNAT)--> filter的OUTPUT --> filter的KUBE-SERVICES -->filter的KUBE-FIREWALL --> nat的POSTROUTING --> nat的KUBE-POSTROUTING --> 没有被NAT
语言描述:0、当集群内部通过clusterIP访问到pod时,会发生以下过程1、对于进入 NAT表的OUTPUT 链的都转到 KUBE-SERVICES 链进行处理2、在 KUBE-SERVICES 链,对于访问 clusterIP 为 10.102.172.63 的转发到 KUBE-SVC-LWBZJHXSVINAPFYY3、访问 KUBE-SVC-LWBZJHXSVINAPFYY 的使用随机数负载均衡,并转发到 KUBE-SEP-SU7QRQC2MJZZVHTR上4、KUBE-SEP-SU7QRQC2MJZZVHTR对应 endpoint 中的 pod 10.244.8.182,设置 mark 标记,进行 DNAT 并转发到具体的 pod 上5、当nat表中的output链完成后,会进入filter表中OUTPUT链中的KUBE-FIREWALL自定义链,可以看到,所有被标记了0x8000/0x8000的数据包都会被直接DROP掉,反之则不会被drop6、最后进入到NAT表中的POSTROUTING链,此时会发现这条规则会把所有标记了0x4000/0x4000的数据包全部MASQUERADE SNAT,由于我们的数据包没有被标记过,所以不匹配这条规则。当数据包匹配到MASQUERADE的话,当前表的剩余规则将不再匹配7、至此,剖析结束

2.从外部访问内部service clusterIP后端pod的流程

2.1. 流程分析

需求: 从外部机器中访问http://10.102.172.63:8088 这个clusterip svc的后端pod
a、因为从上述iptables流程图可知,当请求从外部发出时,先进入的是NAT表中的PREROUTING链---->到达KUBE-SERVICE自定义链

[root@master ~]# iptables -t nat -S |grep PREROUTING
-P PREROUTING ACCEPT
-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER

b、因为是clusterIP模式,因此在KUBE-SERVICES链查找到ClusterIP-10.102.172.63,然后根据结果将其转发到KUBE-SVC-*链

判断是否发生IP伪装(masquerade all)
从下面我们可以看到,当从外部(而不是从 pod)访问服务时,源 IP 替换为 nodeIP;
cactus@master01:~$ curl --interface 外部地址  -s 10.102.172.63:8088 | grep client
client_address=10.244.1.0 
[root@master ~]# conntrack -L -d 10.102.172.63
tcp      6 56 TIME_WAIT src=10.8.21.231 dst=10.102.172.63 sport=56688 dport=8088 src=10.244.8.182 dst=10.244.1.0 sport=18080 dport=50534 [ASSURED] mark=0 use=1#查看kube-svc-*链是否存在
[root@xmhl-std24 ~]# iptables -nvL  -t nat |egrep -i 'kube-mark-masq'  |grep zz-trace0     0 KUBE-MARK-MASQ  all  --  *      *       10.244.8.182         0.0.0.0/0            /* cityos/zz-trace-analyze:web */[root@master ~]# iptables -nv -t nat -L KUBE-SERVICES |grep 'zz-trace'0     0 KUBE-SVC-LWBZJHXSVINAPFYY  tcp  --  *      *       0.0.0.0/0            10.102.172.63        /* xos/zz-trace-analyze:web cluster IP */ tcp dpt:8088

接下来的分析步骤和集群内部通过clusterIP访问到pod的流程中c-i过程一致,在此不做过多描述
至此,集群内部通过clusterIP访问到pod的链路流程剖析完成,整理一下整个过程

数据包经历的链路:数据包 --> nat的PREROUTING--> nat的KUBE-SERVICES --> nat的KUBE-SVC-LWBZJHXSVINAPFYY--> nat的KUBE-SEP-SU7QRQC2MJZZVHTR(多选1,随机负载均衡,被DNAT)--> filter的OUTPUT --> filter的KUBE-SERVICES -->filter的KUBE-FIREWALL --> nat的POSTROUTING --> nat的KUBE-POSTROUTING --> 没有被NAT
语言描述:0、当集群内部通过clusterIP访问到pod时,会发生以下过程1、对于进入 NAT表的PREROUTING 链的都转到 KUBE-SERVICES 链进行处理2、在 KUBE-SERVICES 链,对于访问 clusterIP 为 10.102.172.63 的转发到 KUBE-SVC-LWBZJHXSVINAPFYY3、访问 KUBE-SVC-LWBZJHXSVINAPFYY 的使用随机数负载均衡,并转发到 KUBE-SEP-SU7QRQC2MJZZVHTR上4、KUBE-SEP-SU7QRQC2MJZZVHTR对应 endpoint 中的 pod 10.244.8.182,设置 mark 标记,进行 DNAT 并转发到具体的 pod 上5、当nat表中的output链完成后,会进入filter表中OUTPUT链中的KUBE-FIREWALL自定义链,可以看到,所有被标记了0x8000/0x8000的数据包都会被直接DROP掉,反之则不会被drop6、最后进入到NAT表中的POSTROUTING链,此时会发现这条规则会把所有标记了0x4000/0x4000的数据包全部MASQUERADE SNAT,由于我们的数据包没有被标记过,所以不匹配这条规则。当数据包匹配到MASQUERADE的话,当前表的剩余规则将不再匹配7、至此,剖析结束

3、外部通过nodeport访问后端pod的流程

将根据上述图1分析两种类型的 NodePort 服务:1、默认服务 (externalTrafficPolicy: Cluster)2、externalTrafficPolicy:local

在这里插入图片描述

3.1.当externalTrafficPolicy默认为cluster配置时且从本机访问后端pod流程

a、从本机访问首先进入NAT表的OUTPUT链,然后进入到kube-nodeports链
所有访问端口 64438的数据包,首先要进行 SNAT 处理,然后才能进行kube-svc-*链进行负载均衡

[root@master ~]# iptables -t nat -S |grep OUTPUT
-P OUTPUT ACCEPT
-A OUTPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER[root@master ~]# iptables -nv -t nat -L KUBE-NODEPORTS |grep 'xx-flow'0     0 KUBE-MARK-MASQ  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            /* xos/xx-flow:debug-port */ tcp dpt:644380     0 KUBE-SVC-UFDICDG36KRBVVWD  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            /* xos/xx-flow:debug-port */ tcp dpt:64438

b、可以看到数据包先会命中第一条规则KUBE-MARK-MASQ,然后是第二条规则到达

[root@master ~]# iptables -t nat -L KUBE-MARK-MASQ
Chain KUBE-MARK-MASQ (165 references)
target     prot opt source               destination         
MARK       all  --  anywhere             anywhere             MARK or 0x4000在这里数据包会被标记上0x4000标记,然后回到KUBE-NODEPORTS链中继续匹配下一条规则,下一条规则就是KUBE-SVC-UFDICDG36KRBVVWD[root@master ~]# iptables -t nat -L KUBE-SVC-BCUGWLTE6RKBKCZT
Chain KUBE-SVC-BCUGWLTE6RKBKCZT (2 references)
target     prot opt source               destination         
KUBE-SEP-2SQRA2EPJ5ESOFTW  all  --  anywhere             anywhere             /* xos/xx-flow:web */ statistic mode random probability 0.50000000000
KUBE-SEP-QUKANZ2W6FTD6P23  all  --  anywhere             anywhere             /* xos/xx-flow:web */

c、接下来一路到nat的POSTROUTING为止都与ClusterIP模式相同,但在接下来的nat的KUBE-POSTROUTING阶段,由于我们的数据包在KUBE-MARK-MASQ被打上了0x4000标记,在这里会命中这条规则,从而被MASQUERADE(SNAT)

[root@xmhl-std11 ~]# iptables -nv -t nat -L KUBE-POSTROUTING
Chain KUBE-POSTROUTING (1 references)pkts bytes target     prot opt in     out     source               destination         
41065 3455K RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0            mark match ! 0x4000/0x400022  1320 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            MARK xor 0x400022  1320 MASQUERADE  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* kubernetes service traffic requiring SNAT */

至此,当externalTrafficPolicy默认为cluster配置时且从本机访问后端pod流程剖析完成

数据包经历的链路:
数据包 --> nat的OUTPUT --> nat的KUBE-SERVICES --> nat的KUBE-NODEPORTS --> nat的KUBE-MARK-MASQ (被标记) --> nat的KUBE-SVC-GKN7Y2BSGW4NJTYL--> nat的KUBE-SEP-ISPQE3VESBAFO225(3选1,被DNAT)--> filter的OUTPUT --> filter的KUBE-SERVICES -->filter的KUBE-FIREWALL --> nat的POSTROUTING --> nat的KUBE-POSTROUTING --> 被SNAT

3.2.当externalTrafficPolicy为Local配置时且从本机访问后端pod流程

三、iptables与ipvs区别

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/63201.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为网络设备配置文件备份与恢复(上传、下载、导出,导入)

在日常运维工作中&#xff0c;会经常存在网络割接的情况&#xff0c;为了保证网络割接失败时能重新回退至原有配置&#xff0c;从而不影响原有的办公环境&#xff0c;在网络割接前的备份工作就非常有必要了。 备份方式&#xff1a;FTP 备份技术&#xff1a;PC客户端<---&g…

清风数学建模学习笔记——Topsis法

数模评价类&#xff08;2&#xff09;——Topsis法 概述 Topsis:Technique for Order Preference by Similarity to Ideal Solution 也称优劣解距离法&#xff0c;该方法的基本思想是&#xff0c;通过计算每个备选方案与理想解和负理想解之间的距离&#xff0c;从而评估每个…

[软件工程]九.可依赖系统(Dependable Systems)

9.1什么是系统的可靠性&#xff08;reliability&#xff09; 系统的可靠性反映了用户对系统的信任程度。它反映了用户对其能够按照预期运行且正常使用中不会失效的信心程度。 9.2什么是可依赖性&#xff08;dependablity&#xff09;的目的 其目的是覆盖系统的可用性&#x…

减少30%人工处理时间,AI OCR与表格识别助力医疗化验单快速处理

在医疗行业&#xff0c;化验单作为重要的诊断依据和数据来源&#xff0c;涉及大量的文字和表格信息&#xff0c;传统的手工输入和数据处理方式不仅繁琐&#xff0c;而且容易出错&#xff0c;给医院的运营效率和数据准确性带来较大挑战。随着人工智能技术的快速发展&#xff0c;…

汽车一键启动开关 、一键启动按键 、一键启动按钮

‌汽车一键启动按钮是智能汽车的重要部分&#xff0c;通常用于启动和关闭引擎‌。 ‌具体功能‌&#xff1a; ‌启动引擎‌&#xff1a;在许多现代汽车中&#xff0c;一键启动按键取代了传统的钥匙启动方式。只需轻轻按下一键启动按钮&#xff0c;车辆电源即被接通&#xff0c…

.NET用C#导入Excel数据到数据库

将Excel文件中的数据导入到数据库中不仅能够提升数据处理的效率和准确性&#xff0c;还能极大地促进数据分析和决策制定的过程。尤其在企业级应用中&#xff0c;Excel作为数据输入和初步整理的工具非常普遍&#xff0c;但其功能对于复杂查询、大规模数据管理和跨部门的数据共享…

python中数组怎么转换为字符串

1、数组转字符串 #方法1 arr [a,b] str1 .join(arr)#方法2 arr [1,2,3] #str .join(str(i) for i in arr)#此处str命名与str函数冲突&#xff01; str2 .join(str(i) for i in arr) 2、字符串转数组 #方法一 str_x avfg st_list list(str_x) #使用list()#方法二 list_s…

国内管理咨询公司哪家落地辅导做的好?

在当今快速变化的市场环境中&#xff0c;企业面临着前所未有的竞争压力与转型挑战。为了在这场没有硝烟的战争中脱颖而出&#xff0c;许多企业开始寻求外部专业力量的帮助&#xff0c;以期通过科学的管理咨询实现战略升级和业绩突破。而在众多的管理咨询公司中&#xff0c;思博…

Cursor vs VSCode:主要区别与优势分析

Cursor - The AI Code Editor 1. AI 集成能力 Cursor的优势 原生AI集成&#xff1a; # Cursor可以直接通过快捷键调用AI # 例如&#xff1a;按下 Ctrl K 可以直接获取代码建议 def complex_function():# 在这里&#xff0c;你可以直接询问AI如何实现功能# AI会直接在编辑器中…

python+selenium的八大定位方式

1.id定位 元素的id属 driver.find_element_by_id(By.ID,"username")2.name定位 driver.find_element_by_id(By.NAME,"username")#一个login_btn_list webdriver.find_elements(By.CLASS_NAME,)#多个元素组成的列表&#xff0c; login_btn_list[1].click…

RTCMultiConnection 跨域问题解决

js套件地址 https://github.com/muaz-khan/RTCMultiConnection server套件地址 https://github.com/muaz-khan/RTCMultiConnection-Server 要解决的就是server代码的跨域问题 原装写法&#xff1a; 解决写法&#xff1a; // 喜欢组合语法的自己组 const io new ioServer.S…

【JavaEE】多线程(6)

一、用户态与内核态 【概念】 用户态是指用户程序运行时的状态&#xff0c;在这种状态下&#xff0c;CPU只能执行用户态下的指令&#xff0c;并且只能访问受限的内存空间 内核态是操作系统内核运行时的状态&#xff0c;内核是计算机系统的核心部分&#xff0c;CPU可以执行所有…

Ajax:回忆与节点

一点回忆 面对我的Ajax学习&#xff0c;实现前后端交互&#xff0c;最开始我采用的使用网络寻找intellij IDEA Ultimate破解方法&#xff0c;然后最终成功&#xff0c;然后按照相关教程配置java ee项目&#xff0c;然后中间又去配置了Tomcat服务器&#xff0c;然后又去学习了一…

1688:开启跨境电商新篇章

引言 在全球化贸易不断深化的今天&#xff0c;跨境电商已成为中小企业拓展国际市场的重要渠道。1688&#xff0c;作为阿里巴巴集团旗下领先的内贸平台&#xff0c;近年来也逐渐发力跨境电商领域&#xff0c;为全球买家提供了一个直通中国工厂的贸易平台。本文将带您深入了解16…

2024-12-06 Unity Addressables3——资源加载

文章目录 1 引用加载1.1 Addressables 的资源引用类1.2 加载资源1.3 加载场景1.4 释放资源 2 Label 介绍3 动态加载3.1 加载单个资源3.2 加载多个资源 Unity 版本&#xff1a;6000.0.26f1c1Addressables 版本&#xff1a;2.3.1 1 引用加载 1.1 Addressables 的资源引用类 Ass…

相机动态/在线标定

图1 图2 基本原理 【原理1】平行线在射影变换后会交于一点。如图所示,A为相机光心,蓝色矩形框为归一化平面,O为平面中心。地面四条黄色直线为平行且等距的车道线。HI交其中两条车道线于H、I, 过G作HI的平行线GM交车道线于M。HI、GM在归一化平面上的投影分别为JK、PN,二者会…

工作:SolidWorks从3D文件导出2D的DWG或DXF类型文件方法

工作&#xff1a;SolidWorks从3D文件导出2D的DWG或DXF类型文件方法 SolidWorks从3D文件导出2D的DWG或2D DXF类型文件方法&#xff08;一&#xff09;打开3D文件&#xff08;二&#xff09;从装配体到工程图&#xff08;三&#xff09;拖出想要的角度的图型&#xff08;四&#…

【AI系统】低比特量化原理

低比特量化原理 计算机里面数值有很多种表示方式&#xff0c;如浮点表示的 FP32、FP16&#xff0c;整数表示的 INT32、INT16、INT8&#xff0c;量化一般是将 FP32、FP16 降低为 INT8 甚至 INT4 等低比特表示。 模型量化则是一种将浮点值映射到低比特离散值的技术&#xff0c;可…

【ETCD】【源码阅读】ETCD启动流程源码解读

启动流程的图如下&#xff1a; 1、主函数入口 ETCD 启动的入口在 etcd/server/main.go 文件中。 package mainimport ("os""go.etcd.io/etcd/server/v3/etcdmain" )func main() {etcdmain.Main(os.Args) }这里调用了 etcdmain.Main()&#xff0c;这是 …

计算机网络-应用层/运输层

应用层 在上一篇已经提到过, 计算机网络, 最核心的功能就是个产生信息, 发送信息.而并不关注其中的接受方究竟是人, 机器. 而协议, 就是双方约定的 可以表达一定含义的 消息内容. 符合协议的, 就能够被机器解读, 并进行下一步操作, 可能还会返回一定的响应内容. 而应用层, 有…