草庐IT

用 HAProxy 实现网络流量的负载平衡

Jim O'connell 2023-03-28 原文


安装、配置和运行 HAProxy,在几个网络或应用服务器之间分配网络流量。


不是只有在一个大型公司工作才需要使用负载平衡器。你可能是一个业余爱好者,用几台树莓派电脑自我托管一个网站。也许你是一个小企业的服务器管理员;也许你确实在一家大公司工作。无论你的情况如何,你都可以使用 ​​HAProxy​​ 负载平衡器来管理你的流量。

HAProxy 被称为“世界上最快和使用最广泛的软件负载平衡器”。它包含了许多可以使你的应用程序更加安全可靠的功能,包括内置的速率限制、异常检测、连接排队、健康检查以及详细的日志和指标。学习本教程中所涉及的基本技能和概念,将有助于你使用 HAProxy 建立一个更强大的、远为强大的基础设施。

为什么需要一个负载平衡器?

负载平衡器是一种在几个网络或应用服务器之间轻松分配连接的方法。事实上,HAProxy 可以平衡任何类型的传输控制协议(​​TCP​​)流量,包括 RDP、FTP、WebSockets 或数据库连接。分散负载的能力意味着你不需要因为你的网站流量比谷歌大就购买一个拥有几十万 G 内存的大型网络服务器。

负载平衡器还为你提供了灵活性。也许你现有的网络服务器不够强大,无法满足一年中繁忙时期的峰值需求,你想增加一个,但只是暂时的。也许你想增加一些冗余,以防一个服务器出现故障。有了 HAProxy,你可以在需要时向后端池添加更多的服务器,在不需要时删除它们。

你还可以根据情况将请求路由到不同的服务器。例如,你可能想用几个缓存服务器(如 ​​Varnish​​)来处理你的静态内容,但把任何需要动态内容的东西,如 API 端点,路由到一个更强大的机器。

在这篇文章中,我将通过设置一个非常基本的 HAProxy 环境,使用 HTTPS 来监听安全端口 443,并利用几个后端 Web 服务器。它甚至会将所有进入预定义 URL(如 ​​/api/​​)的流量发送到不同的服务器或服务器池。

安装 HAProxy

要开始安装,请启动一个新的 CentOS 8 服务器或实例,并使系统达到最新状态:

$ sudo yum update -y
这通常会持续一段时间。在等待的时候给自己拿杯咖啡。

这个安装有两部分:第一部分是安装 yum 版本的 HAProxy,第二部分是编译和安装你的二进制文件,用最新的版本覆盖以前的 HAProxy。用 yum 安装,在生成 systemd 启动脚本等方面做了很多繁重的工作,所以运行 ​​yum install​​,然后从源代码编译,用最新的版本覆盖 HAProxy 二进制:

$ sudo yum install -y haproxy
启用 HAProxy 服务:

$ sudo systemctl enable haproxy
要升级到最新版本(​​版本 2.2​​,截至本文写作为止),请编译源代码。许多人认为从源代码编译和安装一个程序需要很高的技术能力,但这是一个相当简单的过程。首先,使用 ​​yum​​ 安装一些提供编译代码工具的软件包:

$ sudo yum install dnf-plugins-core
$ sudo yum config-manager --set-enabled PowerTools
$ sudo yum install -y git ca-certificates gcc glibc-devel \
lua-devel pcre-devel openssl-devel systemd-devel \
make curl zlib-devel

使用 ​​git​​ 获得最新的源代码,并改变到 ​​haproxy​​ 目录:

$ git clone http://git.haproxy.org/git/ haproxy
$ cd haproxy

运行以下三个命令来构建和安装具有集成了 Prometheus 支持的 HAProxy:

$ make TARGET=linux-glibc USE_LUA=1 USE_OPENSSL=1 USE_PCRE=1 \
PCREDIR= USE_ZLIB=1 USE_SYSTEMD=1 \
EXTRA_OBJS="contrib/prometheus-exporter/service-prometheus.o"

$ sudo make PREFIX=/usr install # 安装到 /usr/sbin/haproxy

通过查询版本来测试它:

$ haproxy -v
你应该看到以下输出:

HA-Proxy version 2.2.4-b16390-23 2020/10/09 - https://haproxy.org/

创建后端服务器

HAProxy 并不直接提供任何流量,这是后端服务器的工作,它们通常是网络或应用服务器。在这个练习中,我使用一个叫做 ​​Ncat​​ 的工具,它是网络领域的“瑞士军刀”,用来创建一些极其简单的服务器。安装它:

$ sudo yum install nc -y
如果你的系统启用了 ​​SELinux​​,你需要启用端口 8404,这是用于访问 HAProxy 统计页面的端口(下面有解释),以及你的后端服务器的端口:

$ sudo dnf install policycoreutils-python-utils
$ sudo semanage port -a -t http_port_t -p tcp 8404
$ sudo semanage port -a -t http_port_t -p tcp 10080
$ sudo semanage port -a -t http_port_t -p tcp 10081
$ sudo semanage port -a -t http_port_t -p tcp 10082

创建两个 Ncat 网络服务器和一个 API 服务器:

$ while true ;
do
nc -l -p 10080 -c 'echo -e "HTTP/1.1 200 OK\n\n This is Server ONE"' ;
done &

$ while true ;
do
nc -l -p 10081 -c 'echo -e "HTTP/1.1 200 OK\n\n This is Server TWO"' ;
done &

$ while true ;
do
nc -l -p 10082 -c 'echo -e "HTTP/1.1 200 OK\nContent-Type: application/json\n\n { \"Message\" :\"Hello, World!\" }"' ;
done &

这些简单的服务器打印出一条信息(如“This is Server ONE”),并运行到服务器停止为止。在现实环境中,你会使用实际的网络和应用程序服务器。

修改 HAProxy 的配置文件

HAProxy 的配置文件是 ​​/etc/haproxy/haproxy.cfg​​。你在这里进行修改以定义你的负载平衡器。这个 ​​基本配置​​ 将让你从一个工作的服务器开始:

global
log 127.0.0.1 local2
user haproxy
group haproxy

defaults
mode http
log global
option httplog

frontend main
bind *:80

default_backend web
use_backend api if { path_beg -i /api/ }

#-------------------------
# SSL termination - HAProxy handles the encryption.
# To use it, put your PEM file in /etc/haproxy/certs
# then edit and uncomment the bind line (75)
#-------------------------
# bind *:443 ssl crt /etc/haproxy/certs/haproxy.pem ssl-min-ver TLSv1.2
# redirect scheme https if !{ ssl_fc }

#-----------------------------
# Enable stats at http://test.local:8404/stats
#-----------------------------

frontend stats
bind *:8404
stats enable
stats uri /stats
#-----------------------------
# round robin balancing between the various backends
#-----------------------------

backend web
server web1 127.0.0.1:10080 check
server web2 127.0.0.1:10081 check

#-----------------------------

# API backend for serving up API content
#-----------------------------
backend api
server api1 127.0.0.1:10082 check

重启并重新加载 HAProxy

HAProxy 可能还没有运行,所以发出命令 ​​sudo systemctl restart haproxy​​ 来启动(或重新启动)它。“重启” 的方法在非生产情况下是很好的,但是一旦你开始运行,你要养成使用 ​​sudo systemctl reload haproxy​​ 的习惯,以避免服务中断,即使你的配置中出现了错误。

例如,当你对 ​​/etc/haproxy/haproxy.cfg​​ 进行修改后,你需要用 ​​sudo systemctl reload haproxy​​ 来重新加载守护进程,使修改生效。如果有错误,它会让你知道,但继续用以前的配置运行。用 ​​sudo systemctl status haproxy​​ 检查 HAProxy 的状态。

如果它没有报告任何错误,你就有一个正在运行的服务器。在服务器上用 ​​curl​​ 测试,在命令行输入 ​​curl http://localhost/​​。如果你看到 “This is Server ONE”,那就说明一切都成功了!运行 ​​curl​​ 几次,看着它在你的后端池中循环,然后看看当你输入 ​​curl http://localhost/api/​​ 时会发生什么。在 URL 的末尾添加 ​​/api/​​ 将把所有的流量发送到你池子里的第三个服务器。至此,你就有了一个正常运作的负载平衡器

检查你的统计资料

你可能已经注意到,配置中定义了一个叫做 ​​stats​​ 的前端,它的监听端口是 8404:

frontend stats
bind *:8404
stats uri /stats
stats enable

在你的浏览器中,加载 ​​http://localhost:8404/stats​​。阅读 HAProxy 的博客 ​​学习 HAProxy 的统计页面​​,了解你在这里可以做什么。

一个强大的负载平衡器

虽然我只介绍了 HAProxy 的几个功能,但你现在有了一个服务器,它可以监听 80 和 443 端口,将 HTTP 流量重定向到 HTTPS,在几个后端服务器之间平衡流量,甚至将匹配特定 URL 模式的流量发送到不同的后端服务器。你还解锁了非常强大的 HAProxy 统计页面,让你对你的系统有一个很好的概览。

这个练习可能看起来很简单,不要搞错了,你刚刚建立和配置了一个非常强大的负载均衡器,能够处理大量的流量。

为了你方便,我把本文中的所有命令放在了 ​​GitHub Gist​​ 中。

有关用 HAProxy 实现网络流量的负载平衡的更多相关文章

  1. ruby - 匹配未转义的平衡定界符对 - 2

    如何匹配未被反斜杠转义的平衡定界符对(其本身未被反斜杠转义)(无需考虑嵌套)?例如对于反引号,我试过了,但是转义的反引号没有像转义那样工作。regex=/(?!$1:"how\\"#expected"how\\`are"上面的正则表达式不考虑由反斜杠转义并位于反引号前面的反斜杠,但我愿意考虑。StackOverflow如何做到这一点?这样做的目的并不复杂。我有文档文本,其中包括内联代码的反引号,就像StackOverflow一样,我想在HTML文件中显示它,内联代码用一些spanMaterial装饰。不会有嵌套,但转义反引号或转义反斜杠可能出现在任何地方。

  2. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  3. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  4. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  5. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  6. 网络编程套接字 - 2

    网络编程套接字网络编程基础知识理解源`IP`地址和目的`IP`地址理解源MAC地址和目的MAC地址认识端口号理解端口号和进程ID理解源端口号和目的端口号认识`TCP`协议认识`UDP`协议网络字节序socket编程接口`sockaddr``UDP`网络程序服务器端代码逻辑:需要用到的接口服务器端代码`udp`客户端代码逻辑`udp`客户端代码`TCP`网络程序服务器代码逻辑多个版本服务器单进程版本多进程版本多线程版本线程池版本服务器端代码客户端代码逻辑客户端代码TCP协议通讯流程TCP协议的客户端/服务器程序流程三次握手(建立连接)数据传输四次挥手(断开连接)TCP和UDP对比网络编程基础知识

  7. MIMO-OFDM无线通信技术及MATLAB实现(1)无线信道:传播和衰落 - 2

     MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO

  8. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  9. ruby - Arrays Sets 和 SortedSets 在 Ruby 中是如何实现的 - 2

    通常,数组被实现为内存块,集合被实现为HashMap,有序集合被实现为跳跃列表。在Ruby中也是如此吗?我正在尝试从性能和内存占用方面评估Ruby中不同容器的使用情况 最佳答案 数组是Ruby核心库的一部分。每个Ruby实现都有自己的数组实现。Ruby语言规范只规定了Ruby数组的行为,并没有规定任何特定的实现策略。它甚至没有指定任何会强制或至少建议特定实现策略的性能约束。然而,大多数Rubyist对数组的性能特征有一些期望,这会迫使不符合它们的实现变得默默无闻,因为实际上没有人会使用它:插入、前置或追加以及删除元素的最坏情况步骤复

  10. ruby - "public/protected/private"方法是如何实现的,我该如何模拟它? - 2

    在ruby中,你可以这样做:classThingpublicdeff1puts"f1"endprivatedeff2puts"f2"endpublicdeff3puts"f3"endprivatedeff4puts"f4"endend现在f1和f3是公共(public)的,f2和f4是私有(private)的。内部发生了什么,允许您调用一个类方法,然后更改方法定义?我怎样才能实现相同的功能(表面上是创建我自己的java之类的注释)例如...classThingfundeff1puts"hey"endnotfundeff2puts"hey"endendfun和notfun将更改以下函数定

随机推荐