高并发编程-3 负载均衡-Nginx-HAProxy-LVS
2022-10-10 00:00:00

这篇文章不会过多介绍这几个代理,毕竟在网上可以搜到很多它们的优劣对比和适用场景,只要看几篇文章就可以初步了解。此处更专注于在高并发场景下它们的发挥和配置,而且只针对HTTP和TCP。

Nginx

Nginx是我最先接触的,也是相对来说最熟悉的,可以用来部署一个静态WEB网站,最多的应该是用来当反向代理,提供负载均衡的服务。
Nginx的性能是非常高的,一个普通的服务器部署静态页面单机就可以几万QPS,要想再进一步提高性能,可以参考以下几个方面:

系统调优

可以看前面的文章 《Linux系统调优》对系统参数做适当调整。

配置调优

经过系统调优可以确保系统的高并发,但是对于Nginx来说,还需要修改nginx.conf 主要配置文件里面的参数。

  1. worker_processes 可以调整工作进程数,工作进程数不是越多越好,当和CPU核数相同时可以充分利用CPU,但是我建议不要这样配置,而是空闲一部分CPU用来保持其他进程的正常使用。 比如8核CPU可以配置6或者4,这样Nginx最多也就占用75%的CPU。
  2. worker_cpu_affinity 可以调整CPU亲和力,让不同的工作进程绑定到不同的核。这个地方就涉及到系统中断的概念了,参考上一篇《软中断》,可以尝试将工作的CPU绑定到软中断核或者避开软中断,再测试性能,这个比较我没测试过,而HAProxy中是推荐和网卡中断绑定到同一个CPU,不同的核上面。
  3. event 部分
  • worker_connections 单个工作进程可以允许同时建立外部连接的数量,无论这个连接是外部主动建立的,还是内部建立的,这个数量会受到操作系统的最大文件数限制,一个TCP连接就相当于一个文件,如果进行了系统参数调优则直接修改就行,否则要先调整系统参数,这个数量可以调大一些,比如10240,65535之类,具体的数值要经过测试才会合理。
  1. http 部分
  • keepalive_timeout 指定每个 TCP 连接最多可以保持多长时间,可以设置为60,75之类的,不要设置过大的数据,也不能太短,既要避免TCP连接过长时间不释放占用资源,也要避免过快关闭连接导致重新建立连接消耗资源。
  1. server 部分
  • proxy_set_header Connection “”; 这个设置也很重要,作用是将http请求头Connection置空,不会传给真实后端服务器(上游服务器),因为proxy_set_header Connection 默认是’close’,会关闭长连接,也就是说客户端发的请求到了nginx是正常的,但是nginx和真实后端的http通信都是短连接,这个是很耗费性能的,而且由于此时nginx相当于客户端,还会受到端口数限制,高并发情况会产生大量连接,会有很多time_wait状态的TCP链接。proxy_http_version 1.1; 也需要设置。
  1. upstream 部分
  • keepalive 开启与真实后端服务器(上游服务器)之间的连接池, 其数值为每个nginx worker可以保持的最大连接数,默认不设置,这是一个连接池,也是为了保证nginx的长连接,减少资源消耗。

    上面只是写了需要注意的几个参数,还有一些调优的并没有写出来,比如GZIP压缩、缓存配置、fastcgi和限流等等。完整的配置可以随便搜一下,重点关注上面几个,然后再根据测试情况适当调整参数。

HAProxy

HAProxy也可以用来做负载均衡,但是不能做WEB server,是多线程模型,而Nginx是多进程的,虽然HA也支持多进程,但我测试发现有的时候多进程性能不如单进程好,而且HA会更多利用CPU内核操作,top命令可以看到内核占用百分比很大,相对Nginx来说性能差不多,可能会稍微好一点,但是不如Nginx模块丰富。

系统调优

参考Nginx提到的系统调优

配置调优

我用HAProxy来做四层代理,也就是TCP层,所以配置会少很多,不过用来做负载均衡要注意IP透传之类的,让后端可以拿到真实IP

  1. nbproc 配置进程数,建议配置一下进行测试,搭配cpu亲和绑定,有可能会提高性能,进程不要超过内核数,避免服务器满载。
  2. cpu-map 绑定进程和CPU内核,可以将进程绑定到网卡中断CPU的不同内核上,再配合性能测试调整
  3. maxconn 设定每个haproxy进程所接受的最大并发连接数,这个可以调大一些,几十万都可以
  4. balance 负载均衡方式,可以通过业务情况调整

LVS

lvs已经在内核里面了,性能非常高,虽然这三个都支持4层负载均衡,但是LVS是不一样的。LVS支持DR、NAT、隧道、FULLNAT模式。

  • DR模式:通过改写请求报文的目标MAC地址,将请求发送给真实服务器,而真实服务器将相应后的处理结果直接返还给客户端用户。极大地提高集群的伸缩性,但LB与RS必须在同一局域网环境。
  • NAT模式:通过网络地址转换,LB重写请求报文的目标地址,根据预设的调度算法,将请求分派给后端的真实服务器,真实服务器的响应报文处理之后,返回时必须通过LB,经过LB时报文的源地址被重写,再返回给客户。
  • 隧道模式:LB把请求的报文通过IP隧道转发至真实服务器,而真实服务器将响应处理后直接返回给客户端用户。
  • FULLNAT模式:数据包进入时,除了做DNAT,还做SNAT,从而实现LVS-RealServer间可以跨vlan通讯,RealServer只需要连接到内网。

从中可以看出除了隧道模式,其他的都是修改数据包中IP、MAC之类的操作,隧道模式是再封装一层,就像VPN一样,这就和Nginx之类有了一个很大区别:不用建立TCP连接,也就不用维护TCP,这样就能节省很多资源,继而提升性能。所以LVS性能要高与HAProxy和Nginx,但是LVS也有一些局限性,需要根据具体场景做取舍。

LVS不需要调优就有很高性能,当然支持网卡多队列,多核处理网卡中断会更好,如果想要有更高的性能,可以去搜一下DPDK。