6165金沙总站 15

网络管理,Kafka性能优化之坎坷路

Kafka性能优化之坎坷路(2),kafka性能优化

接上一篇:

题外话:
 上一篇简单说了一下自己对kafka的一些基础理解,以及c++中如何利用librdkafka来实现我们自己的业务需求。这一篇就来研究研究一些另类玩法,跟代码无关,用到的技术也不算新,但是令我感到意外的是,竟然没有人这么使用过,实践过。。。
 我挺难受的,这么一些通用且实用,而且通过很简单的操作就能提升数倍性能的方法,竟然甚少人去使用他们,甚至闻所未闻。忽然觉得中国这个IT环境里,怎么才能造就出伟大的程序员,公司注重的是利益,领导注重的是结果,不懂技术的人做领导,懂技术的人被领导,面试靠张嘴,工作靠开会,晋升靠资历,找工作靠学历。。。
 百分之99的项目,“先出一个版本,后面再考虑优化”“这个需求很简单,怎么实现我不管,明天我就要”,然而。。永远没有时间梳理,也无暇思考。项目永远很急,程序员永远在加班。。。以前的代码永远要靠下一任调bug。。。

扯远了,回归正题吧。

一.Kafka环境搭建
 网上有很多环境搭建的教程示例,看了一下,几乎全是千篇一律,都是相互转过来转过去,没有考虑到实际应用场景,也不考虑性能到底怎么样,也不考虑为何要这么搭,反正大家都是按这个套路来的,甚至我想找一篇搭建5个节点集群的都找不到。
 实际生产环境中,我们的kafka是搭建在服务器上的,我们都知道每台服务器搭建一个节点,多个节点组成一个集群。我们也知道kafka的性能瓶颈是在网络IO和磁盘读写速度上。
正常情况下这么搭建当然是没问题的,而且kafka本身是为短消息而设计的,但是在绝大多数应用场景中,我们不得不实时传输图片这种大消息,假设我们要搭建一个支持日吞吐量4000万数据的集群,每条消息1M,
我们来算一下:
 假设每个节点带宽是1000Mbps,可传输的字节数就1000/8=125M,
如果要支持每秒钟处理500条数据,那需要一个多大的集群呢?
好的,500条*1M=500M, 500M/125M=4。
也就是4个节点的集群。没毛病吧老铁?
没毛病么?毛病很大啊。我们算的这500M仅仅是数据吞吐量的带宽,但是吞吐量吞吐量,有吞也有吐啊。
最简单的1份生产1份消费,各需要占掉其中一半的带宽,那我们要达到每秒钟生产500条消费500条,最少就需要1000M字节的带宽。
这只是最理想的环境,实际应用中,必然不止一个用户要从kafka中消费数据,假设有3个用户要从集群中消费数据,还要支持每秒500条,这就意味着我这个集群的吞吐总量要达到每秒钟2000M字节,网络io比特率要满足每秒钟20000Mbps,如果每个节点采用千兆网卡,那意味着我需要一个由20台服务器组成的集群。一台服务器保守点配置一般的5万块钱一台,那就需要100万成本。
这明显不对啊,kafka不是号称吞吐量宇宙第一的么,怎么会要靠堆积服务器的数量来满足仅仅是每秒处理500条数据的需求呢?
这其中一定有问题,我要去找官方要个说法去,这跟你们吹出来的完全不符合啊,逗我呢吧?
求带麻袋,我们再仔细回过头来想一想,问题出在哪呢,我们的计算也没问题,这还是算的最最理想的情况下,实际的生产环境可能更差。不对,一定有问题。

仔细屡了又屡,真的没问题,我们公司就是这么用的啊,我们公司也是这么用的啊,没毛病吧老铁?
没毛病么?毛病很大啊。通过上面的计算我们很显然会得出一个强有力而且官方可验证的结论,限制kafka性能的只能是网络带宽不够大。有没有办法解决呢?换万兆带宽?整个都换成万兆,那不得了,成本又翻了一倍,200万成本。

好吧,接下来就是我们如何解决这个网络瓶颈的实践之路了:
   
既然我们的瓶颈是在网络上,网络的瓶颈又是在网卡上,把千兆网卡换万兆网卡又不现实,那就只剩一条路了,加多块网卡。OK,一般的服务器都支持4网口+1管理口,先来插上四根网线,配置四个ip地址。没毛病,然后我们就想了,既然都有四块网卡,每块网卡又有独立的ip地址了,那我们是不是可以在一台机器上搭建4个kafka节点,每个节点绑定一块网卡呢,来试试吧,很激动。。。按照教程,一步一步,摩擦摩擦,biu的一。。。。纳尼??竟然起不来??难道我配置出问题了?检查一遍,给我起。。。检查两遍,给我起。。。检查三遍。。。百度谷歌,检查四遍。。。什么鬼???kafka难道不支持在一台机器上开多个进程?不对啊,不是还有在一台机器上搭建伪集群的教程摆在那呢,那说明不是kafka的问题。然后又是一顿查,一顿乱试,终于。。我们检验出了真相:在同一台机器上起多个kafka需要配置端口号不一样,而且新版kafka逐渐废弃了host.name和port这两个配置项,所有相关的配置,只需要配置listeners即可。
再全部删掉重新来过,配网卡ip,配listeners,给我起!哈哈哈,终于起来了,而且可以正常生产消费数据了,我真是太厉害了,这么难的问题竟然被我搞定了,经过这么多努力,我们终于可以实现一块网卡对应一个kafka节点的伟大愿望了,还有谁?? 
然而。。。俗话说的好。。。不要高兴的太早。。。太早。。早。。

来吧,让我们看一看你的网络IO瓶颈能不能达到4000Mbps吧,手指飞快的输入一串代码:sar
-n DEV 1  
当当当。。随着生产线程数的增多,网络io很快达到1000Mbps了,我要再加10个生产!
sar -n DEV 1
当当当。。。什么?网络io竟然还是1000Mbps,不对不对,怎么肥四?抓个包看一看,四个ip分别建立tcp链接并开始交互数据,没问题啊,再仔细一瞅,我去,为啥所有ip指向的都是同一个mac地址,这不科学啊,是在逗我吧?我不信,肯定是我哪里配置错了,肯定是我心不够虔诚,肯定是我启动的方式不对。。。我不信,我不信。。。我不信。。。让我们再试一遍。。两遍。。。三遍。。。
求带麻袋,所有网卡ip都指向了一个mac地址,是不是说需要手动配置网卡的路由信息,让每个网卡都通过自己的路由来转发数据,查资料,看教程,看man手册,配置路由。。让我们再虔诚的试一次。。。试两次。。。试三次。。。不玩了。。我要回家,我想妈妈。。。

静下心来再想想:我们现在可以确认的是,在一台机器上搭建集群是可行的,只需配置端口号不一样即可,每个kafka节点绑定一块网卡的方式不可行,即使把套接字绑定到一个特定网卡的ip上,数据包离开主机时会首先经过路由表,路由表会寻找最低成本的网络接口(任意静态的接口)进行发送,我们配置的四块网卡具有相同的成本,因为四块网卡是在同一个子网内(即同一个网段),因此传输率不会超过单张网卡的传输率,如果要解决这个问题,那么可行的途径是手动配置路由表信息,而且要保证四块网卡的ip位于不同的网段上,并要确保不同的网段是可以连通的。

好吧,实际应用中我们是被分配ip的那一个,而不是可以任意分配网段的那一个,显然这种方式也不可行,但是起码我们总结出了一套可行方案不是么。

我们花了大量的时间研究kafka跟网卡之间的关系,但忽然回过头来想,发现我们不知不觉中绕了一个大弯。归根结底,我们是要解决网络带宽的问题,结果反而把自己绕到跟kafka的关联上了,既然在一台机器上可以搭建伪集群,那么为什么不把这台机器的所有网卡做一个绑定呢?

从Centos7开始使用team模式,链路聚合的方式进行多网卡绑定,让我们来试一试吧:
详细说明请参考官方文档:

要明确的是,用于绑定的网卡,不应该配置任何静态的IP地址,进行绑定之前,需要将所有网卡恢复到初始化状态。而且一台服务器只能有一个网关。
我们需要的是增加带宽模式的绑定,至于其它模式,请自行研究,通过NetworkManager来配置一下:

  1. 创建team1,并选择模式:
    命令:nmcli connection add con-name team1 type team ifname team1 config
    ‘{“device”: “team1”, “runner”: {“name”: “loadbalance”,”tx_hash”:
    [“eth”, “ipv4”, “ipv6″],”tx_balancer”: {“name”: “basic”}}}’
  1. 添加网卡进行绑定(本机一共四块网卡)
    命令:nmcli connection add con-name team1-port1 type team-slave ifname
    enp2s0f0 master team1
    nmcli connection add con-name team1-port2 type team-slave ifname
    enp2s0f1 master team1
    nmcli connection add con-name team1-port3 type team-slave ifname
    enp2s0f2 master team1
    nmcli connection add con-name team1-port4 type team-slave ifname
    enp2s0f3 master team1
  1. 给绑定后的虚拟网卡设置IP地址和网关
    命令:nmcli connection modify team1 ipv4.addresses 192.20.25.100/24
    ipv4.gateway 192.20.25.254 ipv4.method manual
    备注:ipv4.addresses
    192.20.25.100/24这里是四块网卡聚合成一块网卡的ip地址和子网掩码缩写。
    ipv4.gateway 192.20.25.254这里是网卡的网关配置。
  1. 启动team1
    命令:nmcli connection up team1 

5.重启网络
命令:systemctl restart network

  1. 查看状态
    命令:teamdctl team1 state
    备注:这里应该显示了4块网卡的信息。
  1. 列出team1的端口
    命令:teamnl team1 ports
    备注:这里应该显示了4块网卡的信息。

其余的操作:nmcli device disconnect  enp2s0f0 (禁用其中的一块)
nmcli device connect enp2s0f0(启用其中的一块)
ip link set down enp2s0f0 (关闭掉其中的一块进行测试)

  1. 查看网络
    命令:ip add
    备注:这里就可以显示出team1的信息(ip和网关等信息)。

至此,配置多网卡链路聚合结束。

万分期待中,我们在其之上搭建了一个kafka伪集群,开始测试。。。开10个生产!
当当当。。。网络IO达到1000Mbps,2000Mbs,3000Mbps,3600Mbps…天呐,竟然成功了。。。而且带宽损失率竟然不超过百分之10.。。

我们成长在一个幸运的时代,学习进步的成本如此之小,

我们成长在一个不幸的时代,学习进步的成本如此之大。

CentOS 6之前,网络接口使用连续号码命名:eth0、eth1等,当
增加或删除网卡时,名称可能会发生变化 
CentOS 7使用基于硬件,设备拓扑和设置类型命名: 
(1) 网卡命名机制 systemd对网络设备的命名方式
(a) 如果Firmware或BIOS为主板上集成的设备提供的索引信
息可用,且可预测则根据此索引进行命名,例如eno1
(b) 如果Firmware或BIOS为PCI-E扩展槽所提供的索引信息
可用,且可预测,则根据此索引进行命名,例如ens1
(c) 如果硬件接口的物理位置信息可用,则根据此信息进行命
名,例如enp2s0
(d) 如果用户显式启动,也可根据MAC地址进行命名, enx2387a1dc56
(e) 上述均不可用时,则使用传统命名机制

一.CentOS 7网络属性配置

(一)网卡名称命名

使用传统命名方式: 

(1) 编辑/etc/default/grub配置文件 GRUB_CMDLINE_LINUX=”rhgb quiet
net.ifnames=0″

6165金沙总站 1

image.png

(2) 为grub2生成其配置文件

grub2-mkconfig -o /etc/grub2.cfg 或是grub2-mkconfig >
/etc/grub2.cfg
(3) 重启系统
或采用对/boot/grub2/grub.cfg来实现修改
步骤:

(1)vim /boot/grub2/grub.cfg

6165金沙总站 2

image.png

6165金沙总站 3

image.png

6165金沙总站,(2) cdnet ——cd /etc/sysconfig/network-scripts来修改配置文件
vim ifcfg-ens33

6165金沙总站 4

image.png

(3)保存后。重启使其生效

(二) CentOS7主机名

(1)配置文件:/etc/hostname ,默认没有此文件,通过DNS反向解
析获取主机名,主机名默认为:localhost.localdomain——cat /etc/hostname 

6165金沙总站 5

image.png

(2)显示主机名信息 hostname hostnamectl status 
(3)设置主机名 hostnamectl set-hostname centos7.magedu.com

区别于centos6,采用上述命令后会自动生成,且自动写入配置文件中

6165金沙总站 6

image.png

(4)删除文件/etc/hostname,恢复主机名localhost.localdomain 
CentOS 7网络配置工具 

图形工具:nm-connection-editor 

字符配置tui工具:nmtui 

6165金沙总站 7

image.png

(三)nmcli命令

(1)命令行工具:nmcli——有很多的子命令

6165金沙总站 8

image.png

通过 nmcli connection help来熟悉相关命令

6165金沙总站 9

image.png

nmcli [ OPTIONS ] OBJECT { COMMAND | help }

  • device – show ——相当于ip link,查看数据链路层信息
  • nmcli connection show ——相当于ip addr查看网络层信息
    (2)修改IP地址等属性
  • nmcli connection modify ens33 connection.id
    eth0——将name=ens33改为eth0

    cat /etc/sysconfig/network-scripts/ifcfg-ens33

    6165金沙总站 10

    image.png

    nmcli con reload:重新加载,作用是使配置文件生效

  • 在eth1网卡上新增一个网卡
    nmcli connection add con-name home-eth1 ethernet ifname eth1

    ls /etc/sysconfig/network-scripts/ifcfg-home-eth1

    6165金沙总站 11

    image.png

    此时让该网卡生效作用在eth1中:nmcli connection uo
    home-eth1,原来的网卡被挤掉,使用新配置的网卡,因为该网卡的BOOTPROTO是dhcp类型的,所以会自动获取新的网址
    如果想将自动获取方式改为手动获取方式,则通过:nmcli connection
    modify home-eth1 ipv4.method manual ipv4.addresses 3.3.3.3/24
    ipv4.gateway 3.3.3.1 ipv4.dns 2.2.2.2

    然后nmcli connection up home-eth1来使其生效
    删除新增网卡:
    nmcli connection down home-eth1
    nmcli connection del home-eth1
    nmcli connection show来查看是否删除
    (3)修改配置文件执行生效
    systemctl restart network 或是 nmcli con reload 
    nmcli命令生效: nmcli con down eth0 ;nmcli con up eth0

(四)使用nmcli配置网络

NeworkManager是管理和监控网络设置的守护进程 
设备即网络接口,连接是对网络接口的配置。
一个网络接口 可有多个连接配置,但同时只有一个连接配置生效 

  • 显示所有包括不活动连接
    nmcli con show 
  • 显示所有活动连接
    nmcli con show –active 
  • 显示网络连接配置
    nmcli con show “System eth0“ 
  • 显示设备状态
    nmcli dev status
  • 显示网络接口属性 nmcli dev show eth0 
  • 创建新连接default,IP自动通过dhcp获取
    nmcli con add con-name default type Ethernet ifname eth0 
  • 删除连接 nmcli con del default 
  • 创建新连接static ,指定静态IP,不自动连接 nmcti con add con-name
    static ifname eth0 autoconnect no type Ethernet ip4 172.25.X.10/24
    gw4 172.25.X.254

(五)nmcli实现bonding

添加bonding接口
(1)nmcli con add type bond con-name mybond0 ifname mybond0 mode
active-backup
(2)添加从属接口 nmcli con add type bond-slave ifname ens7 master
mybond0 nmcli con add type bond-slave ifname ens3 master mybond0
注:如无为从属接口提供连接名,则该名称是接口名称加类型构成 
(3)要启动绑定,则必须首先启动从属接口 nmcli con up bond-slave-eth0
nmcli con up bond-slave-eth1 
(4) 启动绑定 nmcli con up mybond0

以实验来验证:

步骤:
(1)首先将两个网卡都在设定在一个网段(都是仅主机模式)
开始配置 ncmli connection add type bond con-name bond0 ifname bond0
mode active-backup(主备模式)

6165金沙总站 12

image.png

(2)使bond0生效——nmcli connection up bond0

6165金沙总站 13

image.png

(3)nmcli connection show——查看是否启用该配置网卡
(4)关联两个slave网卡——
nmcli connection add con-name bond0-slave1 type bond-slave ifname eth0
master bond0
nmcli connection add con-name bond0-slave2 type bond-slave ifname eth1
master bond0

6165金沙总站 14

image.png

(5)使网卡生效——nmcli connection up bond0-slave1 nmcli connection up
bond0-slave2
完成设置
cat /proc/net/bonding/bond0 来查看具体哪个网卡生效
删除bond0网卡方法
(1)禁用网卡 nmcli connection down bond0
nmcli connection delete bond0
nmcli connection show-来查看是否删除
nmcli connection delete bond0-slave1
nmcli connection delete bond0-slave2
nmcli connection reload——同步
nmcli connection show-做最后的确认

(六)网络组Network Teaming

(1)网络组:是将多个网卡聚合在一起方法,从而实现冗错和提 高吞吐量 
网络组不同于旧版中bonding技术,提供更好的性能和扩展性 
网络组由内核驱动和teamd守护进程实现. 
多种方式runner
broadcast
roundrobin
activebackup
loadbalance
lacp (implements the 802.3ad Link Aggregation Control Protocol)
(2)启动网络组接口不会自动启动网络组中的port接口 ——nmcil connection up
team0时,网络组中的port接口没有启动
启动网络组接口中的port接口总会自动启动网络组接口 ——nmcli connection up
team-slave-eth0,此时网络组接口也会启动
禁用网络组接口会自动禁用网络组中的port接口——nmcli connectiion down
team0,网络组的port接口也会被禁用
没有port接口的网络组接口可以启动静态IP连接 
启用DHCP连接时,没有port接口的网络组会等待port接 口的加入
(3)创建网络组接口
nmcli con add type team con-name CNAME ifname INAME [config JSON]
CNAME 连接名,INAME 接口名 JSON 指定runner方式 格式:'{“runner”:
{“name”: “METHOD”}}’ METHOD 可以是broadcast, roundrobin, activebackup,
loadbalance, lacp
(4)创建port接口
nmcli con add type team-slave con-name CNAME ifname INAME master TEAM
CNAME 连接名 INAME 网络接口名 TEAM 网络组接口名 
连接名若不指定,默认为team-slave-IFACE nmcli dev dis INAME nmcli con
up CNAME INAME 设备名 CNAME 网络组接口名或port接口
(5)网络组示例
nmcli con add type team con-name team0 ifname team0 config ‘{“runner”:
{“name”: “loadbalance”}}’ 
nmcli con mod team0 ipv4.addresses 192.168.1.100/24 
nmcli con mod team0 ipv4.method manual 
nmcli con add con-name team0-eth1 type team-slave ifname eth1 master
team0 nmcli con add con-name team0-eth2 type team-slave ifname eth2
master team0 nmcli con up team0 
nmcli con up team0-eth1 
nmcli con up team0-eth2 
teamdctl team0 state; nmcli dev dis eth1
实验:创建网络组
ip link nmcli con add type team con-name team0 ifname team0 config
‘{“runner”: {“name”: “activebackup”}}’ 
nmcli con mod team0 ipv4.addresses ‘192.168.0.100/24’ 
nmcli con mod team0 ipv4.method manual 
nmcli con add con-name team0-port1 type team-slave ifname eth1 master
team0 nmcli con add con-name team0-port2 type team-slave ifname eth2
master team0 teamdctl team0 state
ping -I team0 192.168.0.254 
nmcli dev dis eno1 
teamdctl team0 state 
nmcli con up team0-port1 
nmcli dev dis eno2 
teamdctl team0 state 
nmcli con up team0-port2 
teamdctl team0 state
(5)管理网络组配置文件/etc/sysconfig/network-scripts/ifcfg-team0
DEVICE=team0
DEVICETYPE=Team
TEAM_CONFIG=”{“runner”: {“name”: “broadcast”}}”
BOOTPROTO=none
IPADDR0=172.25.5.100
PREFIX0=24
NAME=team0
ONBOOT=yes
/etc/sysconfig/network-scripts/ifcfg-team0-eth1
DEVICE=eth1
DEVICETYPE=TeamPort
TEAM_MASTER=team0
NAME=team0-eth1
ONBOOT=yes

                                          ## 实验练习

创建一个网络组,runner方式为broadcast,手动添加网址
步骤
nmcli connection add type team con-name team0 ifname team0 config
‘{“runner”:{“name”:”broadcast”}}’
nmcli conection modify team0 ipv4.adresses 192.168.136.176/24
ipv4.method manual
添加port接口
nmcli connection add type team-salve con-name team-slave0-eth1 ifname
team-slave-eth1 master team0
nmcli connection add type team-salve con-name team-slave0-eth0 ifname
team-slave-eth0 master team0
ping 192.168.136.176
teamdctl team0 state
删除网络组
nmcli connection down team0
nmcli connection delete team0
nmcli connection delet team-slave0-eth1
nmcli connection delet team-slave0-eth0
nmcli connection reload

二.网桥

(1)概念:
桥接:把一台机器上的若干个网络接口“连接”起来。其结
果是,其中一个网口收到的报文会被复制给其他网口并发送
出去。以使得网口之间的报文能够互相转发。网桥就是这样
一个设备,它有若干个网口,并且这些网口是桥接起来的。
与网桥相连的主机就能通过交换机的报文转发而互相通信。 
主机A发送的报文被送到交换机S1的eth0口,由于eth0与
eth1、eth2桥接在一起,故而报文被复制到eth1和eth2,并
且发送出去,然后被主机B和交换机S2接收到。而S2又会将 报文转发给主机C、D。

6165金沙总站 15

image.png

(2)配置实现网桥
配置原理和bonding和网络组的创建类似,具体配置过程如下:
nmcli connection add type briage con-name brg0 ifname brg0
nmcli connection modify br0 ipv4.addresses 192.168.38.100/24
ipv4.method manuall
nmcli con add type bridge-slave con-name br0-slave0-eth1 ifname eth1
master br0
nmcli con add type bridge-slave con-name br0-slave0-eth0 ifname
eth10master br0
查看配置情况
cat /etc/sysconfig/network-scripts/ifcfg-br0
cat /etc/sysconfig/network-scripts/ifcfg-br0-port0
brctl show
删除网桥
首先禁用网卡,然后删除网卡brctl delbr br0 
删除网桥中网卡 brctl delif eth0 
注意:NetworkManager只支持以太网接口接口连接到网桥,不支 持聚合接口

三测试网络工具

(1)在命令行下测试网络的连通性 
显示主机名 hostname 
测试网络连通性 ping mtr 
显示正确的路由表 ip route 
确定名称服务器使用: nslookup  host  dig 
跟踪路由 • traceroute • tracepath
(2)网络客户端工具
ftp,lftp
子命令:get、 mget、ls、help
lftp [-p port] [-u user[,password]] SERVER 
lftpget URL 
wget [option]… [URL]…
-q: 静默模式 -c: 断点续传 -O: 保存位置 –limit-rate=:
指定传输速率,单位K,M等 links URL –dump –source