个人随笔
目录
nginx-1.22.1在linux服务器上的安装和使用
2023-07-24 22:35:25

一、环境准备

1、gcc安装

安装 nginx 需要先将官网下载的源码进行编译,编译依赖 gcc 环境,如果没有 gcc 环境,则需要安装:

  1. yum install gcc gcc-c++

2、pcre pcre-devel 安装

PCRE(Perl Compatible Regular Expressions) 是一个Perl库,包括 perl 兼容的正则表达式库。Nginx的http 模块使用pcre来解析正则表达式,所以需要在Linux上安装pcre库,pcre-devel 是使用pcre开发的一个二次开发库。Nginx也需要此库。命令:

  1. yum install -y pcre pcre-devel

3、 zlib安装

zlib 库提供了很多种压缩和解压缩的方式, Nginx使用zlib对http包的内容进行gzip,所以需要在Linux Centos 7上安装zlib库。

  1. yum install -y zlib zlib-devel

4、openssl安装

OpenSSL是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用。
Nginx不仅支持http协议,还支持https(即在ssl协议上传输http),所以需要在Linux Centos 7安装OpenSSL库。

  1. yum install -y openssl openssl-devel

二、安装Nginx

1、下载

用wget命令下载(推荐)。确保系统已经安装了wget,如果没有安装,执行 yum install wget 安装。

  1. #下载,这里也可以去官网下载
  2. wget -c https://nginx.org/download/nginx-1.22.1.tar.gz
  3. #解压
  4. tar -zxf nginx-1.22.1.tar.gz -C ./
  5. cd nginx-1.22.1

2、检查配置并指定安装参数

  1. ./configure --prefix=/usr/local/nginx --conf-path=/usr/local/nginx/nginx.conf --with-http_stub_status_module --with-http_ssl_module
  • ./configure 是编译前检查的命令,
  • —prefix=/usr/local/nginx 是安装到指定目录,
  • —with-http_stub_status_module —with-http_ssl_module 是安装ssl证书的两个模块

3、编译安装

  1. make&&make install

4、操作

  1. #进入目录
  2. cd /usr/local/nginx/sbin/
  3. ./nginx #启动
  4. ./nginx -s quit # 此方式停止步骤是待nginx进程处理任务完毕进行停止。
  5. ./nginx -s stop # 此方式相当于先查出nginx进程id再使用kill命令强制杀掉进程。
  6. ./nginx -t #校验配置文件是否正确
  7. ./nginx -s reload #重新加载

5、查看进程

  1. ps -ef|grep nginx
  1. root 4337 1 0 06:13 ? 00:00:00 nginx: master process ./nginx
  2. nobody 4338 4337 0 06:13 ? 00:00:00 nginx: worker process
  3. root 4340 1494 0 06:13 pts/0 00:00:00 grep --color=auto nginx

6、关闭防火墙或者打开80端口

  1. 启动: systemctl start firewalld
  2. 停止: systemctl stop firewalld
  3. 查看所有打开的端口: firewall-cmd --permanent --list-port
  4. 开启端口:firewall-cmd --zone=public --add-port=80/tcp --permanent
  5. 关闭端口:firewall-cmd --zone=public --remove-port=80/tcp --permanent
  6. 更新防火墙规则: firewall-cmd --reload

我这里选择的是开启80端口

  1. 开启端口:firewall-cmd --zone=public --add-port=80/tcp --permanent
  2. firewall-cmd --reload
  1. [root@localhost sbin]# firewall-cmd --permanent --list-port
  2. 80/tcp

7、浏览器访问

这里我linux服务器的地址是192.168.192.11 ,访问

三、nginx使用

1、反向代理

所谓反向代理就是nginx接受到请求后,将请求转发给内部的一台服务器处理,比如我们启动了一个tomcat是8081端口,但是我们防火墙不会开放8081端口,只会开放nginx的80端口,那么我们需要再nginx上进行反向代理配置,让到80端口的请求转发给8081端口处理,这样安全性也有很大的提高,并且后续可以进行负载均衡:80端口进来,从代理的多台服务器按策略选一台处理。

1.1、8081端口服务搭建

我们这里就不启动tomcat来模拟服务了,直接在nginx上配置个8081端口的server即可,nginx配置文件做如下处理

  1. server {
  2. listen 8081;
  3. server_name localhost;
  4. location / {
  5. root html;
  6. index index8081.html index.htm;
  7. }
  8. error_page 500 502 503 504 /50x.html;
  9. location = /50x.html {
  10. root html;
  11. }
  12. }

这里的意思是,请求从8081进来,会返回index8081.html的页面,这个页面会在nginx目录下面的html里面,内容如下

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Welcome to nginx!</title>
  5. <style>
  6. html { color-scheme: light dark; }
  7. body { width: 35em; margin: 0 auto;
  8. font-family: Tahoma, Verdana, Arial, sans-serif; }
  9. </style>
  10. </head>
  11. <body>
  12. <h1>Welcome to 8081!</h1>
  13. </body>
  14. </html>

到这里就相当于有一个新的服务了。

1.2、nginx反向代理配置

下面我们来配置负载均衡,我们在nginx.conf的http配置里面新增upstream.

  1. upstream first {
  2. server localhost:8081;
  3. }

然后,在80的server进行代理配置

  1. server {
  2. listen 80;
  3. server_name localhost;
  4. location / {
  5. #反向代理配置
  6. proxy_pass http://first;
  7. proxy_set_header Host $host;
  8. proxy_set_header X-Real-IP $remote_addr;
  9. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  10. }
  11. }
1.3、重新启动nginx

我们可以先用-t命令校验下配置文件是否正确

  1. ./nginx -t

检查正确后,进行重新加载

  1. ./nginx -s reload
1.4、访问测试

我们访问80端口,然后可以看到返回了index8081.html的页面内容,表面反向代理成功。

1.5、proxy_set_header

我们看到,反向代理设置的时候,有进行proxy_set_header设置,那这个的作用是什么呢?

即允许重新定义或添加字段传递给代理服务器的请求头,简而言之,proxy_set_header 就是可设置请求头-并将头信息传递到服务器端,不属于请求头的参数中也需要传递时,重定义下即可!

主要有三个参数需要设置

Host

若客户端发过来的请求header中有HOST这个字段,$http_host和$host表示的就是原始请求

X-Real-IP

是指客户端的真实IP,如果设置了$remote_addr这个值,后端服务器就能获取到客户端的真实IP

X-Forwarded-For

这个变量的值有$proxy_add_x_forwarded_for,可以真实的显示出客户端原始ip。

我们这里来测试下

环境搭建

在本机搭建一个springboot应用,springboot应用搭建方法参考:从官网开始用IDEA在JDK1.8环境搭建springboot2.7.14项目,然后代码如下

  1. @RestController
  2. public class DemoController {
  3. @GetMapping("/hello")
  4. public Map<String,Object> hello(HttpServletRequest request){
  5. Map<String,Object> result = new TreeMap<String,Object>();
  6. result.put("hello","Hello World");
  7. String scheme = request.getScheme();
  8. String xForwardedFor = request.getHeader("X-Forwarded-For");
  9. String xRealIp = request.getHeader("X-Real-IP");
  10. String host = request.getHeader("Host");
  11. String serverName = request.getServerName();
  12. int serverPort = request.getServerPort();
  13. String remoteName = request.getRemoteAddr();
  14. int remotePort = request.getRemotePort();
  15. result.put("scheme",scheme);
  16. result.put("serverName",serverName);
  17. result.put("serverPort",serverPort);
  18. result.put("remoteName",remoteName);
  19. result.put("remotePort",remotePort);
  20. result.put("xForwardedFor",xForwardedFor);
  21. result.put("xRealIp",xRealIp);
  22. result.put("host",host);
  23. return result;
  24. }
  25. }

我本机的ip为:192.168.192.1
nginx所在的ip:192.168.192.11

nginx的反向代理的配置为

  1. upstream first {
  2. server 192.168.192.1:8080;
  3. }
  1. server {
  2. listen 80;
  3. server_name localhost;
  4. location / {
  5. proxy_pass http://first;
  6. #proxy_set_header Host $host;
  7. #proxy_set_header X-Real-IP $remote_addr;
  8. #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  9. }
  10. }

这样客户端通过访问nginx暴露的80服务就是反向代理到我本机启动的springboot应用。下面我们来测试proxy_set_header的作用

不配置proxy_set_header的测试

我们上面是把proxy_set_header都注释了,此时在浏览器上访问
http://192.168.192.11/hello
返回了

  1. {"hello":"Hello World","host":"first","remoteName":"192.168.192.11","remotePort":35058,"scheme":"http","serverName":"first","serverPort":80,"xForwardedFor":null,"xRealIp":null}

可以看到完全没有拿到任何客户端的信息.

配置proxy_set_header的测试
  1. server {
  2. listen 80;
  3. server_name localhost;
  4. location / {
  5. proxy_pass http://first;
  6. proxy_set_header Host $host;
  7. proxy_set_header X-Real-IP $remote_addr;
  8. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  9. }
  10. }

在浏览器上访问
http://192.168.192.11/hello
返回了

  1. {"hello":"Hello World","host":"192.168.192.11","remoteName":"192.168.192.11","remotePort":35060,"scheme":"http","serverName":"192.168.192.11","serverPort":80,"xForwardedFor":"192.168.192.1","xRealIp":"192.168.192.1"}

request.getRemoteAddr():获取的永远都是代理对象的IP
X-Forwarded-For和X-Real-IP:都获取了客户端的真实IP

X-Forwarded-For和X-Real-IP有什么区别呢

我们上面的例子发现,这两个获取的都是客户端的真实IP地址,其实如果只有一个反向代理服务器,那结果都是一样的,但是如果有多个,这里可以就用一个nginx来模拟一下。配置如下

我们首先在nginx配置一个服务,代理到我们的springboot应用.

  1. upstream second {
  2. server 192.168.192.1:8080;
  3. }
  1. server {
  2. listen 8081;
  3. server_name localhost;
  4. location / {
  5. proxy_pass http://second;
  6. proxy_set_header Host $http_host;
  7. proxy_set_header X-Real-IP $remote_addr;
  8. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  9. }
  10. error_page 500 502 503 504 /50x.html;
  11. location = /50x.html {
  12. root html;
  13. }
  14. }

这里相当于我们的应用被一个nginx服务器代理了,端口是8081,我们再配置一个80端口代理到8081,就模拟了两台代理服务器的情况

  1. upstream first {
  2. server localhost:8081;
  3. }
  1. server {
  2. listen 80;
  3. server_name localhost;
  4. location / {
  5. proxy_pass http://first;
  6. proxy_set_header Host $host;
  7. proxy_set_header X-Real-IP $remote_addr;
  8. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  9. }
  10. }

我们再尝试在本机的浏览器请求:http://192.168.192.11/hello,返回了

  1. {"hello":"Hello World","host":"192.168.192.11","remoteName":"192.168.192.11","remotePort":35086,"scheme":"http","serverName":"192.168.192.11","serverPort":80,"xForwardedFor":"192.168.192.1, 127.0.0.1","xRealIp":"127.0.0.1"}

可以看到X-Real-IP获取的就不是客户端的地址了,而是第一次代理发起的地址,但是我们的X-Forwarded-For却有全部的客户端IP地址,我们想要获取真实客户端,只需要获取X-Forwarded-For第一个即可。

总结:X-Forwarded-For记录服务器的地址,会把记录添加到结尾,X-Real-IP用来记录服务器的地址,它不把记录添加到结尾,而是直接替换。所以用X-Forwarded-For就不会错。

1.6、localtion匹配规则

location的使用语法规则如下

  1. location关键字 + 匹配方式符号(可省略)+匹配规则+如何处理

匹配方式符号可选有:= | ~ | ~* | ^~

  1. location [ = | ~ | ~* | ^~ ] uri { ... }

通常我们配置的时候会使用两种配置方式:普通匹配和正则匹配

1.6.1、普通匹配

普通匹配主要有如下三种配置方式

= : 这代表精准匹配全路径, 命中它后直接返回, 不再进行后续匹配, 优先级最高.

^~ : 这代表精准匹配开头, 命中开头后直接返回, 不再进行后续匹配, 优先级第二.

无匹配方式符号 : 这代表通用性匹配, 命中后还会继续后续匹配, 最后选取路径最长的匹配, 并储存起来, 优先级第四.

举例

  1. #这是精准匹配, 只有请求路径完全匹配`/hello.html`才会命中它
  2. location = /hello.html {
  3. ...
  4. }
  5. #这是精准匹配开头, 只要请求路径的开头是`/hello/`, 就会命中并立即返回
  6. location ^~ /hello/ {
  7. ...
  8. }
  9. #这是无匹配方式符号的普通匹配, 如果请求路径开头是`/hello/`, 则会命中, 但是不会立即返回还会接着进行普通匹配
  10. location /hello/ {
  11. ...
  12. }
  13. #这是无匹配方式符号的普通匹配, 如果请求路径开头是`/hello/a`, 则会命中, 但是不会立即返回还会接着进行普通匹配, 同时会舍弃掉上面那个匹配
  14. location /hello/a {
  15. ...
  16. }
  17. #我们通常配置的/也是无匹配方式符号的普通匹配
  18. location / {
  19. ...
  20. }
1.6.2、正则匹配

正则匹配有如下两种匹配模式

~: 这是区分大小写的正则匹配, 命中后则不进行后续匹配, 立即返回, 优先级第三.

~*: 不区分大小写的正则匹配, 命中后则不进行后续匹配, 立即返回, 优先级第三.

这里有个很重要点点, 也就是正则匹配中~和~*优先级一样, 它们按照从上到下的顺序进行匹配, 最先命中的立即返回, 后续的不会进行匹配, 所以精细的正则匹配规则往前放, 通用的正则匹配规则往后放.

举例

  1. #区分大小写的正则匹配, 如果路径包含 /a/ 则立即返回, 注意这里并不需要开头命中, 因为这是正则表达式
  2. location ~ /a/ {
  3. ...
  4. }
  5. #区分大小写的正则匹配, 如果路径包含 /A(不分大小写)/ 则立即返回, 注意这里并不需要开头命中, 因为这是正则表达式, 但由于上面一个正则匹配规则在前面, 所以如果路径包含 /A/ 则会被挡下来, 匹配不到这里.
  6. location *~ /A/ {
  7. ...
  8. }
1.6.3、正则表达式
  1. *:重复前面的字符0次或多次
  2. ?:重复前面的字符0次或1
  3. +:重复前面的字符1次或多次
  4. .:匹配除换行符以外的任意一个字符
  5. (a|b):匹配ab
  6. ^:以...开头
  7. $:以...结尾
  8. {n}:重复前面的字符n
  9. {n,}:重复前面的字符n次或更多次
  10. {nm}:重复前面的字符n-m
  11. *?:重复前面的字符0次或多次,但尽可能少重复
  12. +?:重复前面的字符1次或多次,但尽可能少重复
  13. ??:重复前面的字符0次或1次,但尽可能少重复
  14. {nm}?:重复前面的字符n-m次,但尽可能少重复
  15. {n}?:重复前面的字符n次以上,但尽可能少重复
1.6.4、正则表达式补充
  1. \W:匹配任意不是字母,数字,下划线,汉字的字符(特殊符号)
  2. \S:匹配任意不是空白符的字符
  3. \D:匹配任意非数字的字符
  4. \B:匹配任意不是单词开头或结尾的位置
  5. [a]:匹配单个字符a
  6. [a-z]:匹配a-z小写字符的任意一个
  7. [^a]:匹配除了a以外的任意字符
  8. [^abc]:匹配除了abc这几个字母以外的任意字符
1.6.5、正则表达式匹配举例
  1. #匹配所有以.jpg,.xml或者.txt结尾的请求
  2. location ~ \.(jpg|xml|txt)$ {
  3. proxy_pass http://first;
  4. proxy_set_header Host $http_host;
  5. proxy_set_header X-Real-IP $remote_addr;
  6. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  7. }
1.7、Rewrite

Rewrite主要的功能是实现URL重写,Nginx 的 Rewrite 规则采用 PCRE Perl 兼容正则表达式的语法进行规则匹配,如果使用 Nginx 的 Rewrite 功能,在编译 Nginx 前要编译安装 PCRE 库。Rewrite主要实现url地址重写,以及重定向,就是把传入web的请求重定向到其他url的过程。

1.7.1、rewrite介绍

rewrite和location的功能有点相像,都能实现跳转,主要区别在于rewrite常用于同一域名内更改获取资源的路径,而location是对一类路径做控制访问和反向代理,可以proxy_pass到其他服务器。

Nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现url重写以及重定向。

rewrite只能放在server{},location{},if{}中,

并且只能对域名后边的除去传递的参数外的字符串起作用。

1.7.2、rewrite语法

指令语法: rewrite regex(正则) replacement(替代内容) [flag](flag标记)

关键字:rewrite是实现URL重写的关键指令,不变
正则:perl兼容正则表达式语句进行规则匹配
替代内容:将正则匹配的内容替换成replacement
flag标记:rewrite支持的flag标记

应用位置:server、location、if

1.7.3、例子

rewrite ^/(.) http://www.suibibk.com/$1 permanent;
说明:
rewrite为固定关键字,表示开始进行rewrite匹配规则
regex部分是 ^/(.
) ,这是一个正则表达式,匹配完整的域名和后面的路径地址
replacement部分是http://www.suibibk.com/$1 $1,是取自regex部分()里的内容。匹配成功后跳转到的URL。
flag部分 permanent表示永久301重定向标记,即跳转到新的 http://www.suibibk.com/$1 地址上

假设我们再nginx如下进行配置

  1. server {
  2. listen 80;
  3. server_name localhost;
  4. rewrite ^/(.*) http://www.suibibk.com/$1 permanent;
  5. ...
  6. }

当我们访问:http://192.168.192.11/hello/a/b?id=12345 的时候,就会自动重定向到https://www.suibibk.com/hello/a/b?id=12345

我们也可以用if条件判断,符合if条件判断的才进行处理

  1. server {
  2. listen 80;
  3. server_name localhost;
  4. if ( $host != 'www.suibibk.com' ) {
  5. rewrite ^/(.*) http://www.suibibk.com/$1 permanent;
  6. }
  7. ...
  8. }
1.7.4、if指令可以使用的全局变量
  1. $args #这个变量等于请求行中的参数,同$query_string
  2. $content_length 请求头中的Content-length字段。
  3. $content_type 请求头中的Content-Type字段。
  4. $document_root 当前请求在root指令中指定的值。
  5. $host 请求主机头字段,否则为服务器名称。
  6. $http_user_agent 客户端agent信息
  7. $http_cookie 客户端cookie信息
  8. $limit_rate 这个变量可以限制连接速率。
  9. $request_method 客户端请求的动作,通常为GETPOST
  10. $remote_addr 客户端的IP地址。
  11. $remote_port 客户端的端口。
  12. $remote_user 已经经过Auth Basic Module验证的用户名。
  13. $request_filename 当前请求的文件路径,由rootalias指令与URI请求生成。
  14. $scheme HTTP协议(如httphttps)。
  15. $server_protocol 请求使用的协议,通常是HTTP/1.0HTTP/1.1
  16. $server_addr 服务器地址,在完成一次系统调用后可以确定这个值。
  17. $server_name 服务器名称。
  18. $server_port 请求到达服务器的端口号。
  19. $request_uri 包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。
  20. $uri 不带请求参数的当前URI$uri不包含主机名,如”/foo/bar.html”。
  21. $document_uri $uri相同。
1.7.5、rewrite 中常用的正则
  1. . 匹配换行符以外任意字符
  2. ? 重复0次或者1
  3. + 重复1次或多次
  4. * 重复0次或者多次
  5. \d 匹配数字
  6. ^ 匹配开始
  7. $ 匹配结束
  8. {n} 重复 n
  9. {n,} 重复 n 次或更多次
  10. [c] 匹配单个字符c
  11. [a-z] 匹配 a-z 任意一个小写字母

使用 () 可以将匹配内容括起来,后面使用 $1 来引用,当然,第二个 () 就是 $2。

1.7.6、rewrite应用场景

可以调整用户浏览的URL,看起来更规范,合乎开发及产品人员的需求。
为了让搜索引擎搜录网站内容及用户体验更好,企业会将动态URL地址伪装成静态地址提供服务。
网址换新域名后,让旧的访问跳转到新的域名上。例如,访问京东的360buy.com会跳转到jd.com
根据特殊变量、目录、客户端的信息进行URL调整等

1.7.6、例子实战:让短连接更短

背景:我们公司前端框架用的是struts2,并且是很老的一个框架,请求格式大概是这样:https://www.suibibk.com/u!u.do?u=ke469i57m ,然后运营就说这个短连接还是太长了,有没有办法再变短,比如变为:https://www.suibibk.com/u/ke469i57m
这怎么办呢,struts2又不支持这种格式,并且两个链接都是可以用的,正常用长的就够了!

解决方案,通过rewrite重新

  1. if ( $request_uri ~ /u/ ){
  2. rewrite ^/(u)/(.*) https://www.suibibk.com/u!u.do?u=$2 permanent;
  3. }

完美解决!

注:$1和$2对应的就是前面的正则括号,比如上面$2对应的就是https://www.suibibk.com/u/ke469i57m 中的ke469i57m

1.7.8、if语句中的判断条件

正则表达式匹配:

  1. ==:等值比较;
  2. ~:与指定正则表达式模式匹配时返回“真”,判断匹配与否时区分字符大小写;
  3. ~*:与指定正则表达式模式匹配时返回“真”,判断匹配与否时不区分字符大小写;
  4. !~:与指定正则表达式模式不匹配时返回“真”,判断匹配与否时区分字符大小写;
  5. !~*:与指定正则表达式模式不匹配时返回“真”,判断匹配与否时不区分字符大小写;

反向代理的学习就到这里先,下面进行负载均衡的实战学习

2、负载均衡

2.1、负载均衡概念

负载均衡(Load Balance)其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。

在服务器集群中,Nginx起到一个代理服务器的角色(即反向代理),为了避免单独一个服务器压力过大,将来自用户的请求转发给不同的服务器。我们通过负载均衡,可以启动多个应用服务器来缓解服务端的压力,提高并发能力。

2.2、Nginx搭建负载均衡

这里直接在nginx进行测试即可,用端口进行区分,先见建两个服务8081和8082
8081

  1. server {
  2. listen 8081;
  3. server_name localhost;
  4. location / {
  5. root html;
  6. index index8081.html index.htm;
  7. }
  8. error_page 500 502 503 504 /50x.html;
  9. location = /50x.html {
  10. root html;
  11. }
  12. }

index8081.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Welcome to nginx!</title>
  5. <style>
  6. html { color-scheme: light dark; }
  7. body { width: 35em; margin: 0 auto;
  8. font-family: Tahoma, Verdana, Arial, sans-serif; }
  9. </style>
  10. </head>
  11. <body>
  12. <h1>Welcome to 8081!</h1>
  13. </body>
  14. </html>

8082

  1. server {
  2. listen 8082;
  3. server_name localhost;
  4. location / {
  5. root html;
  6. index index8082.html index.htm;
  7. }
  8. error_page 500 502 503 504 /50x.html;
  9. location = /50x.html {
  10. root html;
  11. }
  12. }

index8082.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Welcome to nginx!</title>
  5. <style>
  6. html { color-scheme: light dark; }
  7. body { width: 35em; margin: 0 auto;
  8. font-family: Tahoma, Verdana, Arial, sans-serif; }
  9. </style>
  10. </head>
  11. <body>
  12. <h1>Welcome to 8082!</h1>
  13. </body>
  14. </html>

配置upstream和代理

  1. upstream first {
  2. server 127.0.0.1:8081;
  3. server 127.0.0.1:8082;
  4. }
  5. server {
  6. listen 80;
  7. server_name localhost;
  8. #charset koi8-r;
  9. #access_log logs/host.access.log main;
  10. location / {
  11. proxy_pass http://first;
  12. proxy_set_header Host $http_host;
  13. proxy_set_header X-Real-IP $remote_addr;
  14. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  15. }
  16. #error_page 404 /404.html;
  17. # redirect server error pages to the static page /50x.html
  18. #
  19. error_page 500 502 503 504 /50x.html;
  20. location = /50x.html {
  21. root html;
  22. }
  23. }

请求测试

  1. http://192.168.192.11/

可以看到结果在【Welcome to 8081!】和【Welcome to 8082!】轮流显示,这是因为我们默认的负载均衡策略是【轮询】

2.3、Nginx负载均衡策略
2.3.1、策略分类

目前Nginx服务器的upstream模块支持6种方式的分配:

策略 描述
轮询 默认方式
weight 权重方式
ip_hash 依据ip分配方式
least_conn 最少连接方式
fair(第三方) 响应时间方式
url_hash(第三方) 依据URL分配方式

在这里,只详细说明Nginx自带的负载均衡策略,第三方不多描述。

2.3.2、轮询

最基本的配置方法,默认的就是轮询的方式,它是upstream模块默认的负载均衡默认策略。每个请求会按时间顺序逐一分配到不同的后端服务器。

参数 意义
fail_timeout 与max_fails结合使用
max_fails 设置在fail_timeout参数设置的时间内最大失败次数,如果在这个时间内,所有针对该服务器的请求都失败了,那么认为该服务器会被认为是停机了
fail_time 服务器会被认为停机的时间长度,默认为10s。
backup 标记该服务器为备用服务器。当主服务器停止时,请求会被发送到它这里
down 标记服务器永久停机了

注意:

  1. 在轮询中,如果服务器down掉了,会自动剔除该服务器。
  2. 缺省配置就是轮询策略。
  3. 此策略适合服务器配置相当,无状态且短平快的服务使用。
2.3.3、weight

权重方式,在轮询策略的基础上指定轮询的几率。例子如下:

  1. #动态服务器组
  2. upstream first {
  3. server localhost:8080 weight=2;
  4. server localhost:8081;
  5. server localhost:8082 backup;
  6. server localhost:8083 max_fails=3 fail_timeout=20s;
  7. }

在该例子中,weight参数用于指定轮询几率,weight的默认值为1,;weight的数值与访问比率成正比,比如8080被访问的几率为其他服务器的两倍。

注意:

  1. 权重越高分配到需要处理的请求越多。
  2. 此策略可以与least_connip_hash结合使用。
  3. 此策略比较适合服务器的硬件配置差别比较大的情况。
2.3.4、ip_hash

指定负载均衡器按照基于客户端IP的分配方式,这个方法确保了相同的客户端的请求一直发送到相同的服务器,以保证session会话。这样每个访客都固定访问一个后端服务器,可以解决session不能跨服务器的问题。

  1. #动态服务器组
  2. upstream first {
  3. ip_hash; #保证每个访客固定访问一个后端服务器
  4. server localhost:8080 weight=2;
  5. server localhost:8081;
  6. server localhost:8082; #backup;
  7. server localhost:8083 max_fails=3 fail_timeout=20s;
  8. }

注意:

  1. nginx版本1.3.1之前,不能在ip_hash中使用权重(weight)。
  2. 此策略适合有状态服务,比如session
  3. 当有服务器需要剔除,必须手动down掉。

ip_hash不能与backup同时使用。否则会报如下错误。

  1. [root@localhost sbin]# ./nginx -t
  2. nginx: the configuration file /usr/local/nginx/nginx.conf syntax is ok
  3. nginx: configuration file /usr/local/nginx/nginx.conf test is successful
2.3.5、least_conn

把请求转发给连接数较少的后端服务器。轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_conn这种方式就可以达到更好的负载均衡效果。

  1. #动态服务器组
  2. upstream first {
  3. least_conn; #把请求转发给连接数较少的后端服务器
  4. server localhost:8080 weight=2;
  5. server localhost:8081;
  6. server localhost:8082 backup;
  7. server localhost:8083 max_fails=3 fail_timeout=20s;
  8. }

注意:

  1. 此负载均衡策略适合请求处理时间长短不一造成服务器过载的情况。
2.3.6、第三方策略

第三方的负载均衡策略的实现需要安装第三方插件。

fair

按照服务器端的响应时间来分配请求,响应时间短的优先分配。

  1. #动态服务器组
  2. upstream first {
  3. server localhost:8080;
  4. server localhost:8081;
  5. server localhost:8082;
  6. server localhost:8083;
  7. fair; #实现响应时间短的优先分配
  8. }

url_hash

按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,要配合缓存命中来使用。同一个资源多次请求,可能会到达不同的服务器上,导致不必要的多次下载,缓存命中率不高,以及一些资源时间的浪费。而使用url_hash,可以使得同一个url(也就是同一个资源请求)会到达同一台服务器,一旦缓存住了资源,再此收到请求,就可以从缓存中读取。

  1. #动态服务器组
  2. upstream first {
  3. hash $request_uri; #实现每个url定向到同一个后端服务器
  4. server localhost:8080;
  5. server localhost:8081;
  6. server localhost:8082;
  7. server localhost:8083;
  8. }
总结

以上便是6种负载均衡策略的实现方式,其中除了轮询和轮询权重外,都是Nginx根据不同的算法实现的。在实际运用中,需要根据不同的场景选择性运用,大都是多种策略结合使用以达到实际需求。

待续


 904

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2