上篇分析了linux内核的netdev_max_backlog默认设置导致了openvswitch在大量virtual port转发异常的问题,本篇再额外记录一处与大量virtual port相关的调优点。
自openvswitch 2.x版本开始,ovs引入了多线程的支持,在非dpdk即传统的ovs应用模式下,多线程主要用于处理内核fastpath lookup miss的流表,此过程称为upcall;并对这些流表进行统计、老化处理,此过程称为revalidate。
upcall和revalidate的线程数量计算,以openvswitch 2.3.x为例,代码中的判断是将物理核数约3/4分配给upcall,而revalidate则占1/4,这个分配直观上是合理的,毕竟upcall处理转发,要尽可能的快,处理能力也要更强。
而我们知道openvswitch datapath对用户态的每个virtual port都会在linux内核datapath中创建一个vport,内核datapath通过netlink发送消息给upcall,为了更快的处理每个vport的upcall请求,openvswitch将会为每个virtual port分配等同upcall线程数量的netlink socket,内核datapath根据flow hash将同一vport的upcall分发给不同的netlink socket,实现不同upcall线程间的并发处理,提升upcall性能。
从这里可以看出,openvswitch在优化性能方面确实做足了功夫,但这里确存在一个值得考虑的地方,我们知道linux process存在一个max open files的限制,当限制达到后,新的fd将无法被分配,导致建立文件、创建socket等需要用到fd资源的操作无法执行。
那么我们可以估计一个24 physical core的系统上,如果有2000个virtual port,openvswitch将会有多少个netlink socket,243/42000即36000,也即单音用于处理vport的netlink socket就占用了36000个fd,如果对openvswitch的max open files限制过小,很容易导致在大量virtual port下,出现各种工作异常。
对于此问题主要的优化思路如下:
- 调整ovs-vswitchd进程的max open files limit上限,可按照前述算法估量
- openvswitch提供了一个n-handler-threads的配置,可通过ovs-vsctl持久化配置,根据性能需求适当的减少upcall线程数量