安装和配置 Nginx

一、安装Nginx

本文环境是CentOS Linux release 7.3.1611 (Core)

cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)

1: 添加 yum 源

Nginx 不在默认的 yum 源中,可以使用 epel 或者官网的 yum 源,本例使用官网的 yum 源。

sudo rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm

安装完 yum 源之后,可以查看一下

yum repolist

2. 安装

yum 安装 Nginx,非常简单,一条命令。

sudo yum install nginx

3. 配置 Nginx 服务

## 设置开机启动
sudo systemctl enable nginx

## 启动服务
sudo systemctl start nginx

## 停止服务
sudo systemctl restart nginx

## 重新加载,因为一般重新配置之后,不希望重启服务,这时可以使用重新加载。
sudo systemctl reload nginx

4. 打开防火墙端口

默认 CentOS7 使用的防火墙 firewalld 是关闭 http 服务的(打开 80 端口)。

$ sudo firewall-cmd --zone=public --permanent --add-service=http
success
$ sudo firewall-cmd --reload
success

打开之后,可以查看一下防火墙打开的所有的服务

sudo firewall-cmd --list-service
ssh dhcpv6-client http

可以看到,系统已经打开了 http 服务

5. 查看和修改nginx文件

ls /etc/nginx
conf.d  fastcgi_params  koi-utf  koi-win  mime.types  modules  
nginx.conf  scgi_params  uwsgi_params  win-utf

二、配置Nginx

1. Nginx常用功能

  • 反向代理
  • 负载均衡
  • web缓存

2. 使用Nginx的必备工具

2.1 GCC & G++编译器

sudo yum install -y gcc
sudo yum install -y g++

2. 2 PCRE库

兼容正则表达式(PCRE)。在配置nginx时如果使用了正则表达式,就需要将PCRE库编译进nginx。pcre-devel是使用PCRE做二次开发时所需要的开发库,包括头文件等,这也是编译Nginx所必须使用的。PCRE库安装方法如下:

sudo yum install -y pcre pcre-devel

2.3 zlib

zlib库用于对HTTP包的内容做gzip格式的压缩,如果我们在nginx.conf里配置了gzip on,并指定对于某些类型(content-type)的HTTP响应使用gzip来进行压缩以减少网络传输量,那么,在编译时就必须把zlib编译进Nginx。其安装方式如下:

sudo yum install -y zlib zlib-devel

2.4 OpenSSL开发库

如果我们的服务器不只是要支持HTTP,还需要在更安全的SSL协议上传输HTTP,那么
就需要拥有OpenSSL了。另外,如果我们想使用MD5、SHA1等散列函数,那么也需要安装它。其yum安装方式如下:

sudo yum install -y openssl openssl-devel

2.5 磁盘目录

要使用Nginx,还需要在Linux文件系统上准备以下目录。

a. Nginx源代码存放目录

该目录用于放置从官网上下载的Nginx源码文件,以及第三方或我们自己所写的模块源代码文件。

b. Nginx编译阶段产生的中间文件存放目录

该目录用于放置在configure命令执行后所生成的源文件及目录,以及make命令执行后生成的目标文件和最终连接成功的二进制文件。默认情况下,configure命令会将该目录命名为objs,并放在Nginx源代码目录下。

c. 部署目录

该目录存放实际Nginx服务运行期间所需要的二进制文件、配置文件等。默认情况下,该目录为 /usr/local/nginx

d. 日志文件存放目录

日志文件通常会比较大,当研究Nginx的底层架构时,需要打开debug级别的日志,这个级别的日志非常详细,会导致日志文件的大小增长得极快,需要预先分配一个拥有更大磁盘空间的目录。

小结

Nginx是高度自由化的Web服务器,它的功能是由许多模块来支持的。而这些模块可根据
我们的使用需求来定制,如果某些模块不需要使用则完全不必理会它。同样,如果使用了某个模块,而这个模块使用了一些类似zlib或OpenSSL等的第三方库,那么就必须先安装这些软件。

3. Linux内核优化

由于默认的Linux内核参数考虑的是最通用的场景,这明显不符合用于支持高并发访问的Web服务器的定义,所以需要修改Linux内核参数,使得Nginx可以拥有更高的性能。

在优化内核时,可以做的事情很多,不过,我们通常会根据业务特点来进行调整,当Nginx作为静态Web内容服务器、反向代理服务器或是提供图片缩略图功能(实时压缩图片的服务器时,其内核参数的调整都是不同的。这里只针对最通用的、使Nginx支持更多并发请求的TCP网络参数做简单说明

首先,需要修改/etc/sysctl.conf来更改内核参数。例如,最常用的配置:

# 这个参数表示进程(比如一个worker进程)可以同时打开的最大句柄数
# 这个参数直接限制最大并发连接数,需根据实际情况配置
fs.file-max = 999999  

# 这个参数设置为1,表示允许将TIME-WAIT状态的socket重新用于新的
# TCP连接,这对于服务器来说很有意义,因为服务器上总会有大量TIME-WAIT状态的连接
net.ipv4.tcp_tw_reuse = 1

#这个参数表示当keepalive启用时,TCP发送keepalive消息的频度。
# 默认是2小时,若将其设置得小一些,可以更快地清理无效的连接
net.ipv4.tcp_keepalive_time = 600

# 这个参数表示当服务器主动关闭连接时,socket保持在FIN-WAIT-2状
# 态的最大时间。
net.ipv4.tcp_fin_timeout = 30

#v这个参数表示操作系统允许TIME_WAIT套接字数量的最大值,
# 如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。该参数默认为
# 180000,过多的TIME_WAIT套接字会使Web服务器变慢
net.ipv4.tcp_max_tw_buckets = 5000

# 定义了在UDP和TCP连接中本地(不包括连接的远端)端口的取值范围。
net.ipv4.ip_local_port_range = 1024    61000

# 定义了TCP接收缓存(用于TCP接收滑动窗口)的
# 最小值、默认值、最大值。
net.ipv4.tcp_rmem = 4096 32768 262142

# 定义了TCP发送缓存(用于TCP发送滑动窗口)的
# 最小值、默认值、最大值。
net.ipv4.tcp_wmem = 4096 32768 262142

# 当网卡接收数据包的速度大于内核处理的速度时,会有一个队列
# 保存这些数据包。这个参数表示该队列的最大值。
net.core.netdev_max_backlog = 8096

# 表示内核套接字接收缓存区默认的大小。
net.core.rmem_default = 262144

# 表示内核套接字发送缓存区默认的大小。
net.core.wmem_default = 262144

# 表示内核套接字接收缓存区的最大大小
net.core.rmem_max = 2097152

# 表示内核套接字发送缓存区的最大大小
net.core.wmem_max = 2097152

# tcp_syncookies性能无关,用于解决TCP的SYN攻击
net.ipv4.tcp_syncookies = 1

# 表示TCP三次握手建立阶段接收SYN请求队列的最大
# 长度,默认为1024,将其设置得大一些可以使出现Nginx繁忙来不及accept新连接的情况时,
# Linux不至于丢失客户端发起的连接请求
net.ipv4.tcp_max_syn.backlog=1024

使上述修改生效,需要执行以下命令:

sysctl-p

3. Nginx配置

Nginx拥有大量官方发布的模块和第三方模块,这些已有的模块可以帮助我们实现Web服务器上很多的功能。使用这些模块时,仅仅需要增加、修改一些配置项即可。

3.1 运行中的Nginx进程间的关系

在正式提供服务的产品环境下,部署Nginx时都是使用一个master进程来管理多个worker进程,一般情况下,worker进程的数量与服务器上的CPU核心数相等。每一个worker进程都是繁忙的,它们在真正地提供互联网服务,master进程则很“清闲”,只负责监控管理worker进程。worker进程之间通过共享内存、原子操作等一些进程间通信机制来实现负载均衡等功能。

Nginx是支持单进程(master进程)提供服务而,那么为什么要按照worker方式配置同时启动多个进程呢?原因如下:

  • 由于master进程不会对用户请求提供服务,只用于管理真正提供服务的worker进程,所以master进程可以是唯一的,它仅专注于自己的纯管理工作,为管理员提供命令行服务,包括诸如启动服务、停止服务、重载配置文件、平滑升级程序等
  • master进程需要拥有较大的权限,例如,通常会利用root用户启动master进程。worker进程的权限要小于或等于master进程,这样master进程才可以完全地管理worker进程。当任意一个worker进程出现错误从而导致coredump时,master进程会立刻启动新的worker进程继续服务。·
  • 多个worker进程处理互联网请求不但可以提高服务的健壮性(一个worker进程出错后,其他worker进程仍然可以正常提供服务),最重要的是,这样可以充分利用现在常见的SMP多核架构,从而实现微观上真正的多核并发处理。因此,用一个进程(master进程)来处理互联网请求肯定是不合适的。

另外,为什么要把worker进程数量设置得与CPU核心数量一致呢?

  • 这正是Nginx与Apache服务器的不同之处。在Apache上每个进程在一个时刻只处理一个请求,因此,如果希望Web服务器拥有并发处理的请求数更多,就要把Apache的进程或线程数设置得更多,通常会达到一台服务器拥有几百个工作进程,这样大量的进程间切换将带来无谓的系统资源消耗。
  • Nginx则不然,一个worker进程可以同时处理的请求数只受限于内存大小,而且在架构设计上,不同的worker进程之间处理并发请求时几乎没有同步锁的限制,worker进程通常不会进入睡眠状态,因此,当Nginx上的进程数与CPU核心数相等时(最好每一个worker进程都绑定特定的CPU核心),进程间切换的代价是最小的。

nginx进程间的关系如下图所示:
在这里插入图片描述

3.2 Nginx配置的通用语法

Nginx的配置文件其实是一个普通的文本文件。下面是nginx默认的配置文件:

[root]# cat /etc/nginx/nginx.conf
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

3.2.1 认识nginx配置项

块配置项

上面代码段中的eventshttp都是块配置项。所有的事件类配置都要在events块中,http、server等配置也遵循这个规定。

单位

当指定空间大小时,可以使用的单位包括:

  • K或者k千字节(KiloByte,KB)
  • M或者m兆字节(MegaByte,MB)

当指定时间时,可以使用的单位包括:

·ms(毫秒),s(秒),m(分钟),h(小时),d(天),w(周,包含7天),
M(月,包含30天),y(年,包含365天)。

在配置中使用变量

有些模块允许在配置项中使用变量,如在日志记录部分,具体示例如下

 log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

其中,remote_addr是一个变量,使用它的时候前面要加上$符号。需要注意的是,这种变量只有少数模块支持,并不是通用的

3.2.2 常用配置项

(1)优化性能的配置项

#Nginx worker进程个数. 默认为1
worker_processes number 

# 绑定Nginx worker进程到指定的CPU内核
# 如果每一个worker进程都独享一个CPU,就在内核的调度策略上实现了完全的并发。
# worker_cpu_affinity cpumask[cpumask...] 
worker_cpu_affinity 1000 0100 0010 0001 # 4核CPU

# SSL硬件加速
# 如果服务器上有SSL硬件加速设备,那么就可以进行配置以加快SSL协议的处理速度。
ssl_engine device

# 内核的事件调用(epoll、select等)返回时,都会执行一次gettimeofday
# timer_resolution可以改变gettimeofday的执行频率.
# 至少每t ms才调用一次gettimeofday
timer_resolution t

# Nginx worker进程优先级设置
 worker_priority nice # 默认为0
# 使用OpenSSL提供的命令来查看是否有SSL硬件加速设备
[root@calm-boot-3 ~]# openssl engine -t
(rdrand) Intel RDRAND engine
     [ available ]
(dynamic) Dynamic engine loading support
     [ unavailable ]

(2) event事件类配置项

# 是否打开accept锁.accept_mutex是Nginx的负载均衡锁
accept_mutex [on|off] # 默认 accept_mutext on;

# lock文件的路径
# accept锁可能需要这个lock文件,如果accept锁关闭,lock_file配置完全不生效。
lock_file path/file # 默认lock_file logs/nginx.lock;

# 用accept锁后到真正建立连接之间的延迟时间
accept_mutex_delay Nms; # 默认500ms

# 每个worker的最大连接数
worker_connections number

# 批量建立新连接。当事件模型通知有新连接时,
# 尽可能地对本次调度中客户端发起的所有TCP请求都建立连接。
multi_accept[on|off] # 默认off

4. 用HTTP核心模块配置一个静态Web服务器

静态Web服务器的主要功能由ngx_http_core_module模块(HTTP框架的主要成员)实现,当然,一个完整的静态Web服务器还有许多功能是由其他的HTTP模块实现的。

除了上文提到的基本配置项外,一个典型的静态Web服务器还会包含多个server块和
location块。

Nginx为配置一个完整的静态Web服务器提供了非常多的功能,下面会把这些配置项分为以下8类进行详述:虚拟主机与请求的分发、文件路径的定义、内存及磁盘资源的分配、网络连接的设置、MIME类型的设置、对客户端请求的限制、文件操作的优化、对客户端请求的特殊处理。这种划分只是为了帮助大家从功能上理解这些配置项。

4.1 虚拟主机与请求的分发

由于IP地址的数量有限,因此经常存在多个主机域名对应着同一个IP地址的情况,这时在nginx.conf中就可以按照server_name(对应用户请求中的主机域名)并通过server块来定义虚拟主机,每个server块就是一个虚拟主机,它只处理与之相对应的主机域名请求。这样,一台服务器上的Nginx就能以不同的方式处理访问不同主机域名的HTTP请求了。

在这里插入图片描述
(1)监听端口

  • 语法: listen address:port[default_server| backlog=num| rcvbuf=size|sndbuf=size| accept_filter=filter|deferred|bind|ipv6only=[on|off]|ssl]];
  • 默认: listen 80;
  • 配置块:server

listen参数决定Nginx服务如何监听端口。在listen后可以只加IP地址、端口或主机名,非
常灵活,例如:

server {
	listen 127.0.0.1:8000; #注意:不加端口时,默认监听80
	# 在地址和端口后,还可以加上其他参数,例如:
	listen  443 default_server ssl;
	listen  127.0.0.1 default_server accept_filter=dataready backlog=1024;
}

下面说明listen可用参数的意义。

  • default_server:将所在的server块作为整个Web服务的默认server块。如果没有设置这个参数,那么将会以在nginx.conf中找到的第一个server块作为默认server块。为什么需要默认虚拟主机呢?当一个请求无法匹配配置文件中的所有主机域名时,就会选用默认的虚拟主机

  • backlog=num:表示TCP中backlog队列的大小。默认为–1,表示不予设置。在TCP建立三次握手过程中,进程还没有开始处理监听句柄,这时backlog队列将会放置这些新连接。可如果backlog队列已满,还有新的客户端试图通过三次握手建立TCP连接,这时客户端将会建立连接失败。

  • rcvbuf=size:设置监听句柄的SO_RCVBUF参数。

  • sndbuf=size:设置监听句柄的SO_SNDBUF参数。

  • accept_filter:设置accept过滤器,只对FreeBSD操作系统有用。

  • deferred:在设置该参数后,若用户发起建立连接请求,并且完成了TCP的三次握手,内核也不会为了这次的连接调度worker进程来处理,只有用户真的发送请求数据时(内核已经在网卡中收到请求数据包),内核才会唤醒worker进程处理这个连接。这个参数适用于大并发的情况下,它减轻了worker进程的负担。当请求数据来临时,worker进程才会开始处理这个连接。只有确认上面所说的应用场景符合自己的业务需求时,才可以使用deferred配置。

  • bind:绑定当前端口/地址对,如127.0.0.1:8000。只有同时对一个端口监听多个地址时 才会生效

  • ssl:在当前监听的端口上建立的连接必须基于SSL协议。

(2)主机名称

  • 语法: server_name name[…];
  • 默认: server_name " ";
  • 配置块: server

server_name后可以跟多个主机名称,如:
server_name www.testweb.com 、www.testweb.com;

在开始处理一个HTTP请求时,Nginx会取出header头中的Host,与每个server中的server_name进行匹配,以此决定到底由哪一个server块来处理这个请求。有可能一个Host与多个server块中的server_name都匹配,这时就会根据匹配优先级来选择实际处理的server块。server_name与Host的匹配优先级如下:

1)首先选择所有字符串完全匹配的server_name,如www.testweb.com 。

2)其次选择通配符在前面的server_name,如*.testweb.com。

3)再次选择通配符在后面的server_name,如www.testweb.* 。

4)最后选择使用正则表达式才匹配的server_name,如~^.testweb.com$。

Nginx正是使用server_name配置项针对特定Host域名的请求提供不同的服务,
以此实现虚拟主机功能。

(3) server_names_hash_bucket_size

  • 语法: server_names_hash_bucket_size size;
  • 默认: server_names_hash_bucket_size 32|64|128;
  • 配置块: http、server、location

为了提高快速寻找到相应server name的能力,Nginx使用散列表来存储server name
server_names_hash_bucket_size设置了每个散列桶占用的内存大小。

(4) server_names_hash_max_size

  • 语法: server_names_hash_max_size size;
  • 默认: server_names_hash_max_size 512;
  • 配置块: http、server、location

server_names_hash_max_size会影响散列表的冲突率。server_names_hash_max_size越大,消耗的内存就越多,但散列key的冲突率则会降低,检索速度也更快。server_names_hash_max_size越小,消耗的内存就越小,但散列key的冲突率可能增高。
(5)重定向主机名称的处理

语法: server_name_in_redirect on|off;

默认: server_name_in_redirect on;

配置块: http、server或者location

该配置需要配合server_name使用。在使用on打开时,表示在重定向请求时会使用server_name里配置的第一个主机名代替原先请求中的Host头部,而使用off关闭时,表示在重定向请求时使用请求本身的Host头部。
(6)location

  • 语法: location[=||*|^~|@]/uri/{…}
  • 配置块: server

location会尝试根据用户请求中的URI来匹配上面的/uri表达式,如果可以匹配,就选择location{}块中的配置来处理用户请求。

  • ~表示匹配URI时是字母大小写敏感的。
  • ~*表示匹配URI时忽略字母大小写问题。
  • ^~表示匹配URI时只需要其前半部分与uri参数匹配即可。例如:
    location ^~ images { 
    	 # 以images开始的请求都会匹配上
    }
    
  • @表示仅用于Nginx服务内部请求之间的重定向,带有@的location不直接处理用户请求
  • 在uri参数里是可以用正则表达式的。当一个请求有可能匹配多个location时,实际上这个请求会被第一个location处理。

在以上各种匹配方式中,都只能表达为“如果匹配…则…”。如果需要表达“如果不匹配…则…”,就很难直接做到。有一种解决方法是在最后一个location中使用/作为参数,它会匹配所有的HTTP请求,这样就可以表示如果不能匹配前面的所有location,则由“/”这个location处理。

4.2 文件路径的定义

先看个常用的配置。这里配置完后如果访问返回404, 则需要修改配置文件(/etc/nginx/nginx.conf)。这是因为nginx是由root用户安装创建,但是配置文件默认是user nginx;改为user root即可正常访问静态图片资源。

server {
    location / {
        proxy_pass http://localhost:8080/;
    }

    location ~ \.(gif|jpg|png)$ {
        root /data/images;
    }
}

(1)以root方式设置资源路径

  • 语法: root path;
  • 默认: root html;
  • 配置块: http、server、location、if

例如,定义资源文件相对于HTTP请求的根目录。

location /download/ {
        root optwebhtml;
}

在上面的配置中,如果有一个请求的URI是/download/index/test.html,那么Web服务器将会返回服务器上optwebhtmldownload/index/test.html文件的内容。

(2)以alias方式设置资源路径

  • 语法: alias path;
  • 配置块: location

alias也是用来设置文件资源路径的,它与root的不同点主要在于如何解读紧跟location后面的uri参数,这将会致使alias与root以不同的方式将用户请求映射到真正的磁盘文件上。例如,如果有一个请求的URI是/conf/nginx.conf,而用户实际想访问的文件在usrlocal/nginx/conf/nginx.conf,那么想要使用alias来进行设置的话,可以采用如下方式:

location conf {
	alias usr/local/nginx/conf/;    
}

如果用root设置,那么语句如下所示:

location conf {
	root usr/local/nginx/;        
}

(3)访问首页

  • 语法: index file…;
  • 默认: index index.html;
  • 配置块: http、server、location

有时,访问站点时的URI是/,这时一般是返回网站的首页,而这与root和alias都不同。这里用ngx_http_index_module模块提供的index配置实现。index后可以跟多个文件参数,Nginx将会按照顺序来访问这些文件。

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

上面配置nginx收到请求后,先去找index.html文件,如果有,则停止向后查找。如果没有,则向后查找直到找到一个存在的文件。

(4)根据HTTP返回码重定向页面

  • 语法: error_page code[code…][=|=answer-code]uri|@named_location
  • 配置块: http、server、location、if

当对于某个请求返回错误码时,如果匹配上了error_page中设置的code,则重定向到新的URI中

error_page   500 502 503 504  /50x.html;
location = /50x.html {
	root   /usr/share/nginx/html;
}

4.3 内存及磁盘资源的分配

下面介绍处理请求时内存、磁盘资源分配的配置项。

(1)HTTP包体只存储到磁盘文件中

  • 语法: client_body_in_file_only on|clean|off;
  • 默认: client_body_in_file_only off;
  • 配置块: http、server、location

当值为非off时,用户请求中的HTTP包体一律存储到磁盘文件中,即使只有0字节也会存储为文件。当请求结束时,如果配置为on,则这个文件不会被删除(该配置一般用于调试、定位问题),但如果配置为clean,则会删除该文件。

(2)HTTP包体尽量写入到一个内存buffer中

  • 语法: client_body_in_single_buffer on|off;
  • 默认: client_body_in_single_buffer off;
  • 配置块: http、server、location

用户请求中的HTTP包体一律存储到内存buffer中。当然,如果HTTP包体的大小超过了下面client_body_buffer_size设置的值,包体还是会写入到磁盘文件中。

(3)存储HTTP头部的内存buffer大小

  • 语法: client_header_buffer_size size;
  • 默认: client_header_buffer_size 1k;
  • 配置块: http、server

上面配置项定义了正常情况下Nginx接收用户请求中HTTP header部分(包括HTTP行和HTTP头部)时分配的内存buffer大小。有时,请求中的HTTP header部分可能会超过这个大小,这时large_client_header_buffers定义的buffer将会生效。

(4)存储超大HTTP头部的内存buffer大小

  • 语法: large_client_header_buffers number size;
  • 默认: large_client_header_buffers 48k;
  • 配置块: http、server

large_client_header_buffers定义了Nginx接收一个超大HTTP头部请求的buffer个数和每个buffer的大小。如果HTTP请求行(如GET/index HTTP/1.1)的大小超过上面的单个buffer,则返回"Request URI too large"(414)。请求中一般会有许多header,每一个header的大小也不能超过单个buffer的大小,否则会返回"Bad request"(400)。当然,请求行和请求头部的总和也不可以超过buffer个数*buffer大小。

(5)connection_pool_size

  • 语法: connection_pool_size size;
  • 默认: connection_pool_size 256;
  • 配置块: http、server

Nginx对于每个建立成功的TCP连接会预先分配一个内存池,上面的size配置项将指定这个内存池的初始大小(即ngx_connection_t结构体中的pool内存池初始大小),用于减少内核对于小块内存的分配次数。需慎重设置,因为更大的size会使服务器消耗的内存增多,而更小的size则会引发更多的内存分配次数。

(6)request_pool_size

  • 语法: request_pool_size size;
  • 默认: request_pool_size 4k;
  • 配置块: http、server

Nginx开始处理HTTP请求时,将会为每个请求都分配一个内存池,size配置项将指定这
个内存池的初始大小。

三、Nginx反向代理

1. 什么是反向代理

当我们在外网访问百度的时候,其实会进行一个转发,代理到内网去,这就是所谓的反向代理,即反向代理“代理”的是服务器端,而且这一个过程对于客户端而言是透明的。
在这里插入图片描述

2. 反向代理部署

Nginx的核心功能——反向代理是基于upstream模块(该模块属于HTTP框架的一部分)实现的。在弄清楚upstream的用法后,完全可以根据自己的需求重写Nginx的反向代理功能。

例如,反向代理模块是在先接收完客户请求的HTTP包体后,才向上游服务器建立连接并转发请求的。假设用户要上传大小为1GB的文件,由于网速限制,文件完整地到达Nginx需要10小时,恰巧Nginx与上游服务器间的网络也很差(当然这种情况很少见),反向代理这个请求到上游服务也需要10小时,因此,根据用户的网速也许本来只要10个小时的上传过程,最终可能需要20个小时才能完成。

在了解了upstream功能后,可以试着改变反向代理模块的这种特性,比如模仿squid反向代理模式,在接收完整HTTP请求的头部后就与上游服务器建立连接,并开始将请求向上游服务器透传。upstream的使用方式并不复杂,它提供了8个回调方法,用户只需要视自己的需要实现其中几个回调方法就可以了。在了解这8个回调方法之前,首先要了解upstream是如何嵌入到一个请求中的。


启动upstream的流程如下所示:
在这里插入图片描述

upstream执行的一般流程:
在这里插入图片描述

3. 修改配置文件实现反向代理

其实就是在location这一段配置中的root替换成proxy_pass即可。root说明是静态资源,可以由Nginx进行返回;而proxy_pass说明是动态请求,需要进行转发,比如代理到Tomcat上。

server {
    location / {
        proxy_pass http://localhost:8080/;
    }

    location ~ \.(gif|jpg|png)$ {
        root /data/images;
    }
}

反向代理,上面已经说了,过程是透明的,比如说request -> Nginx -> Tomcat,那么对于Tomcat而言,请求的IP地址就是Nginx的地址,而非真实的request地址,这一点需要注意。不过好在Nginx不仅仅可以反向代理请求,还可以由用户自定义设置HTTP HEADER。

四、Nginx负载均衡

上面的反向代理中,我们通过proxy_pass来指定Tomcat的地址,很显然我们只能指定一台Tomcat地址,那么我们如果想指定多台来达到负载均衡呢?

第一,通过upstream来定义一组Tomcat,并指定负载策略(IPHASH、加权论调、最少连接),健康检查策略(Nginx可以监控这一组Tomcat的状态)等。

第二,将proxy_pass替换成upstream指定的值即可。

负载均衡可能带来的问题

负载均衡所带来的明显的问题是,一个请求,可以到A server,也可以到B server,这完全不受我们的控制,当然这也不是什么问题,只是我们得注意的是:用户状态的保存问题,如Session会话信息,不能在保存到服务器上

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章