您的位置:  首页 > 技术杂谈 > 正文

服务网格数据面性能深度调优

2022-02-23 11:00 https://my.oschina.net/u/4565392/blog/5460458 网易数帆 次阅读 条评论

导读:服务网格作为云原生的重要技术,提升了微服务的流控、熔断、升级等服务治理能力,但同时sidecar的引入也导致了时延的增加。网易数帆通过对时延引入的具体分析,尝试利用eBPF和用户态协议栈技术,来对时延进行优化,并最大限度的考虑兼容性,做到对容器网络、sidecar应用的无侵入加速。

时延分析

服务网格中sidecar的引入在整个网络路径上增加了两个网络处理单元,从而不可避免的会引入时延。针对sidecar本身逻辑的优化来优化时延是社区的一个方向,比如envoy社区针对mixer的优化。另外一个方向是针对链路底层做优化。

如果打开整个链路来看,sidecar会多引入Service到sidecar的链路以及sidecar到sidecar的链路,客户端和服务端总共多经过了四次内核态协议栈。我们通过了火焰图分析了sidecar应用envoy的CPU占用,发现内核态协议栈的CPU占比近50%,所以针对内核态协议栈的优化效果理论上应该非常可观。

另外也可以针对容器网络做优化,比如使用SRIOV容器网络方案,不过会涉及对已有的容器网络方案的改造,有侵入性。

eBPF Sockops优化Service和sidecar通信

Service和sidecar之间属于同一个节点的两个容器间的通信,可以采用Sockops组件进行加速。

Sockops原本是开源Cillium中的一个组件,利用sockmap和sk redirect技术直接绕过TCP/IP协议栈将报文直接发给对端socket,从而来加速同节点socket之间的通信。我们借用相关实现并作了增强开发,来适配sidecar的场景。

Sockops加速在《eBPF 在网易轻舟云原生的应用实践》中有详细说明,参见:https://www.infoq.cn/article/ovcvwqijzta7jlexgdoc

从最终测试结果来看,使用Sockops加速Service和sidecar的通信,可以降低时延10%左右。

用户态协议栈优化sidecar和sidecar通信

sidecar和sidecar之间的通信会涉及跨节点,无法使用Sockops进行加速,这里我们使用用户态协议栈替换内核态协议栈实现。用户态协议栈相较内核态协议栈可以在两个方面带来性能的提升:

  1. 消除内核态和用户态切换的开销;
  2. 将协议栈的实现代码放到独立的用户态进程中实现,去除sidecar中协议栈实现的CPU开销;

下面来具体说明相关实现。

VPP+VCL分离式部署节省CPU资源

为了兼顾到性能和资源占用,我们选择VPP作为用户态协议栈。VPP作为独立进程实现用户态协议栈,并提供轻量级的VCL动态库供sidecar集成以实现socket接口的劫持,VPP和VCL之间通过共享内存进行通信。

其中:

VCL - 实现Socket类接口劫持并和后端VPP完成交互

FIFO - 是基于共享内存封装的消息队列,用于VCL和VPP之间通信

Session - 维持传输层和上层应用会话之间的对应

TCP/IP - 对应内核的TCP/IP协议栈实现

AF_XDP - 实现将网卡的报文收发卸载到用户态

可见,VPP+VCL分离式的部署模式将协议栈从应用端剥离,VPP作为实现协议栈的独立进程可以服务于节点上的所有sidecar,从而将sidecar和协议栈的1:1绑定部署关系,变为N:1的独立部署关系,节省了总体的CPU资源占用。同时,sidecar也将更多的CPU资源用于自身业务逻辑的处理,提高了CPU资源的利用率,从而降低了sidecar节点的处理时延。

无侵入设计提升易用性

无侵入设计体现在南北两个方向,南向对接容器网络,而北向对接sidecar。

北向对接sidecar时,会通过VCL动态库供sidecar集成。VCL动态库中会自动劫持socket接口,这样就无需sidecar修改代码。而且VCL动态库支持LD_PRELOAD加载方式,仅需要sidecar应用启动时指定此环境变量来配置VCL动态库的路径即可。

南向对接容器网络会麻烦一些。容器网络种类繁多,但是最终都会插入一个网口给POD使用,此网口以veth口居多,也有可能是VF口。由于并不是所有的流量都需要走sidecar,比如Service和宿主机通信就只需要走内核态,那么如何在保留现有内核通信通道的情况下进行用户态协议栈的加速呢?

我们借助AF_XDP来做流量的分流。即先使用XDP针对于特定报文进行过滤,满足条件则送入VPP,否则继续走内核。

报文分流到VPP,再上送sidecar后,sidecar还需要将报文发送给Service,这条路径只能走内核,可以通过Sockops进行加速。

双栈支持

双栈支持其实包括两个方面。

一个是基于eth0口基于AF_XDP的双栈分流,这个在上节中已经做了说明。

另一个是sidecar的双栈支持,因为sidecar也需要通过内核态和Service进行通信。

sidecar的双栈支持需要VCL中针对报文做区分,需要走内核态的报文则重新调用原生的socket接口让报文走内核态协议栈。

优化效果

针对不同的RPS测试Both Sidecar时延的情况,ua表示启用了用户态协议栈优化。可以看出,用户态协议栈时延降低30%左右,Sockops时延降低10%左右,两者结合后时延降低35%左右。

写在最后

AF_XDP+用户态协议栈+Sockops针对服务网格sidecar场景,优化了内核协议栈的CPU资源占用,降低了sidecar所引入的端到端时延,且对当前的容器网络以及sidecar应用无修改,做到无侵入加速。用户态协议栈和Sockops的管控基于Kubernetes Operator进行开发,部署和运维也非常简单,根据需要可以单独进行部署,也可以合并使用。后续我们也会考虑将针对服务网格的这些加速套件进行开源。

另外,通过加速组件的灵活组合,除了sidecar加速,我们也上线了针对API网关的加速,单独的用户态协议栈加速组件我们也在拓展到Redis、Nginx等加速场景。

作者简介:汪翰林,网易数帆系统开发专家,17年软件开发老兵。曾就职于华三和华为,从事安全、视频监控、大数据和网络虚拟化等技术产品研发,目前在网易数帆轻舟云原生团队负责高性能网络技术预研和产品落地工作。

展开阅读全文
  • 0
    感动
  • 0
    路过
  • 0
    高兴
  • 0
    难过
  • 0
    搞笑
  • 0
    无聊
  • 0
    愤怒
  • 0
    同情
热度排行
友情链接