做网站用不用thinkphp枸橼酸西地那非片是什么
今天晚上和小小一起学习,上个晚自习。
已经是reuseport骨灰级玩家了,所以简单写。
最开始,Linux协议栈并没有完全兼容BSD的reuseport语义,也就是说,Linux 3.9之前,所谓的reuseport仅仅有socket热备份功能,没有socket负载均衡功能,但是很快在3.9内核之后,Linux协议栈的reuseport功能便完善了:
- Active-Backup
- Active-Active
最开始的 Active-Active 实现非常Low,自己看代码就知道了,必须遍历所有的socket,计算hash,才能选出工作socket,如果系统的Listener(TCP的,或者UDP的,比如DNS)非常多,那么socket lookup将会成为热点,徒耗CPU。
而后,在Linux 4.6,事情起了变化,改成了取模算法,详见:
https://blog.csdn.net/dog250/article/details/80458669
增加了eBPF的支持,看起来很棒,但是好用吗?不一定。
比如,我想实现一致性哈希,Linux 4.6版本的reuseport调用eBPF很难吧。即便实现一个最简单的一致性哈希,为了简洁,我也首选kpatch这类hotfix方案,而不是去写一个eBPF程序。以下是我的一致性哈希的代码:
https://blog.csdn.net/dog250/article/details/89268404
然而,如何用一种更加优雅的方案去促成这件事呢?
…
等吧。
终于,在eBPF的大潮下,我们迎来了 BPF_PROG_TYPE_SK_REUSEPORT ,这是又一个新增的eBPF的HOOK点,当reuseport逻辑选择socket的时候,该类型的eBPF程序被调用,最终的效果是:
- 给定一个数据包skb,该HOOK点的eBPF程序会为该skb选择一个处理它的socket。
先花一两分钟浏览下面的链接:
https://lwn.net/Articles/762101/
https://github.molgen.mpg.de/donald/linux/commit/8217ca653ec601246832d562207bc24bdf652d2f
它们交代了这个eBPF的HOOK点的来龙去脉。
reuseport这个HOOK点的eBPF程序依托两层嵌套的map:
首先,数据包根据元数据map到一个内层的reuseport map,该内层的map以数据包的内容为key,map到特定的socket。
有点意思,不是吗?
若要写代码,也不难,我这里没时间搞了,小小已经睡着了,我也要睡了,不过还是给出一个未完成的demo:
struct {__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);__uint(max_entries, 1);__uint(key_size, sizeof(__u32));__uint(value_size, sizeof(__u32));
} outer_map SEC(".maps");struct {__uint(type, BPF_MAP_TYPE_ARRAY);__uint(max_entries, NR_RESULTS);__type(key, __u32);__type(value, __u32);
} result_map SEC(".maps");SEC("select_by_skb_data")
int _select_by_skb_data(struct sk_reuseport_md *reuse_md)
{__u32 index = 0, flags = 0, dummy = 0, key = 0;void *data, *data_end;void *reuseport_array;enum result result;struct udphdr *uh;int err;data = reuse_md->data;data_end = reuse_md->data_end;if (reuse_md->eth_protocol != bpf_htons(ETH_P_IP))return SK_PASS;if (reuse_md->ip_protocol != IPPROTO_UDP)return SK_PASS;uh = data;if (uh + 1 > data_end)return SK_PASS;// 仅仅一个reuseport组而已reuseport_array = bpf_map_lookup_elem(&outer_map, &dummy);if (!reuseport_array)return SK_DROP;// ... key的获取过程,略!// key计算自数据包内容err = bpf_sk_select_reuseport(reuse_md, reuseport_array, &key, flags);if (err)return SK_DROP;return SK_PASS;
}char _license[] SEC("license") = "GPL";
如果想知道更加详细的信息,请自行debug内核源码树的下面的文件:
linux-source-5.3.0/tools/testing/selftests/bpf/progs/test_select_reuseport_kern.c
linux-source-5.3.0/tools/testing/selftests/bpf/test_select_reuseport.c
自诩reuseport,Netfilter/iptables,eBPF/XDP骨灰级玩家,欢迎志同道合者周末一起玩耍,然而也有我不会,不擅长的,比如DPDK,FPGA,Golang,数据库等,等等等等。
浙江温州皮鞋湿,下雨进水不会胖!