文章目录

  • BGP 介绍
    • BGP 分类
    • BGP 报文
    • Calico BGP
  • 部署
  • 流量分析
    • Pod 间
    • Node 到 Pod
    • Pod 到 service

BGP 介绍

不同于 RIP 、OSPF 协议都是基于 AS 即自治系统内的协议,BGP 是域间路由协议,或者叫做外部网关协议;
BGP 协议只是满足选择一条到达目的网络比较好的路由,而非选择一条最佳路由,BGP 采用了路径向量路由选择协议,它与 RIP 和 OSPF 有很大的差别;路径向量路由,BGP 中数据包送达目标网络时,会生成中途经过所有 AS 的编号列表,即 AS 路径信息访问列表;如果针对一个目标地址有多条路径,BGP 选择较短的路由。

BGP 支持 CIDR,因此 BGP 的路由表也就应当包括当前目的网络前缀、下一跳路由器,以及到达目的网络所经过的 AS;

在 BGP 刚刚运行时,BGP 的临站是交换整个 BGP 路由表,以后只要在发生变化时更新有新变化的部分即可。这样对节省网络带宽和减少路由器开销有很大好处,这个特性和 OSPF 非常相似。
BGP - 4 主要有下面几类报文类型:

  • OPEN ( 打开 )报文,用来和相邻的 BGP 区域边界路由器建立关系,进行通信初始化。
  • UPDATE ( 更新 ) 报文,用来通告路由信息,以及列出需要更新的多条路由。
  • KEEPALIVE ( 保活 ) 报文,用来周期性的证实临站的连通性。
  • NOTIFICATION ( 通知 ) 报文,用来发送检测到的差错。

如果两个临站属于两个不同的自治系统,而且其中一个临站打算和其他临站进行路由交换的时候,这时候应当有一个路由商量的过程。商量的过程包括临站路由器是否还能够接受额外的路由信息。因此一开始进行商谈的时候应该要先发送 OPEN 报文,如果临站可以接受这种关系,就用 KEEPALIVE 报文响应。

关系建立之后,是需要相互维持的,两个 BGP 边界路由器需要定期交换 KEEPALIVE 报文,一般这个定期的时间就是 30 s。

BGP 边界路由器可以使用 UPDATE 报文来更新路由:包括撤掉以前通知过的路由和增加新的路由。撤销路由时一次可以撤销多条,但是新增路由一个 UPDATE 报文只能增加一条。

BGP 边界路由器不只有一个,而且当某个路由器或者链路出现故障时,由于 BGP 边界路由器可以不止从一个临站获得路由信息,因此很容易选出新的路由。

BGP 分类

BGP 分为 IBGP,EBGP
IBGP:如果 BGP 对等体处于同一自治系统内,被称为 IBGP 对等体,要求 TCP 可达。为了防止环路,BGP 协议规定 BGP 发言者从 IBGP 获得的路由不向它的 IBGP 对等体发布。
EBGP:BGP 对等体处于不同自治系统时,被称为 EBGP 对等体,一般物理直连。BGP Speaker 从 EBGP 对等体获得的路由会向它所有 BGP 对等体通告(包括 EBGP 和 IBGP);同时为了防止环路,他不会将学习到的路由再向原发布者发布。

BGP 报文


不同类型报文首部都为 19 字节

  • Marker 字段 16字节,用来鉴别收到的 BGP 报文,如果不使用鉴别,标记字段要置为全 1。
  • 长度 2 字节,长度字段指出包括通用首部在内的整个 BGP 报文的长度,以字节为单位,最小值是 19,最大值是 4096.
  • 类型字段的值为 1 到 4,分别对应上面报文的介绍顺序。

OPEN:除了前三个字段,接下来依次是 version (1 字节),My AS 本自治系统号( 2 字节),Hold Time 保持时间 ( 2 字节,以秒计算的保持为临站关系的时间 ),BGP Identifier BGP 标识符 ( 4 字节,路由器的 IP 地址 )
KEEPALIVE:只有 那 19 字节

UPDATE:报文中的 Unfeasible routes length 表示不可行路由长度,后面是 Withdrawn Routes ,要撤销的路由列表,后面的 Total Path Attribute Length 表示路径属性总长度,后面的 Path attributes 就表示路径属性,最后的 NLRI 标识发出这个报文的网络。

10.244.153.192/26 下一跳是 192.168.100.111

NOTIFICATION:主要包括差错代码 ( 1 字节 ),差错子代码 ( 1 字节 ) ,后面还有差错数据。

Calico BGP

一个集群内部 node 使用的 ippool 相同,as 号相同,集群内部使用的 IBGP,当有不同 ippool 的节点加到集群里就需要配置多个 as 号。

[root@node111 bgp]# calicoctl get node -o wide
NAME      ASN       IPV4                 IPV6
node111   (64512)   192.168.100.111/24
node112   (64512)   192.168.100.112/24
node113   (64512)   192.168.100.113/24

Calico 默认开启 nodeToNodeMesh,每两个主机之间都会建立连接

[root@node111 bgp]# calicoctl node status
Calico process is running.IPv4 BGP status
+-----------------+-------------------+-------+----------+-------------+
|  PEER ADDRESS   |     PEER TYPE     | STATE |  SINCE   |    INFO     |
+-----------------+-------------------+-------+----------+-------------+
| 192.168.100.112 | node-to-node mesh | up    | 09:43:09 | Established |
| 192.168.100.113 | node-to-node mesh | up    | 09:39:04 | Established |
+-----------------+-------------------+-------+----------+-------------+

鉴于集群规模变大后,链接太多,提出 BGP Route Reflectors,选择集群中几台机器作为 BGP Route Reflectors,其他 node 只与 BGP Route Reflectors 进行链接。
改成 BGP RR 模式
关掉 nodeToNodeMesh

apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:name: default
spec:logSeverityScreen: InfonodeToNodeMeshEnabled: falseasNumber: 64512

创建 bgppeer 配置

apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:name: node111
spec:nodeSelector: "all()"peerSelector: "has(route-reflector)"

给选定节点 node111 加 routeReflectorClusterID 和 label

配置 node111 routeReflectorClusterID
$ calicoctl get node node111 -o yaml > rr-node.yaml
bgp 加 routeReflectorClusterID: 244.0.0.1
$ calicoctl apply -f rr-node.yaml$ kubectl label node node111 route-reflector=true

在三个节点

# node111
IPv4 BGP status
+-----------------+---------------+-------+----------+-------------+
|  PEER ADDRESS   |   PEER TYPE   | STATE |  SINCE   |    INFO     |
+-----------------+---------------+-------+----------+-------------+
| 192.168.100.112 | node specific | up    | 10:39:33 | Established |
| 192.168.100.113 | node specific | up    | 10:39:33 | Established |
+-----------------+---------------+-------+----------+-------------+# node112
IPv4 BGP status
+-----------------+---------------+-------+----------+-------------+
|  PEER ADDRESS   |   PEER TYPE   | STATE |  SINCE   |    INFO     |
+-----------------+---------------+-------+----------+-------------+
| 192.168.100.111 | node specific | up    | 10:39:33 | Established |
+-----------------+---------------+-------+----------+-------------+# node113
IPv4 BGP status
+-----------------+---------------+-------+----------+-------------+
|  PEER ADDRESS   |   PEER TYPE   | STATE |  SINCE   |    INFO     |
+-----------------+---------------+-------+----------+-------------+
| 192.168.100.111 | node specific | up    | 10:39:33 | Established |
+-----------------+---------------+-------+----------+-------------+

查看 报文过程

  1. Node111 向 node113 通告本节点 cidr 的路由 10.244.153.192/26 到 192.168.100.111
  2. Node111 向 node112 通告本节点 cidr 的路由 10.244.153.192/26 到 192.168.100.111
  3. Node113 向 node111 通告本节点 cidr 的路由 10.244.84.192/26 到 192.168.100.113
  4. node112 向 node111 通告本节点 cidr 的路由 10.244.146.192/26 到 192.168.100.112
  5. node111 向 node113 通告到 10.244.146.192/26 到 192.168.100.112
  6. node111 向 node112 通告到 10.244.84.192/26 到 192.168.100.113
    5-6 步 node111 作为 RR 的实现,node112 和 node113 不直接 bgp

部署

如果环境是 ipip,修改成 bgp

需要修改

1. 修改 calico-node
# kubectl edit ds calico-node -n kube-system
- name: CALICO_IPV4POOL_IPIP
value: Always
- name: CALICO_AUTODETECTION_METHOD
value: interface=eth02. 修改 ippool,需要把 ipipMode 从 Always 修改成为 Never(执行下面命令修改 ipipMode)
# kubectl edit ippool
ipipMode: Never


可以看到,在宿主机上有到每个 pod IP 的路由指向 veth 设备
到对端节点网段的路由对端 业务网卡的 ip

流量分析

Pod 间

  • 同 node 不同 pod 之间
    pod1 <-> pod2
  1. 在 pod1 eth0 抓包:
22:49:09.291741 de:f9:e6:21:f3:22 > ee:ee:ee:ee:ee:ee, ethertype IPv4 (0x0800), length 98: 10.244.153.214 > 10.244.153.216: ICMP echo request, id 5409, seq 12, length 64
22:49:09.291804 ee:ee:ee:ee:ee:ee > de:f9:e6:21:f3:22, ethertype IPv4 (0x0800), length 98: 10.244.153.216 > 10.244.153.214: ICMP echo reply, id 5409, seq 12, length 64

pod1 中下一跳都是 169.254.1.1,且目的 mac 是 ee:ee:ee:ee:ee:ee
2. 在 host 端 calice0906292e2 抓包不变
3. 匹配主机路由 10.244.153.216 dev calibd2348b4f67 scope link 和 ip neighbor 10.244.153.216 dev calibd2348b4f67 lladdr 36:42:dd:fc:5a:a1 REACHABLE, 在 calibd2348b4f67 抓包

22:50:42.475843 ee:ee:ee:ee:ee:ee > 36:42:dd:fc:5a:a1, ethertype IPv4 (0x0800), length 98: 10.244.153.214 > 10.244.153.216: ICMP echo request, id 5409, seq 103, length 64
22:50:42.475869 36:42:dd:fc:5a:a1 > ee:ee:ee:ee:ee:ee, ethertype IPv4 (0x0800), length 98: 10.244.153.216 > 10.244.153.214: ICMP echo reply, id 5409, seq 103, length 64
  1. 在 pod2 内 eth0 抓包:
    22:50:42.475843 ee:ee:ee:ee:ee:ee > 36:42:dd:fc:5a:a1, ethertype IPv4 (0x0800), length 98: 10.244.153.214 > 10.244.153.216: ICMP echo request, id 5409, seq 103, length 64
    22:50:42.475869 36:42:dd:fc:5a:a1 > ee:ee:ee:ee:ee:ee, ethertype IPv4 (0x0800), length 98: 10.244.153.216 > 10.244.153.214: ICMP echo reply, id 5409, seq 103, length 64
  • 不同 node 上 pod 之间
    pod1 访问 pod3
    在 veth host 端抓包
22:51:50.782553 de:f9:e6:21:f3:22 > ee:ee:ee:ee:ee:ee, ethertype IPv4 (0x0800), length 98: 10.244.153.214 > 10.244.146.212: ICMP echo request, id 60131, seq 20, length 64
22:51:50.783496 ee:ee:ee:ee:ee:ee > de:f9:e6:21:f3:22, ethertype IPv4 (0x0800), length 98: 10.244.146.212 > 10.244.153.214: ICMP echo reply, id 60131, seq 20, length 64

看 主机路由 10.244.146.192/26 via 192.168.100.112 dev ens10 proto bird 下一跳是 192.168.100.112
在 ens10 上抓包,可以看到 mac 地址是业务网卡两个端点的 mac,报文没有任何变化。

22:53:04.149175 52:54:00:dc:c7:b4 > 52:54:00:d3:bf:21, ethertype IPv4 (0x0800), length 98: 10.244.153.214 > 10.244.146.212: ICMP echo request, id 60131, seq 93, length 64
22:53:04.149870 52:54:00:d3:bf:21 > 52:54:00:dc:c7:b4, ethertype IPv4 (0x0800), length 98: 10.244.146.212 > 10.244.153.214: ICMP echo reply, id 60131, seq 93, length 64

在 对面机器上的报文路径与之对称

Node 到 Pod

  • Node 到本 node 上的 pod
    在 node111 ping pod1
    在 veth host 端抓包,根据路由 10.244.153.216 dev calibd2348b4f67 scope link,生成报文时拿默认路由网卡的 ip 做源地址
22:56:11.243903 ee:ee:ee:ee:ee:ee > 36:42:dd:fc:5a:a1, ethertype IPv4 (0x0800), length 98: 172.18.22.111 > 10.244.153.216: ICMP echo request, id 4, seq 7, length 64
22:56:11.243930 36:42:dd:fc:5a:a1 > ee:ee:ee:ee:ee:ee, ethertype IPv4 (0x0800), length 98: 10.244.153.216 > 172.18.22.111: ICMP echo reply, id 4, seq 7, length 64

在 veth 内 eth0 抓包

22:56:11.243903 ee:ee:ee:ee:ee:ee > 36:42:dd:fc:5a:a1, ethertype IPv4 (0x0800), length 98: 172.18.22.111 > 10.244.153.216: ICMP echo request, id 4, seq 7, length 64
22:56:11.243930 36:42:dd:fc:5a:a1 > ee:ee:ee:ee:ee:ee, ethertype IPv4 (0x0800), length 98: 10.244.153.216 > 172.18.22.111: ICMP echo reply, id 4, seq 7, length 64
  • Node 到其他 node 上的 pod
    node111 到 pod3
    在 node111 ens10 抓包,根据路由 10.244.146.192/26 via 192.168.100.112 dev ens10 proto bird
21:10:18.124555 52:54:00:dc:c7:b4 > 52:54:00:d3:bf:21, ethertype IPv4 (0x0800), length 118: 192.168.100.111 > 192.168.100.112: 10.244.153.192 > 10.244.146.205: ICMP echo request, id 11, seq 62, length 64
21:10:18.129910 52:54:00:d3:bf:21 > 52:54:00:dc:c7:b4, ethertype IPv4 (0x0800), length 118: 192.168.100.112 > 192.168.100.111: 10.244.146.205 > 10.244.153.192: ICMP echo reply, id 11, seq 62, length 64

Pod 到 service

# kubectl get svc
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
nginx-service   ClusterIP   10.107.161.255   <none>        8080/TCP   2s
# kubectl get endpoints
NAME            ENDPOINTS                             AGE
nginx-service   10.244.146.212:80,10.244.153.216:80   5s
  • Pod 访问 service clusterIP
    在 pod1 veth 对抓包,目的地之为 svcIP
22:58:56.371127 de:f9:e6:21:f3:22 > ee:ee:ee:ee:ee:ee, ethertype IPv4 (0x0800), length 74: 10.244.153.214.33430 > 10.107.161.255.webcache: Flags [S], seq 1879858029, win 64240, options [mss 1460,sackOK,TS val 1064877586 ecr 0,nop,wscale 7], length 0
22:58:56.371341 ee:ee:ee:ee:ee:ee > de:f9:e6:21:f3:22, ethertype IPv4 (0x0800), length 74: 10.107.161.255.webcache > 10.244.153.214.33430: Flags [S.], seq 46666836, ack 1879858030, win 65160, options [mss 1460,sackOK,TS val 512837314 ecr 1064877586,nop,wscale 7], length 0

在 pod2 veth 对抓包,源地址为 主机默认路由网卡 ip,目的地址为 pod2,目的端口为 80

22:59:25.194941 ee:ee:ee:ee:ee:ee > 36:42:dd:fc:5a:a1, ethertype IPv4 (0x0800), length 74: 10.244.153.214.39958 > 10.244.153.216.http: Flags [S], seq 3052450619, win 64240, options [mss 1460,sackOK,TS val 1064906410 ecr 0,nop,wscale 7], length 0
22:59:25.194996 36:42:dd:fc:5a:a1 > ee:ee:ee:ee:ee:ee, ethertype IPv4 (0x0800), length 74: 10.244.153.216.http > 10.244.153.214.39958: Flags [S.], seq 3853432263, ack 3052450620, win 65160, options [mss 1460,sackOK,TS val 512866138 ecr 1064906410,nop,wscale 7], length 0

去 service dnat 成后端 IP 转到 pod2,pod2 回复 pod1,再 snat 成 svcIP。
后端为 跨节点的 pod3 和上面相同

Node 到 service

  • Node 访问 service clusterIP
    本节点 pod 时
    Dnat 成 pod2 ip,根据默认路由网卡 IP,构造报文
22:59:56.156054 ee:ee:ee:ee:ee:ee > 36:42:dd:fc:5a:a1, ethertype IPv4 (0x0800), length 74: 172.18.22.111.49871 > 10.244.153.216.http: Flags [S], seq 1440047978, win 65495, options [mss 65495,sackOK,TS val 2095085657 ecr 0,nop,wscale 7], length 0
22:59:56.156112 36:42:dd:fc:5a:a1 > ee:ee:ee:ee:ee:ee, ethertype IPv4 (0x0800), length 74: 10.244.153.216.http > 172.18.22.111.49871: Flags [S.], seq 1382921424, ack 1440047979, win 65160, options [mss 1460,sackOK,TS val 3307386812 ecr 2095085657,nop,wscale 7], length 0

跨节点 pod 时
Dnat 成 pod3 ip,根据路由用 10.244.146.192/26 via 192.168.100.112 dev ens10 proto bird 的 网关去请求

23:00:18.641689 ee:ee:ee:ee:ee:ee > be:9d:c7:f8:b7:61, ethertype IPv4 (0x0800), length 74: 192.168.100.111.12138 > 10.244.146.212.http: Flags [S], seq 417839269, win 65495, options [mss 65495,sackOK,TS val 2095108142 ecr 0,nop,wscale 7], length 0
23:00:18.641775 be:9d:c7:f8:b7:61 > ee:ee:ee:ee:ee:ee, ethertype IPv4 (0x0800), length 74: 10.244.146.212.http > 192.168.100.111.12138: Flags [S.], seq 3468595817, ack 417839270, win 65160, options [mss 1460,sackOK,TS val 3469987261 ecr 2095108142,nop,wscale 7], length 0

外部到 svc

default    nginx-service   NodePort    10.107.161.255   <none>   8080:30080/TCP

在主机被访问 IP 网卡抓包

23:04:01.185278 52:54:00:d0:eb:12 > 52:54:00:ba:dc:62, ethertype IPv4 (0x0800), length 74: 172.18.22.108.45618 > 172.18.22.111.30080: Flags [S], seq 662387376, win 64240, options [mss 1460,sackOK,TS val 14241135 ecr 0,nop,wscale 7], length 0
23:04:01.185529 52:54:00:ba:dc:62 > 52:54:00:d0:eb:12, ethertype IPv4 (0x0800), length 74: 172.18.22.111.30080 > 172.18.22.108.45618: Flags [S.], seq 1190337779, ack 662387377, win 65160, options [mss 1460,sackOK,TS val 3307631841 ecr 14241135,nop,wscale 7], length 0
Chain KUBE-NODE-PORT (1 references)
target     prot opt source               destination
KUBE-MARK-MASQ  tcp  --  0.0.0.0/0            0.0.0.0/0            /* Kubernetes nodeport TCP port for masquerade purpose */ match-set KUBE-NODE-PORT-TCP dst

Masquerade 转为

23:04:01.185434 ee:ee:ee:ee:ee:ee > 36:42:dd:fc:5a:a1, ethertype IPv4 (0x0800), length 74: 172.18.22.111.8408 > 10.244.153.216.http: Flags [S], seq 662387376, win 64240, options [mss 1460,sackOK,TS val 14241135 ecr 0,nop,wscale 7], length 0
23:04:01.185484 36:42:dd:fc:5a:a1 > ee:ee:ee:ee:ee:ee, ethertype IPv4 (0x0800), length 74: 10.244.153.216.http > 172.18.22.111.8408: Flags [S.], seq 1190337779, ack 662387377, win 65160, options [mss 1460,sackOK,TS val 3307631841 ecr 14241135,nop,wscale 7], length 0

如果 后端不在本节点
Masquerade 转为 192.168.100.111 (根据默认路由决定)

23:04:59.183752 ee:ee:ee:ee:ee:ee > be:9d:c7:f8:b7:61, ethertype IPv4 (0x0800), length 74: 192.168.100.111.36047 > 10.244.146.212.http: Flags [S], seq 3939988989, win 64240, options [mss 1460,sackOK,TS val 14299130 ecr 0,nop,wscale 7], length 0
23:04:59.183829 be:9d:c7:f8:b7:61 > ee:ee:ee:ee:ee:ee, ethertype IPv4 (0x0800), length 74: 10.244.146.212.http > 192.168.100.111.36047: Flags [S.], seq 2347549368, ack 3939988990, win 65160, options [mss 1460,sackOK,TS val 3470267803 ecr 14299130,nop,wscale 7], length 0

CNI 网络流量 4.5 Calico BGP相关推荐

  1. CNI 网络流量 5.2 Cilium 流量分析(一)

    文章目录 Pod 间 同节点 pod 跨节点 pod in vxlan 小结 环境: fedora37,kernel:6.0.7-301.fc37.x86_64,cilium 版本 v1.13.0 传 ...

  2. CNI 网络流量 5.3 Cilium 流量分析(二)

    文章目录 Native Routing 部署 同节点 pod 到 node 跨节点 pod 到 node 跨节点 pod 到 pod Native Routing 除了 overlay 的 vxlan ...

  3. 追踪 Kubernetes 中的网络流量

    作者 | Addo Zhang 来源 | 云原生指北 译者注: 这篇文章很全面的罗列出了 Kubernetes 中涉及的网络知识,从 Linux 内核的网络内容,到容器.Kubernetes,一一进行 ...

  4. K8s NetworkPolicy与网络插件flannel、calico详细版

    Pod是Kubernetes调度的最小单元.一个Pod可以包含一个或多个容器,因此它可以被看作是内部容器的逻辑宿主机.Pod的设计理念是为了支持多个容器在一个Pod中共享网络和文件系统.那么为什么Po ...

  5. K8S CNI及各CNI网络解决方案简述

    CNi: 什么是CNI? CNI是Container Network Interface的缩写,是一个标准的通用的接口.为了让用户在容器创建或销毁时都能够更容易地配置容器网络,现在容器平台:docke ...

  6. K8s网络插件Flannel,Calico

    文章目录 一.K8s网络插件flannel与calico 1. k8s网络解决方案 容器虚拟化网络方案 基于隧道 基于路由 2. CNI(容器网络接口) flannel与calico 选型比较 3. ...

  7. 数据中心网络流量精细运维

    从IDC运营商和云服务商的角度来说,做好网络运维是企业的根本.国内对互联网带宽需求的快速增长,催生出很多大型的IDC服务商,他们在全省.全国,甚至全世界布局数据中心.快速布局的同时如何对数据中心流量精 ...

  8. 阿里云容器服务cni网络插件terway非官方网络性能测试

    作者:张荣滨,酷划在线后端架构师,关注微服务治理,容器化技术,Service Mesh等技术领域 terway网络性能测试 酷划在线成立于2014年,是国内激励广告行业的领军者.酷划致力于打造一个用户 ...

  9. 俄罗斯国有电信提供商被指大规模劫持网络流量,意外还是阴谋?

     聚焦源代码安全,网罗国内外最新资讯! 编译:奇安信代码卫士团队 4月1日,俄罗斯国有电信提供商Rostelecom 被指进行大规模的 BGP 劫持,将200多家厂商(包括谷歌.亚马逊.Faceboo ...

最新文章

  1. 涨点技巧!汇集13个Kaggle图像分类项目的性能提升指南
  2. 强网杯2019 Copperstudy
  3. Oracle存储过程procedure与函数function区别
  4. 安卓ssr无网络连接_解决Android模拟器网络问题(使用了代理的情况下)
  5. 《系统集成项目管理工程师》必背100个知识点-54冲突解决方法
  6. 严格程度_国内医疗器械生产许可证申请申报-经营一类、二类、严格的三类之间区别...
  7. Mysql 的子查询
  8. 树链剖分概念及模板 + 例题 [POJ3237 tree + 软件包管理器]
  9. 计算机鼠标介绍教学反思,《玩转鼠标》教学反思
  10. CXF发布RestFul WebService和SOAP WebService
  11. 学习记录-操作系统知识(1)
  12. hdoj--5621--KK's Point(简单数学)
  13. python暂停和恢复按钮,Python:如何暂停和恢复线程
  14. 利用计算机打字教学设计,四年级全一册信息技术教案-第1课正确的坐姿和指法--基本键打字练习 河大版...
  15. redis灵魂拷问:聊一聊zset使用
  16. mysql数据驱动测试_[ddt02篇]十年测试老鸟帮您解析:ddt结合excel,csv,mysql实现自动化测试数据驱动...
  17. 数字特征值-对数字求特征值是常用的编码算法,奇偶特征是一种简单的特征值
  18. 台式计算机无法启动不了,电脑开机启动不了怎么办 电脑开机进不去系统的解决方法...
  19. 阿里妈妈展示广告引擎动态算力再探索:面向业务收益的机器自适应调配
  20. 离线数仓 (十三) --------- DWD 层搭建

热门文章

  1. 微信读书vscode插件_VSCODE插件推荐
  2. 慧拓 规划算法实习生 20220818 笔面试
  3. 创业机会:你眼前的机会早已不是机会
  4. [创业基础笔记] 第3章-识别创业机会
  5. IT综合运维系统-身份对接记录
  6. 7-9 求分数序列前N项和 (15 分)
  7. php解析JSON数据
  8. 计算机情感计算的sci,情感
  9. echarts饼图的颜色修改
  10. 交换两个变量值的四种方法