12、Kubernetes中KubeProxy实现之iptables和ipvs

news2024/11/30 8:43:17

目录

一、概述

二、iptables 代理模式

三、iptables案例分析

四、ipvs案例分析

一、概述

iptables和ipvs其实都是依赖的一个共同的Linux内核模块:Netfilter。Netfilter是Linux 2.4.x引入的一个子系统,它作为一个通用的、抽象的框架,提供一整套的hook函数的管理机制,使得诸如数据包过滤、网络地址转换(NAT)和基于协议类型的连接跟踪成为了可能。

Netfilter的架构就是在整个网络流程的若干位置放置了一些检测点(HOOK),而在每个检测点上登记了一些处理函数进行处理。

在一个网络包进入Linux网卡后,有可能经过这上面五个Hook点,我们可以自己写Hook函数,注册到任意一个点上,而iptables和ipvs都是在这个基础上实现的。

二、iptables 代理模式

iptables模式下 kube-proxy 为每一个pod创建相对应的 iptables 规则,发送给 ClusterIP 的请求会被直接发送给后端pod之上。

在该模式下 kube-proxy 不承担负载均衡器的角色,其只会负责创建相应的转发策略,该模式的优点在于效率较高,但是不能提供灵活的LB策略,当后端Pod不可用的时候无法进行重试。

iptables是把一些特定规则以“链”的形式挂载到每个Hook点,这些链的规则是固定的,而是是比较通用的,可以通过iptables命令在用户层动态的增删,这些链必须串行的执行。执行到某条规则,如果不匹配,则继续执行下一条,如果匹配,根据规则,可能继续向下执行,也可能跳到某条规则上,也可能下面的规则都跳过。

三、iptables案例分析

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx

---

apiVersion: v1
kind: Service
metadata:
  name: nginx-basic
spec:
  type: ClusterIP
  ports:
    - port: 80
      protocol: TCP
      name: http
  selector:
    app: nginx                           

我们这里创建一个副本数量为3的nginx pod,并创建一个对应的service对外暴露服务,service类型为ClusterIP。

创建完成后,资源如下:

$ kubectl get pod -o wide
NAME                                READY   STATUS    RESTARTS   AGE   IP            NODE           NOMINATED NODE   READINESS GATES
nginx-deployment-748c667d99-dtr82   1/1     Running   0          38m   192.168.1.3   node01         <none>           <none>
nginx-deployment-748c667d99-jzpqf   1/1     Running   0          38m   192.168.0.7   controlplane   <none>           <none>
nginx-deployment-748c667d99-whgr5   1/1     Running   0          38m   192.168.1.4   node01         <none>           <none>


$ kubectl get svc nginx-basic -o wide
NAME          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE   SELECTOR
nginx-basic   ClusterIP   10.105.250.129   <none>        80/TCP    39m   app=nginx

可以看到,三个pod的IP分别为192.168.1.3、192.168.0.7、192.168.1.4。service的ClusterIP地址为10.105.250.129。

下面我们通过【iptables-save -t nat】命令输出iptables中nat表的信息,说明iptables如何实现转发。

$ iptables-save -t nat
# Generated by iptables-save v1.8.4 on Mon Feb 20 01:52:41 2023
*nat
:PREROUTING ACCEPT [11:660]
:INPUT ACCEPT [11:660]
:OUTPUT ACCEPT [4706:282406]
:POSTROUTING ACCEPT [4706:282406]
:DOCKER - [0:0]
:KUBE-KUBELET-CANARY - [0:0]
:KUBE-MARK-DROP - [0:0]
:KUBE-MARK-MASQ - [0:0]
:KUBE-NODEPORTS - [0:0]
:KUBE-POSTROUTING - [0:0]
:KUBE-PROXY-CANARY - [0:0]
:KUBE-SEP-ABG426TTTCGMOND7 - [0:0]
:KUBE-SEP-BEMSLTMJA26ZCLYL - [0:0]
:KUBE-SEP-D23ODROEH5R4FSGE - [0:0]
:KUBE-SEP-G44RJ25JKAEOKO42 - [0:0]
:KUBE-SEP-GHNVWKROTCCBFQKZ - [0:0]
:KUBE-SEP-NGZXZA7GIJDM26Z3 - [0:0]
:KUBE-SEP-NH2YM7NDCNPLOCTP - [0:0]
:KUBE-SEP-UF65ZV4QBOPNRP6O - [0:0]
:KUBE-SEP-UG4OSZR4VSWZ27C5 - [0:0]
:KUBE-SEP-WQR67ZLSTPDXXME4 - [0:0]
:KUBE-SERVICES - [0:0]
:KUBE-SVC-ERIFXISQEP7F7OF4 - [0:0]
:KUBE-SVC-JD5MR3NA4I4DYORP - [0:0]
:KUBE-SVC-NPX46M4PTMTKRN6Y - [0:0]
:KUBE-SVC-TCOU7JCQXEZGVUNU - [0:0]
:KUBE-SVC-WWRFY3PZ7W3FGMQW - [0:0]
:cali-OUTPUT - [0:0]
:cali-POSTROUTING - [0:0]
:cali-PREROUTING - [0:0]
:cali-fip-dnat - [0:0]
:cali-fip-snat - [0:0]
:cali-nat-outgoing - [0:0]
-A PREROUTING -m comment --comment "cali:6gwbT8clXdHdC1b1" -j cali-PREROUTING
-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT -m comment --comment "cali:tVnHkvAo15HuiPy0" -j cali-OUTPUT
-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
-A POSTROUTING -m comment --comment "cali:O3lYWMrLQYEMJtB5" -j cali-POSTROUTING
-A POSTROUTING -m comment --comment "kubernetes postrouting rules" -j KUBE-POSTROUTING
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 192.168.0.0/16 -d 192.168.0.0/16 -j RETURN
-A POSTROUTING -s 192.168.0.0/16 ! -d 224.0.0.0/4 -j MASQUERADE --random-fully
-A POSTROUTING ! -s 192.168.0.0/16 -d 192.168.0.0/24 -j RETURN
-A POSTROUTING ! -s 192.168.0.0/16 -d 192.168.0.0/16 -j MASQUERADE --random-fully
-A DOCKER -i docker0 -j RETURN
-A KUBE-MARK-DROP -j MARK --set-xmark 0x8000/0x8000
-A KUBE-MARK-MASQ -j MARK --set-xmark 0x4000/0x4000
-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
-A KUBE-POSTROUTING -j MARK --set-xmark 0x4000/0x0
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully
-A KUBE-SEP-ABG426TTTCGMOND7 -s 192.168.1.2/32 -m comment --comment "kube-system/kube-dns:dns-tcp" -j KUBE-MARK-MASQ
-A KUBE-SEP-ABG426TTTCGMOND7 -p tcp -m comment --comment "kube-system/kube-dns:dns-tcp" -m tcp -j DNAT --to-destination 192.168.1.2:53
-A KUBE-SEP-BEMSLTMJA26ZCLYL -s 192.168.0.7/32 -m comment --comment "default/nginx-basic:http" -j KUBE-MARK-MASQ
-A KUBE-SEP-BEMSLTMJA26ZCLYL -p tcp -m comment --comment "default/nginx-basic:http" -m tcp -j DNAT --to-destination 192.168.0.7:80
-A KUBE-SEP-D23ODROEH5R4FSGE -s 172.30.1.2/32 -m comment --comment "default/kubernetes:https" -j KUBE-MARK-MASQ
-A KUBE-SEP-D23ODROEH5R4FSGE -p tcp -m comment --comment "default/kubernetes:https" -m tcp -j DNAT --to-destination 172.30.1.2:6443
-A KUBE-SEP-G44RJ25JKAEOKO42 -s 192.168.0.6/32 -m comment --comment "kube-system/kube-dns:dns-tcp" -j KUBE-MARK-MASQ
-A KUBE-SEP-G44RJ25JKAEOKO42 -p tcp -m comment --comment "kube-system/kube-dns:dns-tcp" -m tcp -j DNAT --to-destination 192.168.0.6:53
-A KUBE-SEP-GHNVWKROTCCBFQKZ -s 192.168.1.2/32 -m comment --comment "kube-system/kube-dns:dns" -j KUBE-MARK-MASQ
-A KUBE-SEP-GHNVWKROTCCBFQKZ -p udp -m comment --comment "kube-system/kube-dns:dns" -m udp -j DNAT --to-destination 192.168.1.2:53
-A KUBE-SEP-NGZXZA7GIJDM26Z3 -s 192.168.0.6/32 -m comment --comment "kube-system/kube-dns:dns" -j KUBE-MARK-MASQ
-A KUBE-SEP-NGZXZA7GIJDM26Z3 -p udp -m comment --comment "kube-system/kube-dns:dns" -m udp -j DNAT --to-destination 192.168.0.6:53
-A KUBE-SEP-NH2YM7NDCNPLOCTP -s 192.168.0.6/32 -m comment --comment "kube-system/kube-dns:metrics" -j KUBE-MARK-MASQ
-A KUBE-SEP-NH2YM7NDCNPLOCTP -p tcp -m comment --comment "kube-system/kube-dns:metrics" -m tcp -j DNAT --to-destination 192.168.0.6:9153
-A KUBE-SEP-UF65ZV4QBOPNRP6O -s 192.168.1.3/32 -m comment --comment "default/nginx-basic:http" -j KUBE-MARK-MASQ
-A KUBE-SEP-UF65ZV4QBOPNRP6O -p tcp -m comment --comment "default/nginx-basic:http" -m tcp -j DNAT --to-destination 192.168.1.3:80
-A KUBE-SEP-UG4OSZR4VSWZ27C5 -s 192.168.1.2/32 -m comment --comment "kube-system/kube-dns:metrics" -j KUBE-MARK-MASQ
-A KUBE-SEP-UG4OSZR4VSWZ27C5 -p tcp -m comment --comment "kube-system/kube-dns:metrics" -m tcp -j DNAT --to-destination 192.168.1.2:9153
-A KUBE-SEP-WQR67ZLSTPDXXME4 -s 192.168.1.4/32 -m comment --comment "default/nginx-basic:http" -j KUBE-MARK-MASQ
-A KUBE-SEP-WQR67ZLSTPDXXME4 -p tcp -m comment --comment "default/nginx-basic:http" -m tcp -j DNAT --to-destination 192.168.1.4:80
-A KUBE-SERVICES -d 10.96.0.10/32 -p tcp -m comment --comment "kube-system/kube-dns:dns-tcp cluster IP" -m tcp --dport 53 -j KUBE-SVC-ERIFXISQEP7F7OF4
-A KUBE-SERVICES -d 10.96.0.10/32 -p tcp -m comment --comment "kube-system/kube-dns:metrics cluster IP" -m tcp --dport 9153 -j KUBE-SVC-JD5MR3NA4I4DYORP
-A KUBE-SERVICES -d 10.96.0.10/32 -p udp -m comment --comment "kube-system/kube-dns:dns cluster IP" -m udp --dport 53 -j KUBE-SVC-TCOU7JCQXEZGVUNU
-A KUBE-SERVICES -d 10.105.250.129/32 -p tcp -m comment --comment "default/nginx-basic:http cluster IP" -m tcp --dport 80 -j KUBE-SVC-WWRFY3PZ7W3FGMQW
-A KUBE-SERVICES -d 10.96.0.1/32 -p tcp -m comment --comment "default/kubernetes:https cluster IP" -m tcp --dport 443 -j KUBE-SVC-NPX46M4PTMTKRN6Y
-A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL -j KUBE-NODEPORTS
-A KUBE-SVC-ERIFXISQEP7F7OF4 ! -s 192.168.0.0/16 -d 10.96.0.10/32 -p tcp -m comment --comment "kube-system/kube-dns:dns-tcp cluster IP" -m tcp --dport 53 -j KUBE-MARK-MASQ
-A KUBE-SVC-ERIFXISQEP7F7OF4 -m comment --comment "kube-system/kube-dns:dns-tcp -> 192.168.0.6:53" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-G44RJ25JKAEOKO42
-A KUBE-SVC-ERIFXISQEP7F7OF4 -m comment --comment "kube-system/kube-dns:dns-tcp -> 192.168.1.2:53" -j KUBE-SEP-ABG426TTTCGMOND7
-A KUBE-SVC-JD5MR3NA4I4DYORP ! -s 192.168.0.0/16 -d 10.96.0.10/32 -p tcp -m comment --comment "kube-system/kube-dns:metrics cluster IP" -m tcp --dport 9153 -j KUBE-MARK-MASQ
-A KUBE-SVC-JD5MR3NA4I4DYORP -m comment --comment "kube-system/kube-dns:metrics -> 192.168.0.6:9153" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-NH2YM7NDCNPLOCTP
-A KUBE-SVC-JD5MR3NA4I4DYORP -m comment --comment "kube-system/kube-dns:metrics -> 192.168.1.2:9153" -j KUBE-SEP-UG4OSZR4VSWZ27C5
-A KUBE-SVC-NPX46M4PTMTKRN6Y ! -s 192.168.0.0/16 -d 10.96.0.1/32 -p tcp -m comment --comment "default/kubernetes:https cluster IP" -m tcp --dport 443 -j KUBE-MARK-MASQ
-A KUBE-SVC-NPX46M4PTMTKRN6Y -m comment --comment "default/kubernetes:https -> 172.30.1.2:6443" -j KUBE-SEP-D23ODROEH5R4FSGE
-A KUBE-SVC-TCOU7JCQXEZGVUNU ! -s 192.168.0.0/16 -d 10.96.0.10/32 -p udp -m comment --comment "kube-system/kube-dns:dns cluster IP" -m udp --dport 53 -j KUBE-MARK-MASQ
-A KUBE-SVC-TCOU7JCQXEZGVUNU -m comment --comment "kube-system/kube-dns:dns -> 192.168.0.6:53" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-NGZXZA7GIJDM26Z3
-A KUBE-SVC-TCOU7JCQXEZGVUNU -m comment --comment "kube-system/kube-dns:dns -> 192.168.1.2:53" -j KUBE-SEP-GHNVWKROTCCBFQKZ
-A KUBE-SVC-WWRFY3PZ7W3FGMQW ! -s 192.168.0.0/16 -d 10.105.250.129/32 -p tcp -m comment --comment "default/nginx-basic:http cluster IP" -m tcp --dport 80 -j KUBE-MARK-MASQ
-A KUBE-SVC-WWRFY3PZ7W3FGMQW -m comment --comment "default/nginx-basic:http -> 192.168.0.7:80" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-BEMSLTMJA26ZCLYL
-A KUBE-SVC-WWRFY3PZ7W3FGMQW -m comment --comment "default/nginx-basic:http -> 192.168.1.3:80" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-UF65ZV4QBOPNRP6O
-A KUBE-SVC-WWRFY3PZ7W3FGMQW -m comment --comment "default/nginx-basic:http -> 192.168.1.4:80" -j KUBE-SEP-WQR67ZLSTPDXXME4
-A cali-OUTPUT -m comment --comment "cali:GBTAv2p5CwevEyJm" -j cali-fip-dnat
-A cali-POSTROUTING -m comment --comment "cali:Z-c7XtVd2Bq7s_hA" -j cali-fip-snat
-A cali-POSTROUTING -m comment --comment "cali:nYKhEzDlr11Jccal" -j cali-nat-outgoing
-A cali-PREROUTING -m comment --comment "cali:r6XmIziWUJsdOK6Z" -j cali-fip-dnat
-A cali-nat-outgoing -m comment --comment "cali:flqWnvo8yq4ULQLa" -m set --match-set cali40masq-ipam-pools src -m set ! --match-set cali40all-ipam-pools dst -j MASQUERADE --random-fully
COMMIT

iptables-save命令,可以查看当前所有的iptables规则,涉及到k8s的比较多,基本在每个链上都有,包括一些SNAT的,就是Pod访问外部的地址的时候,需要做一下NAT转换,我们只看涉及到Service负载均衡的。

首先,PREROUTING和OUTPUT都加了一个KUBE-SERVICES规则,也就是进来的包和出去的包都要都走一下KUBE-SERVICES规则。

-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES

-A OUTPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES

接着,因为我们service的ClusterIP地址为10.105.250.129,所以我们从nat表中找出跟10.105.250.129有关的转发规则。

-A KUBE-SERVICES -d 10.105.250.129/32 -p tcp -m comment --comment "default/nginx-basic:http cluster IP" -m tcp --dport 80 -j KUBE-SVC-WWRFY3PZ7W3FGMQW

 可以看到,当目标地址是10.105.250.129/32并且目标端口是80的,也就是这个服务的ClusterIP,走到KUBE-SVC-WWRFY3PZ7W3FGMQW规则,这个规则其实就是Kube-Proxy。

下面我们查看KUBE-SVC-WWRFY3PZ7W3FGMQW规则:

-A KUBE-SVC-WWRFY3PZ7W3FGMQW -m comment --comment "default/nginx-basic:http -> 192.168.0.7:80" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-BEMSLTMJA26ZCLYL
-A KUBE-SVC-WWRFY3PZ7W3FGMQW -m comment --comment "default/nginx-basic:http -> 192.168.1.3:80" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-UF65ZV4QBOPNRP6O
-A KUBE-SVC-WWRFY3PZ7W3FGMQW -m comment --comment "default/nginx-basic:http -> 192.168.1.4:80" -j KUBE-SEP-WQR67ZLSTPDXXME4

可以看到,KUBE-SVC-WWRFY3PZ7W3FGMQW又对应了三条规则,分别来看下:

1)、第一条规则

-A KUBE-SVC-WWRFY3PZ7W3FGMQW -m comment --comment "default/nginx-basic:http -> 192.168.0.7:80" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-BEMSLTMJA26ZCLYL

# 这条规则对应的又会走KUBE-SEP-BEMSLTMJA26ZCLYL规则
-A KUBE-SEP-BEMSLTMJA26ZCLYL -p tcp -m comment --comment "default/nginx-basic:http" -m tcp -j DNAT --to-destination 192.168.0.7:80

# 可以看到, 有33%的概率将会被转发到【192.168.0.7:80】这个pod

2)、第二条规则

-A KUBE-SVC-WWRFY3PZ7W3FGMQW -m comment --comment "default/nginx-basic:http -> 192.168.1.3:80" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-UF65ZV4QBOPNRP6O

# 这条规则对应的又会走KUBE-SEP-UF65ZV4QBOPNRP6O规则
-A KUBE-SEP-UF65ZV4QBOPNRP6O -p tcp -m comment --comment "default/nginx-basic:http" -m tcp -j DNAT --to-destination 192.168.1.3:80

# 可以看到, 有50%的概率将会被转发到【192.168.1.3:80】这个pod

3)、第三条规则

-A KUBE-SVC-WWRFY3PZ7W3FGMQW -m comment --comment "default/nginx-basic:http -> 192.168.1.4:80" -j KUBE-SEP-WQR67ZLSTPDXXME4

# 这条规则对应的又会走KUBE-SEP-WQR67ZLSTPDXXME4规则
-A KUBE-SEP-WQR67ZLSTPDXXME4 -p tcp -m comment --comment "default/nginx-basic:http" -m tcp -j DNAT --to-destination 192.168.1.4:80

# 可以看到,这条规则没有加--probability,所以有100%的概率将会被转发到【192.168.1.4:80】这个pod

可以看到,最重要的就是KUBE-SVC-WWRFY3PZ7W3FGMQW规则,它以不同的概率走到了不同的规则,这些规则最终走到了Pod里,这就是负载均衡策略。

我们把这个负载均衡用图画出来,大体就是如下:

上述我们演示的是ClusterIP类型的Service,我们可以尝试修改为NodePort类型,实际上,在iptables规则里,最终也是会转发到KUBE-SVC-WWRFY3PZ7W3FGMQW规则,综上,不管是ClusterIP,还是NodePort,都走到了同一个规则上。

四、ipvs案例分析

IPVS模式工作在内核态,在同步代理规则时具有更好的性能,同时提高网络吞吐量为大型集群提供了更好的可扩展性,同时提供了大量的负责均衡算法。

还是通过一个例子说明ipvs怎么转发的,首先我们需要修改kube-proxy的代理模式为ipvs,我们可以通过修改configmap来实现:

$ kubectl edit configmap kube-proxy -n kube-system
configmap/kube-proxy edited

将mode修改为ipvs即可,如下图:

image.png

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx

---

apiVersion: v1
kind: Service
metadata:
  name: nginx-basic
spec:
  type: ClusterIP
  ports:
    - port: 80
      protocol: TCP
      name: http
  selector:
    app: nginx                           

创建对应的pod和service:

$ vim ipvs.yaml
controlplane $ kubectl create -f ipvs.yaml
deployment.apps/nginx-deployment created
service/nginx-basic created

$ kubectl get pods -o wide
NAME                                READY   STATUS    RESTARTS   AGE   IP            NODE           NOMINATED NODE   READINESS GATES
nginx-deployment-748c667d99-fpsh6   1/1     Running   0          12s   192.168.1.3   node01         <none>           <none>
nginx-deployment-748c667d99-hsnzw   1/1     Running   0          12s   192.168.0.7   controlplane   <none>           <none>
nginx-deployment-748c667d99-sb9b2   1/1     Running   0          12s   192.168.1.4   node01         <none>           <none>

$ kubectl get svc -o wide
NAME          TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE   SELECTOR
nginx-basic   ClusterIP   10.96.115.68   <none>        80/TCP    36s   app=nginx

我们通过【ipvsadm -L】命令查看ipvs转发规则:

$  ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
...省略...    
TCP  10.96.115.68:80 rr
  -> 192.168.0.7:80               Masq    1      0          0         
  -> 192.168.1.3:80               Masq    1      0          0         
  -> 192.168.1.4:80               Masq    1      0          0         
...省略...

可以看到,到ClusterIP:Port的流量,都被以rr(round robin)的策略转发到3个后端pod上。

五、iptables vs ipvs

●1、iptables更通用,主要是应用在防火墙上,也能应用于路由转发等功能,ipvs更聚焦,它只能做负载均衡,不能实现其它的例如防火墙上。
●2、iptables在处理规则时,是按“链”逐条匹配,如果规则过多,性能会变差,它匹配规则的复杂度是O(n),而ipvs处理规则时,在专门的模块内处理,查找规则的复杂度是O(1)。
●3、iptables虽然可以实现负载均衡,但是它的策略比较简单,只能以概率转发,而ipvs可以实现多种策略。

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

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

相关文章

华为智能高校出口安全解决方案(3)

本文承接&#xff1a; https://qiuhualin.blog.csdn.net/article/details/133267254?spm1001.2014.3001.5502 重点讲解华为智能高校出口安全解决方案的攻击防御&安全运维&日志审计的部署流程。 华为智能高校出口安全解决方案&#xff08;3&#xff09; 课程地址攻击防…

git报错:Failed to connect to 127.0.0.1 port 1080

Bug描述 由于在试了网上的这条命令 git config --global http.proxy socks5 127.0.0.1:1080 git config --global https.proxy socks5 127.0.0.1:1080git config --global http.proxy 127.0.0.1:1080 git config --global https.proxy 127.0.0.1:1080Bug描述&#xff1a;Faile…

对负采样(negative sampling)的一些理解

负采样&#xff08;negative sampling&#xff09;通常用于解决在训练神经网络模型时计算softmax的分母过大、难以计算的问题。但在LightGCN模型论文的BPR LOSS中&#xff0c;负采样的概念可能与传统的softmax分母问题不完全一样。 在LightGCN模型中&#xff0c;不同于传统的协…

Spring结合自定义注解实现 AOP 切面功能【详解】

Spring结合自定义注解实现 AOP 切面功能 Spring AOP 注解概述Aspect 快速入门execution 切点表达式 拦截指定类的方法Pointcut("annotation(xx)") 拦截拥有指定注解的方法常用注解1.Before&#xff1a;在切点方法前执行2.After&#xff1a;在切点方法后执行3.Around&…

Python爬虫获取百度图片+重命名+帧差法获取关键帧

&#xff08;清库存&#xff09; 获取图片 重命名 帧差法 爬虫获取图片文件重命名帧差法获取关键帧 爬虫获取图片 # 图片在当前目录下生成import requests import renum 0 numPicture 0 file List []def dowmloadPicture(html, keyword):global num# t 0pic_url re.fin…

【JVM】运行时数据区之 堆——自问自答

Q:堆和栈&#xff0c;在设计上有何用义&#xff1f; 此处我们不说数据结构的概念。 堆本身是一种存储结构&#xff0c;在代码的内存层面来看&#xff0c;无论是c 操作的原生内存&#xff0c;还是Java 背后的JVM&#xff0c;堆的作用都是进行持久存储的。 这个持久存储并不是…

集合-Collection

系列文章目录 1.集合-Collection-CSDN博客 文章目录 目录 系列文章目录 文章目录 前言 一 . 集合的继承体系 二 . 什么是Collection? 三 . 常用方法 1.add(Object element): 将指定的元素添加到集合中。 2. remove(Object element): 从集合中移除指定的元素。 3. bo…

国庆day1---消息队列实现进程之间通信方式代码,现象

snd&#xff1a; #include <myhead.h>#define ERR_MSG(msg) do{\fprintf(stderr,"__%d__:",__LINE__);\perror(msg);\ }while(0)typedef struct{ long msgtype; //消息类型char data[1024]; //消息正文 }Msg;#define SIZE sizeof(Msg)-sizeof(long)int main…

HP E1740A 模拟量输入模块

HP&#xff08;惠普&#xff09;E1740A 模拟量输入模块是一种用于数据采集和测量的工控模块&#xff0c;通常用于各种自动化和监测应用中。以下是该模拟量输入模块的一些可能特点和功能&#xff1a; 多通道输入&#xff1a; E1740A 模块通常具有多个模拟量输入通道&#xff0c;…

windows的arp响应

1.原理‘ 2.场景 3.步骤

YOLOv8+swin_transfomerv2

测试环境&#xff1a;cuda11.3 pytorch1.11 rtx3090 wsl2 ubuntu20.04 踩了很多坑&#xff0c;网上很多博主的代码根本跑不通&#xff0c;自己去github仓库复现修改的 网上博主的代码日常出现cpu,gpu混合&#xff0c;或许是人家分布式训练了&#xff0c;哈哈哈 下面上干货…

Android回收视图

本文所有代码均存放于https://github.com/MADMAX110/BitsandPizzas 回收视图是列表视图的一个更高级也更灵活的版本。 回收视图比列表视图更加灵活&#xff0c;所以需要更多设置&#xff0c;回收视图使用一个适配器访问它的数据&#xff0c;不过与列表视图不同&#xff0c;回收…

[RCTF2015]EasySQL 二次注入 regexp指定字段 reverse逆序输出

第一眼没看出来 我以为是伪造管理员 就先去测试管理员账号 去register.php 注册 首先先注册一个自己的账号 我喜欢用admin123 发现里面存在修改密码的内容 那么肯定链接到数据库了 题目又提示是sql 那我们看看能不能修改管理员密码 首先我们猜测闭合 通过用户名 admin…

HTML,CSS,JavaScript知识点

HTML&#xff0c;CSS&#xff0c;JavaScript知识点 HTML篇 HTML是超文本标记语言。文件以.html结尾。 Hello,HTML。常用的工具: 标题: <h1>一级标题</h1><h2>二级标题</h2><h3>三级标题</h3><h4>四级标题</h4>无序列表和有…

YOLOv8+swin_transfomer

测试环境&#xff1a;cuda11.3 pytorch1.11 rtx3090 wsl2 ubuntu20.04 本科在读&#xff0c;中九以上老师或者课题组捞捞我&#xff0c;孩子想读书&#xff0c;求课题组师兄内推qaq 踩了很多坑&#xff0c;网上很多博主的代码根本跑不通&#xff0c;自己去github仓库复现修…

PHP免登录积分商城系统/动力商城/积分商城兑换系统源码Tinkphp

介绍&#xff1a; PHP免登录积分商城系统/动力商城/积分商城兑换系统源码Tinkphp&#xff0c;这个免登录积分商城系统是一种新型的电子商务模式&#xff0c;它通过省去麻烦的注册步骤&#xff0c;让用户能够很快又方便去积分兑换。这种商城系统具有UI干净整洁大方、运行顺畅的…

正点原子嵌入式linux驱动开发——STM32MP1启动详解

STM32单片机是直接将程序下载到内部 Flash中&#xff0c;上电以后直接运行内部 Flash中的程序。 STM32MP157内部没有供用户使用的 Flash&#xff0c;系统都是存放在外部 Flash里面的&#xff0c;比如 EMMC、NAND等&#xff0c;因此 STM32MP157上电以后需要从外部 Flash加载程序…

Mendix中的依赖管理:npm和Maven的应用

序言 在传统java开发项目中&#xff0c;我们可以利用maven来管理jar包依赖&#xff0c;但在mendix项目开发Custom Java Action时&#xff0c;由于目录结构有一些差异&#xff0c;我们需要自行配置。同样的&#xff0c;在mendix项目开发Custom JavaScript Action时&#xff0c;…

调度算法2-适用于交互式系统

一、时间片轮转调度算法(RR) 1.算法思想 Round-Robin 公平、轮流地为各个进程服务&#xff0c;让每个进程在一定时间间隔内都可得到响应 2.算法规则 按照各进程到达就绪队列的顺序&#xff0c;轮流让各个进程执行一个时间片 响应比(等待时间要求服务时间)/要求服务时间 3…

http请求报错:406 Not Acceptable的解决办法

目录 应用场景 基本概念 解决方法 方法一&#xff1a; 方法二&#xff1a; 方法三&#xff1a; 应用场景 接口在返回结果集的时候出现了406的报错&#xff0c;但是返回String类型不会报错&#xff0c;正常返回。 基本概念 406 Not Acceptable是一个HTTP响应状态码&…