如何使用 HAProxy 在 Ubuntu VPS 上设置 HTTP 负载平衡

2023-11-20

关于HAProxy


HAProxy(高可用性代理)是一个开源负载均衡器,可以对任何 TCP 服务进行负载均衡。它特别适合 HTTP 负载平衡,因为它支持会话持久性和第 7 层处理。

与数字海洋专用网络,HAProxy 可以配置为前端,通过专用网络连接对两个 VPS 进行负载平衡。

Prelude


我们将在这里使用三个 VPS(Droplet):

Droplet 1 - 负载均衡器 主机名:haproxy 操作系统:Ubuntu 公共IP:1.1.1.1 私有IP:10.0.0.100

Droplet 2 - 节点 1 主机名:lamp1 操作系统:Ubuntu 上的 LAMP 私有IP:10.0.0.1

Droplet 2 - 节点 2 主机名:lamp2 操作系统:Ubuntu 上的 LAMP 私有IP:10.0.0.2

安装HAProxy


Use the apt-get命令安装 HAProxy。

apt-get install haproxy

我们需要启用 HAProxy 由 init 脚本启动。

nano /etc/default/haproxy

Set the ENABLED选项1

ENABLED=1

要检查此更改是否正确完成,请执行不带任何参数的 HAProxy 初始化脚本。您应该看到以下内容。

root@haproxy:~# service haproxy
Usage: /etc/init.d/haproxy {start|stop|reload|restart|status}

配置HAProxy


我们将移动默认配置文件并创建我们自己的配置文件。

mv /etc/haproxy/haproxy.cfg{,.original}

创建并编辑新的配置文件:

nano /etc/haproxy/haproxy.cfg

让我们首先将配置逐块添加到此文件中:

global
	log 127.0.0.1 local0 notice
	maxconn 2000
	user haproxy
	group haproxy

The log指令提到了日志消息将发送到的系统日志服务器。在 Ubuntu 上,rsyslog 已经安装并运行,但它不侦听任何 IP 地址。稍后我们将修改rsyslog的配置文件。

The maxconn指令指定前端并发连接数。默认值为2000并且应该根据您的 VPS 配置进行调整。

The user and group指令将 HAProxy 进程更改为指定的用户/组。这些不应该改变。

defaults
	log     global
	mode    http
	option  httplog
	option  dontlognull
	retries 3
	option redispatch
	timeout connect  5000
	timeout client  10000
	timeout server  10000

我们在本节中指定默认值。要修改的值是各种timeout指令。这connect选项指定等待 VPS 连接尝试成功的最长时间。

The client and server当客户端或服务器期望在 TCP 过程中确认或发送数据时,将应用超时。 HAProxy 建议设置client and server超时为相同的值。

The retries指令设置连接失败后在 VPS 上执行的重试次数。

The option redispatch在连接失败的情况下启用会话重新分配。因此,如果 VPS 出现故障,会话粘性就会被覆盖。

listen appname 0.0.0.0:80
	mode http
	stats enable
	stats uri /haproxy?stats
	stats realm Strictly\ Private
	stats auth A_Username:YourPassword
	stats auth Another_User:passwd
	balance roundrobin
	option httpclose
	option forwardfor
	server lamp1 10.0.0.1:80 check
	server lamp2 10.0.0.2:80 check

这包含前端和后端的配置。我们正在配置 HAProxy 以侦听端口 80appname这只是一个用于识别应用程序的名称。这stats指令启用连接统计页面并保护它HTTP 基本身份验证使用指定的凭据stats auth指示。

可以通过以下提到的 URL 查看此页面stats uri所以在这种情况下,它是http://1.1.1.1/haproxy?stats;该页面的演示可以是在这里查看.

The balance指令指定要使用的负载平衡算法。可用选项有循环赛(roundrobin), 静态循环 (static-rr), 最少连接 (leastconn), 来源 (source), URI (uri) 和 URL 参数 (url_param).

有关每个算法的信息可以从官方文档.

The server指令声明一个后端服务器,语法为:

server <name> <address>[:port] [param*]

我们在这里提到的名称将出现在日志和警报中。有许多参数该指令支持,我们将使用check and cookie本文中的参数。这check选项启用 VPS 上的运行状况检查,否则 VPS 处于 始终被认为可用。

完成配置后启动 HAProxy 服务:

service haproxy start

测试负载平衡和故障转移


要测试此设置,请在所有 Web 服务器(后端服务器 - 此处为 LAMP1 和 LAMP2)上创建一个 PHP 脚本。

/var/www/file.php

<?php
header('Content-Type: text/plain');
echo "Server IP: ".$_SERVER['SERVER_ADDR'];
echo "\nClient IP: ".$_SERVER['REMOTE_ADDR'];
echo "\nX-Forwarded-for: ".$_SERVER['HTTP_X_FORWARDED_FOR'];
?>

现在我们将使用curl 并多次请求该文件。

> curl http://1.1.1.1/file.php

Server IP: 10.0.0.1
Client IP: 10.0.0.100
X-Forwarded-for: 117.213.X.X

> curl http://1.1.1.1/file.php

Server IP: 10.0.0.2
Client IP: 10.0.0.100
X-Forwarded-for: 117.213.X.X

> curl http://1.1.1.1/file.php

Server IP: 10.0.0.1
Client IP: 10.0.0.100
X-Forwarded-for: 117.213.X.X

请注意此处 HAProxy 如何交替切换 LAMP1 和 LAMP2 之间的连接,这就是循环法的工作原理。我们在这里看到的客户端 IP 是负载均衡器的私有 IP 地址,X-Forwarded-For标题是你的IP。

要查看故障转移的工作原理,请转到 Web 服务器并停止该服务:

lamp1@haproxy:~#service apache2 stop

发送请求curl再次看看事情是如何运作的。

会话粘性


如果您的 Web 应用程序根据用户的登录会话提供动态内容(该应用程序不提供),则由于 VPS 之间的持续切换,访问者会遇到奇怪的情况。会话粘性可确保访问者坚持访问为其第一个请求提供服务的 VPS。这可以通过使用 cookie 标记每个后端服务器来实现。

我们将使用以下 PHP 代码来演示会话粘性的工作原理。

/var/www/session.php

<?php
header('Content-Type: text/plain');
session_start();
if(!isset($_SESSION['visit']))
{
        echo "This is the first time you're visiting this server";
        $_SESSION['visit'] = 0;
}
else
        echo "Your number of visits: ".$_SESSION['visit'];

$_SESSION['visit']++;

echo "\nServer IP: ".$_SERVER['SERVER_ADDR'];
echo "\nClient IP: ".$_SERVER['REMOTE_ADDR'];
echo "\nX-Forwarded-for: ".$_SERVER['HTTP_X_FORWARDED_FOR']."\n";
print_r($_COOKIE);
?>

这段代码创建了一个PHP会话并显示单个会话中的页面浏览量。

在此方法中,从 HAProxy 到客户端的所有响应都将包含Set-Cookie:标头以后端服务器的名称作为其 cookie 值。因此,客户端(Web 浏览器)将在其所有请求中包含此 cookie,HAProxy 将根据 cookie 值将请求转发到正确的后端服务器。

对于此方法,您需要添加cookie指令并修改server根据指令listen

   cookie SRVNAME insert
   server lamp1 10.0.0.1:80 cookie S1 check
   server lamp2 10.0.0.2:80 cookie S2 check

这会导致 HAProxy 添加一个Set-Cookie:带有名为 cookie 的标头SRVNAME其价值为S1 or S2基于哪个后端响应了请求。添加后重新启动服务:

service haproxy restart

and use curl检查这是如何工作的。

> curl -i http://1.1.1.1/session.php
HTTP/1.1 200 OK
Date: Tue, 24 Sep 2013 13:11:22 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.8
Set-Cookie: PHPSESSID=l9haakejnvnat7jtju64hmuab5; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 143
Connection: close
Content-Type: text/plain
Set-Cookie: SRVNAME=S1; path=/

This is the first time you're visiting this server
Server IP: 10.0.0.1
Client IP: 10.0.0.100
X-Forwarded-for: 117.213.X.X
Array
(
)

这是我们提出的第一个请求,LAMP1 回答了这个请求,我们可以看到Set-Cookie: SRVNAME=S1; path=/。现在,为了模拟 Web 浏览器对下一个请求执行的操作,我们使用以下方法将这些 cookie 添加到请求中:--cookie 范围的卷曲。

> curl -i http://1.1.1.1/session.php --cookie "PHPSESSID=l9haakejnvnat7jtju64hmuab5;SRVNAME=S1;"
HTTP/1.1 200 OK
Date: Tue, 24 Sep 2013 13:11:45 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.8
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 183
Connection: close
Content-Type: text/plain

Your number of visits: 1
Server IP: 10.0.0.1
Client IP: 10.0.0.100
X-Forwarded-for: 117.213.87.127
Array
(
    [PHPSESSID] => l9haakejnvnat7jtju64hmuab5
    [SRVNAME] => S1
)

> curl -i http://1.1.1.1/session.php --cookie "PHPSESSID=l9haakejnvnat7jtju64hmuab5;SRVNAME=S1;"
HTTP/1.1 200 OK
Date: Tue, 24 Sep 2013 13:11:45 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.8
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 183
Connection: close
Content-Type: text/plain

Your number of visits: 2
Server IP: 10.0.0.1
Client IP: 10.0.0.100
X-Forwarded-for: 117.213.87.127
Array
(
    [PHPSESSID] => l9haakejnvnat7jtju64hmuab5
    [SRVNAME] => S1
)

这两个请求均由 LAMP1 满足,并且会话得到正确维护。如果您希望 Web 服务器上的所有文件具有粘性,则此方法非常有用。


另一方面,如果您只希望特定 cookie 具有粘性,或者不想使用单独的 cookie 来实现会话粘性,则prefix选项适合您。

要使用此方法,请使用以下命令cookie指示:

cookie PHPSESSID prefix

The PHPSESSID可以替换为您自己的cookie名称。这server指令与之前的配置保持相同。

现在让我们看看这是如何工作的。

> curl -i http://1.1.1.1/session.php
HTTP/1.1 200 OK
Date: Tue, 24 Sep 2013 13:36:27 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.8
Set-Cookie: PHPSESSID=S1~6l2pou1iqea4mnhenhkm787o56; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 143
Content-Type: text/plain

This is the first time you're visiting this server
Server IP: 10.0.0.1
Client IP: 10.0.0.100
X-Forwarded-for: 117.213.X.X
Array
(
)

请注意如何server cookie S1是会话 cookie 的前缀。现在,让我们用这个 cookie 再发送两个请求。

> curl -i http://1.1.1.1/session.php --cookie "PHPSESSID=S1~6l2pou1iqea4mnhenhkm787o56;"
HTTP/1.1 200 OK
Date: Tue, 24 Sep 2013 13:36:45 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.8
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 163
Content-Type: text/plain

Your number of visits: 1
Server IP: 10.0.0.1
Client IP: 10.0.0.100
X-Forwarded-for: 117.213.X.X
Array
(
    [PHPSESSID] => 6l2pou1iqea4mnhenhkm787o56
)

> curl -i http://1.1.1.1/session.php --cookie "PHPSESSID=S1~6l2pou1iqea4mnhenhkm787o56;"
HTTP/1.1 200 OK
Date: Tue, 24 Sep 2013 13:36:54 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.8
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 163
Content-Type: text/plain

Your number of visits: 2
Server IP: 10.0.0.1
Client IP: 10.0.0.100
X-Forwarded-for: 117.213.X.X
Array
(
    [PHPSESSID] => 6l2pou1iqea4mnhenhkm787o56
)

我们可以清楚地看到,这两个请求均由 LAMP1 处理,并且会话运行良好。

为 HAProxy 配置日志记录


当我们开始配置 HAProxy 时,我们添加了一行:log 127.0.0.1 local0 notice它将系统日志消息发送到本地主机 IP 地址。但默认情况下,Ubuntu 上的 rsyslog 不会侦听任何地址。所以我们必须让它这样做。

编辑rsyslog的配置文件。

nano /etc/rsyslog.conf

添加/编辑/取消注释以下行:

$ModLoad imudp
$UDPServerAddress 127.0.0.1
$UDPServerRun 514

现在 rsyslog 将在地址 127.0.0.1 上的 UDP 端口 514 上工作,但所有 HAProxy 消息将发送至/var/log/syslog所以我们必须将它们分开。

为 HAProxy 日志创建规则。

nano /etc/rsyslog.d/haproxy.conf

将以下行添加到其中。

if ($programname == 'haproxy') then -/var/log/haproxy.log

现在重新启动 rsyslog 服务:

service rsyslog restart

这会将所有 HAProxy 消息和访问日志写入/var/log/haproxy.log.

HAProxy 中的 Keepalive


在下面listen指令,我们使用option httpclose这增加了一个Connection: close标头。这告诉客户端(Web 浏览器)在收到响应后关闭连接。

如果要在 HAProxy 上启用 keep-alives,请替换option httpclose符合:

option http-server-close
timeout http-keep-alive 3000

明智地设置保持活动超时,以便少数连接不会耗尽负载均衡器的所有资源。

测试保活

Keepalives 可以使用测试curl通过同时发送多个请求。以下示例将省略不必要的输出:

> curl -v http://1.1.1.1/index.html http://1.1.1.1/index.html
* About to connect() to 1.1.1.1 port 80 (#0)
*   Trying 1.1.1.1... connected
> GET /index.html HTTP/1.1
> User-Agent: curl/7.23.1 (x86_64-pc-win32) libcurl/7.23.1 OpenSSL/0.9.8r zlib/1.2.5
> Host: 1.1.1.1
> Accept: */*
>
......[Output omitted].........
* Connection #0 to host 1.1.1.1 left intact
* Re-using existing connection! (#0) with host 1.1.1.1
* Connected to 1.1.1.1 (1.1.1.1) port 80 (#0)
> GET /index.html HTTP/1.1
> User-Agent: curl/7.23.1 (x86_64-pc-win32) libcurl/7.23.1 OpenSSL/0.9.8r zlib/1.2.5
> Host: 1.1.1.1
> Accept: */*
>
.......[Output Omitted].........
* Connection #0 to host 1.1.1.1 left intact
* Closing connection #0

在此输出中,我们必须查找以下行:Re-using existing connection! (#0) with host 1.1.1.1,这表明curl使用相同的连接来发出后续请求。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 HAProxy 在 Ubuntu VPS 上设置 HTTP 负载平衡 的相关文章

随机推荐

  • 如何在 Ubuntu 18.04 上安装 Android Studio

    安卓工作室是一款功能齐全的跨平台 IDE 可帮助您在各种类型的 Android 设备上构建应用程序 它是基于JetBrains 的 IntelliJ IDEA并包含 Android 开发所需的一切 Android Studio 构建系统由G
  • 如何在 Debian 10 上安装 Python 3.9

    Python 是世界上最流行的编程语言之一 它是一种多功能语言 用于构建各种应用程序 从简单的脚本到复杂的机器学习算法 凭借其简单易学的语法 Python 成为初学者和经验丰富的开发人员的热门选择 Python 3 9 是 Python 语
  • 如何删除本地和远程 Git 分支

    分支是日常开发过程的一部分 也是 Git 中最强大的功能之一 一个分支一旦合并 除了历史研究之外就没有任何作用了 成功合并后删除分支是常见且推荐的做法 本指南介绍如何删除本地和远程 Git 分支 删除本地 Git 分支 The git br
  • Python 枚举函数

    enumerate 是 Python 中的一个内置函数 允许您在循环迭代时拥有一个自动计数器 Python enumerate 功能 The enumerate 函数采用以下形式 enumerate iterable start 0 该函数
  • 如何在 Ubuntu 18.04 上部署 Mattermost

    Mattermost 是一个企业级即时消息平台 是一个开源自托管 Slack 替代品 它是用 Golang 和 React 编写的 可以使用 MySQL 或 PostgreSQL 作为数据库后端 Mattermost 将您的所有团队沟通集中
  • 如何在 Ubuntu 18.04 上安装 OpenCart

    OpenCart是一个免费开源的 PHP 电子商务平台 将强大的功能与灵活性和用户友好的界面相结合 OpenCart 具有用户管理 多商店 附属机构 折扣 产品评论 多语言和多个支付网关等功能 是许多在线商家的首选平台 在本教程中 我们将向
  • 如何在 CentOS 7 上停止和禁用 Firewalld

    防火墙D是一个完整的防火墙解决方案 可动态管理网络连接和接口的信任级别 它使您可以完全控制允许或禁止进出系统的流量 从 CentOS 7 开始 FirewallD 取代 iptables 成为默认的防火墙管理工具 强烈建议保持 Firewa
  • 如何使用 Mysqldump 备份和恢复 MySQL 数据库

    本教程介绍如何使用 mysqldump 实用程序从命令行备份和恢复 MySQL 或 MariaDB 数据库 mysqldump 实用程序创建的备份文件基本上是一组可用于重新创建原始数据库的 SQL 语句 mysqldump 命令还可以生成
  • 如何在 Ubuntu 20.04 上安装 Spotify

    Spotify是一种数字音乐流媒体服务 可让您即时访问数百万首歌曲 从经典老歌到最新热门歌曲 本指南展示了在 Ubuntu 20 04 上安装 Spotify 的两种方法 Spotify 可以通过 Snapcraft 商店作为 snap 包
  • 如何在 Debian 9 上设置或更改时区

    使用正确的时区对于许多与系统相关的任务和流程都很重要 例如 cron 守护进程使用系统的时区来执行 cron 作业 并且日志文件中的时间戳基于同一系统的时区 系统的时区是在安装过程中设置的 但以后可以轻松更改 本教程展示如何在 Debian
  • 如何在 Ubuntu 20.04 上安装 VMware Workstation Player

    VMwareWorkstation Player 是一款桌面虚拟化软件 允许您在一台计算机上运行多个独立的操作系统 借助 VMware Player 您可以创建并运行自己的虚拟机 并评估由许多软件供应商提供的作为虚拟设备分发的软件VMwar
  • 如何在 CentOS 8 上设置 Apache 虚拟主机

    Apache 虚拟主机允许您在一台计算机上运行多个网站 使用虚拟主机 您可以指定站点文档根 包含网站文件的目录 为每个站点创建单独的安全策略 使用不同的 SSL 证书等等 本文介绍如何在 CentOS 8 服务器上设置 Apache 虚拟主
  • 如何在 Ubuntu 18.04 上安装 VLC 媒体播放器

    VLC 是最流行的开源多媒体播放器之一 它是跨平台的 几乎可以播放所有多媒体文件以及 DVD 音频 CD 和不同的流媒体协议 本教程介绍如何在 Ubuntu 18 04 上安装 VLC 媒体播放器 相同的说明适用于 Ubuntu 16 04
  • 如何在 CentOS 8 上安装和配置 Redis

    Redis 是一个开源内存键值数据存储 它可以用作数据库 缓存和消息代理 并支持各种数据结构 例如字符串 哈希 列表 集合等 Redis 通过 Redis Sentinel 提供高可用性 并通过 Redis Cluster 跨多个 Redi
  • 如何在Linux中删除组(groupdel命令)

    在 Linux 中 组用于组织和管理用户帐户 组的主要目的是定义一组权限 例如读 写或执行允许对于可以在组内的用户之间共享的给定资源 可以使用以下命令创建一个新组groupadd命令 如果不再需要某个组并且可以从系统中删除 本文介绍了如何在
  • Python 加入列表

    Python join list 的意思是将一串字符串与指定的分隔符连接起来形成一个字符串 有时 当您必须将列表转换为字符串时 它很有用 例如 将字母列表转换为逗号分隔的字符串以保存在文件中 Python 加入列表 我们可以用蟒蛇字符串jo
  • Java Hello World 程序

    每当我们开始学习一门编程语言时 第一个程序总是打印Hello World 在上一篇文章中 我们了解到如何在 Windows 10 上安装 Java 现在我们准备编写并运行我们的第一个 Hello World Java 程序 Java Hel
  • 从 Python 调用 C 函数

    我们可以使用 Python 程序调用 C 函数ctypes module 从 Python 调用 C 函数 它涉及以下步骤 创建具有所需函数的 C 文件 c 扩展名 使用 C 编译器创建共享库文件 so 扩展名 在 Python 程序中 从
  • Java中的迭代器设计模式

    迭代器设计模式中的行为模式之一 迭代器模式用于提供遍历一组对象的标准方法 迭代器模式广泛应用于Java集合框架 Iterator 接口提供了遍历集合的方法 迭代器设计模式 According to GoF iterator design p
  • 如何使用 HAProxy 在 Ubuntu VPS 上设置 HTTP 负载平衡

    关于HAProxy HAProxy 高可用性代理 是一个开源负载均衡器 可以对任何 TCP 服务进行负载均衡 它特别适合 HTTP 负载平衡 因为它支持会话持久性和第 7 层处理 与数字海洋专用网络 HAProxy 可以配置为前端 通过专用