Linux 系统 nginx 服务器安装及负载均衡配置详解

nginx(engine x) 是一个高性能的 HTTP 和反向代理服务器、邮件代理服务器以及通用的 TCP/UDP 代理服务器。其特点为轻量级(占用系统资源少)、稳定性好、可扩展性(模块化结构)、并发能力强、配置简单等。
本文主要介绍在测试环境中通过 nginx 实现基本的负载均衡功能。

nginx 可以提供 HTTP 服务,包括处理静态文件,支持 SSL 和 TLS SNI、GZIP 网页压缩、虚拟主机、URL 重写等功能,可以搭配 FastCGI、uwsgi 等程序处理动态请求。

此外,nginx 还可以用于代理、反向代理、负载均衡、缓存等服务器功能,在集群环境中改善网络负载、提高可用性。

一、搭建测试环境

这里的测试环境为通过 VirtualBox 安装的两台 Lubuntu 19.04 虚拟机,Linux 系统安装方法不作赘述。
为了保证两台 Linux 虚拟机之间的相互访问,虚拟机的网络配置除了默认的 NAT 方式外,还使用了 VirtualBox 软件提供的 内部网络(Internal) 联网方式。
此外,还需要将两台虚拟机中与“内部网络”相关联的网卡,绑定上同一网段的静态 IP 地址,则两台主机形成局域网络,相互之间可以直接访问。

网络配置

打开 VirtualBox 软件,分别进入两台虚拟机的设置界面,为其添加连接方式为内部网络的网络连接,截图如下(两台虚拟机作同样的配置):

内部网络

登录进虚拟机系统,使用 ip addr 命令查看当前的网络连接信息:

$ ip addr
...
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:38:65:a8 brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic noprefixroute enp0s3
       valid_lft 86390sec preferred_lft 86390sec
    inet6 fe80::9a49:54d3:2ea6:1b50/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:0d:0b:de brd ff:ff:ff:ff:ff:ff
    inet6 fe80::2329:85bd:937e:c484/64 scope link noprefixroute
       valid_lft forever preferred_lft forever

可以看到,此时的 enp0s8 网卡还没有绑定 IPv4 地址,需要为其手动指定静态 IP。
需要注意的是,从 Ubuntu 17.10 版本开始,一个新的名为 netplan 的工具被引入,原来的网络配置文件 /etc/network/interfaces 不再生效。

所以为网卡设置静态 IP 时需要修改 /etc/netplan/01-network-manager-all.yaml 配置文件,示例如下:

network:
  version: 2
  renderer: NetworkManager
    ethernets:
    enp0s8:
      dhcp4: no
      dhcp6: no
      addresses: [192.168.1.101/24]
#      gateway4: 192.168.1.101
#      nameservers:
#          addresses: [192.168.1.101, 8.8.8.8]

由于两台主机处于同一子网,网关和 DNS 服务器未配置的情况下仍可以互相访问。对应的配置项暂时先注释掉(后续可以尝试自行搭建 DNS 服务器)。

编辑完成后运行 sudo netplan apply 命令,前面配置的静态 IP 即可生效。

$ ip addr
...
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:0d:0b:de brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.101/24 brd 192.168.1.255 scope global noprefixroute enp0s8
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe0d:bde/64 scope link
       valid_lft forever preferred_lft forever

登录进另一台虚拟机中,执行同样的操作(注意配置文件中的 addresses 项改为 [192.168.1.102/24])。两台虚拟机的网络即配置完成。

此时有 Linux 虚拟机 server1,IP 地址为 192.168.1.101;Linux 虚拟机 server2,IP 地址为 192.168.1.102。两台主机可相互访问。测试如下:

starky@server1:~$ ping 192.168.1.102 -c 2
PING 192.168.1.102 (192.168.1.102) 56(84) bytes of data.
64 bytes from 192.168.1.102: icmp_seq=1 ttl=64 time=0.951 ms
64 bytes from 192.168.1.102: icmp_seq=2 ttl=64 time=0.330 ms

--- 192.168.1.102 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 2ms
rtt min/avg/max/mdev = 0.330/0.640/0.951/0.311 ms
skitar@server2:~$ ping 192.168.1.101 -c 2
PING 192.168.1.101 (192.168.1.101) 56(84) bytes of data.
64 bytes from 192.168.1.101: icmp_seq=1 ttl=64 time=0.223 ms
64 bytes from 192.168.1.101: icmp_seq=2 ttl=64 time=0.249 ms

--- 192.168.1.101 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 29ms
rtt min/avg/max/mdev = 0.223/0.236/0.249/0.013 ms

二、安装 nginx 服务器

nginx 的安装方式主要有两种:

  • 预编译的二进制程序。这是最简单和最快速的安装方式,各主流操作系统都可以通过包管理器(如 Ubuntu 的 apt-get)安装。此种方式会安装几乎所有的官方模块或插件。
  • 从源代码编译安装。这种方式相对于前者更加灵活,可以自行选择需要安装的模块或第三方插件。

本示例并没有特殊的需求,所以直接选择第一种安装方式。命令如下:

$ sudo apt-get update
$ sudo apt-get install nginx

安装成功后,通过 systemctl status nginx 命令查看 nginx 服务的运行状态:

$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: en
   Active: active (running) since Tue 2019-07-02 01:22:07 CST; 26s ago
     Docs: man:nginx(8)
 Main PID: 3748 (nginx)
    Tasks: 2 (limit: 1092)
   Memory: 4.9M
   CGroup: /system.slice/nginx.service
           ├─3748 nginx: master process /usr/sbin/nginx -g daemon on; master_pro
           └─3749 nginx: worker process

通过 curl -I 127.0.0.1 命令验证 Web 服务器是否可以正常访问:

$ curl -I 127.0.0.1
HTTP/1.1 200 OK
Server: nginx/1.15.9 (Ubuntu)
...

三、负载均衡配置

负载均衡(load-balancing)即按照一定的规则将负载分摊到多个操作单元上执行,从而提高服务的可用性和响应速度。
简单的示例图如下:

load-balancing

如某网站应用部署在多台主机构成的服务器集群上,负载均衡服务器位于终端用户和服务器集群之间,负责接收终端用户的访问流量,并根据一定的规则将用户访问分发给后端的服务器主机,从而提高在高并发状态下的响应速度。

负载均衡服务器

nginx 可以通过 upstream 选项配置负载均衡。这里使用虚拟机 server1 作为负载均衡服务器。
修改 serve1 上默认站点的配置文件(sudo vim /etc/nginx/sites-available/default),改为如下内容:

upstream backend {
    server 192.168.1.102:8000;
    server 192.168.1.102;
}

server {
    listen 80;

    location / {
        proxy_pass http://backend;
    }
}

基于测试的目的,当前只有两台虚拟机。server1(192.168.1.101)已经作为负载均衡服务器,所以使用 server2(192.168.1.102)作为应用服务器。
这里借助 nginx 的虚拟主机功能,分别将 192.168.1.102192.168.1.102:8000 “模拟”为两台不同的应用服务器。

应用服务器

修改 server2 上默认站点的配置文件(sudo vim /etc/nginx/sites-available/default),改为如下内容:

server {
        listen 80;

        root /var/www/html;

        index index.html index.htm index.nginx-debian.html;

        server_name 192.168.1.102;

        location / {
                try_files $uri $uri/ =404;
        }
}

/var/www/html 目录下创建 index.html 文件,作为 default 站点的 index 页面,内容如下:

<html>
    <head>
        <title>Index Page From Server1</title>
    </head>
    <body>
        <h1>This is Server1, Address 192.168.1.102.</h1>
    </body>
</html>

运行 sudo systemctl restart nginx 命令重启 nginx 服务,此时访问 http://192.168.1.102 即可获取刚刚创建的 index.html 页面:

$ curl 192.168.1.102
<html>
    <head>
        <title>Index Page From Server1</title>
    </head>
    <body>
        <h1>This is Server1, Address 192.168.1.102.</h1>
    </body>
</html>

配置“另一台主机”上的站点,在 server2 上创建 /etc/nginx/sites-available/server2 配置文件,内容如下:

server {
        listen 8000;

        root /var/www/html;

        index index2.html index.htm index.nginx-debian.html;

        server_name 192.168.1.102;

        location / {
                try_files $uri $uri/ =404;
        }
}

注意监听端口和 index 页面的配置变化。在 /var/www/html 目录下创建 index2.html 文件,作为 server2 站点的 index 页面,内容如下:

<html>
    <head>
        <title>Index Page From Server2</title>
    </head>
    <body>
        <h1>This is Server2, Address 192.168.1.102:8000.</h1>
    </body>
</html>

PS:为了测试目的,default 站点和 server2 站点配置在同一个主机 server2 上,且页面稍有不同。实际环境中通常将这两个站点配置在不同的主机上,且内容一致。

运行 sudo ln -s /etc/nginx/sites-available/server2 /etc/nginx/sites-enabled/ 命令启用刚刚创建的 server2 站点。
重启 nginx 服务,此时访问 http://192.168.1.102:8000 即可获取刚刚创建的 index2.html 页面:

$ curl 192.168.1.102:8000
<html>
    <head>
        <title>Index Page From Server2</title>
    </head>
    <body>
        <h1>This is Server2, Address 192.168.1.102:8000.</h1>
    </body>
</html>
负载均衡测试

回到负载均衡服务器即虚拟机 server1 上,其配置文件中设置的反向代理 URL 为 http://backend
由于未曾配置域名解析服务,无法将 URL http://backend 定位到正确的位置。

可以修改 server1 上的 /etc/hosts 文件,添加如下一条记录:
127.0.0.1 backend
即可将该域名解析到本地 IP ,完成对负载均衡服务器的访问。

重启 nginx 服务,在 server1 上访问 http://backend ,效果如下:

$ curl http://backend
<html>
    <head>
        <title>Index Page From Server1</title>
    </head>
    <body>
        <h1>This is Server1, Address 192.168.1.102.</h1>
    </body>
</html>
$ curl http://backend
<html>
    <head>
        <title>Index Page From Server2</title>
    </head>
    <body>
        <h1>This is Server2, Address 192.168.1.102:8000.</h1>
    </body>
</html>
$ curl http://backend
<html>
    <head>
        <title>Index Page From Server1</title>
    </head>
    <body>
        <h1>This is Server1, Address 192.168.1.102.</h1>
    </body>
</html>
$ curl http://backend
<html>
    <head>
        <title>Index Page From Server2</title>
    </head>
    <body>
        <h1>This is Server2, Address 192.168.1.102:8000.</h1>
    </body>
</html>

从输出中可以看出,server1 对负载均衡服务器 http://backend 的访问,完成了对应用服务器 server2 上两个 Web 站点的轮询,起到负载均衡的作用。

四、负载均衡方法

nginx 开源版本提供四种负载均衡的实现方式,简单介绍如下。

1. Round Robin

用户请求均匀地分配给后端服务器集群(可以通过 weight 选项设置轮询的权重),这是 nginx 默认使用的负载均衡方式:

upstream backend {
   server backend1.example.com weight=5;
   server backend2.example.com;
}
2. Least Connections

用户请求会优先转发给集群中当前活跃连接数最少的服务器。同样支持 weight 选项。

upstream backend {
    least_conn;
    server backend1.example.com;
    server backend2.example.com;
}
3. IP Hash

用户请求会根据客户端 IP 地址进行转发。即该方式意图保证某个特定的客户端最终会访问同一个服务器主机。

upstream backend {
    ip_hash;
    server backend1.example.com;
    server backend2.example.com;
}

4. Generic Hash

用户请求会根据一个自定义键值确定最终转发的目的地,该键值可以是字符串、变量或者组合(如源 IP 和端口号)。

upstream backend {
    hash $request_uri consistent;
    server backend1.example.com;
    server backend2.example.com;
}
权重

参考下面的示例配置:

upstream backend {
    server backend1.example.com weight=5;
    server backend2.example.com;
    server 192.0.0.1 backup;
}

默认权重(weight)为 1 。backup 服务器只有在所有其他服务器全部宕机的情况下才会接收请求。
如上面的示例,每 6 个请求会有 5 个转发给 backend1.example.com,1 个转发给 backend2.example.com。只有当 backend1 和 backend2 全部宕机时,192.0.0.1 才会接收并处理请求。

参考资料

HTTP Load Balancing

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容