Nginx 是一个高性能的 HTTP 服务器,支持虚拟主机、反向代理和负载均衡。本篇简单介绍下 Nginx 的组件、用途、常用命令,以及如何配置多虚拟主机、反向代理、负载均衡。
概述 Nginx 由一个 master 进程和多个 worker 进程组成:
master 进程:读取、校验配置,维护 worker 进程;
worker 进程:接收请求并进行处理。
Nginx 可以用作什么:
HTTP 服务器:Nginx 可以独立提供 HTTP 服务,作为静态网页服务器;
虚拟主机:在一台服务器上虚拟出多个网站;
反向代理:从一组或多组后端服务器上获取资源,然后再将这些资源返回给客户端;
负载均衡:多台服务器组成的集群使用 Nginx 做反向代理,分担负载。
安装 Nginx 的安装过程无需过多介绍:
1 2 3 4 5 $ yum install nginx $ apt install nginx
其他版本 Linux 的 Nginx 安装过程可以参考官方指南 nginx: Linux packages 。
常用命令 启动 Nginx:
1 2 3 4 5 6 7 8 9 10 11 12 $ nginx $ nginx -c /etc/nginx/conf.d/blog.conf $ nginx -t $ systemctl enable nginx.service Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.
Nginx 启动后,可以使用 -s
参数来进行控制:
1 2 3 4 5 6 7 8 9 10 11 12 13 $ nginx -s <signal> $ nginx -s reload $ nginx -s quit $ nginx -s stop
简易配置说明 配置语法 Nginx 由模块组成,模块由配置文件中的指令控制。指令分为简单指令和块指令两种:
简单指令:也称为单行指令,指令和参数用空格隔开,由分号 ;
结尾;
块指令:指令和参数用空格隔开,不以分号 ;
结尾,而是用大括号 {}
包裹起来。如果块指令可以在大括号内包含其他指令,则称为 context
,比如 events
、http
、server
和 location
。
在任一 context
以外的指令被认为是在 main
这个 context
中,在全局范围生效,可以被子 context
中的配置覆盖。
常用配置项 Nginx 及模块的工作方式由配置文件决定,默认配置文件为 /etc/nginx/nginx.conf
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 user nginx; worker_processes auto; error_log /var/log /nginx/error.log error; pid /run/nginx.pid; include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } http { 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; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; include /etc/nginx/conf.d/*.conf; server { listen 127.0.0.1:80 default_server; listen [::]:80 default_server; server_name sannaha.moe; root /home/git/www/hexo; include /etc/nginx/default.d/*.conf; location / { } error_page 404 =301 https://sannaha.moe; error_page 500 502 503 504 /50x.html; location = /50x.html { } } }
内置变量 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 $args $query_string $arg_NAME $is_args $uri $document_uri $document_root $host $hostname $https $binary_remote_addr $body_bytes_sent $bytes_sent $connection $connection_requests $content_length $content_type $cookie_name $limit_rate $msec $nginx_version $pid $pipe $proxy_protocol_addr $realpath_root $remote_addr $remote_port $remote_user $request $request_body $request_body_file $request_completion $request_filename $request_length $request_method $request_time $request_uri $scheme $server_addr $server_name $server_port $server_protocol $status $time_iso8601 $time_local $cookie_NAME $http_NAME $http_cookie $http_post $http_referer $http_user_agent $http_x_forwarded_for $sent_http_NAME $sent_http_cache_control $sent_http_connection $sent_http_content_type $sent_http_keep_alive $sent_http_last_modified $sent_http_location $sent_http_transfer_encoding
多虚拟主机 虚拟主机是一种特殊的软硬件技术,它可以将网络上的一台计算机分成多个虚拟主机,每个虚拟主机都可以独立对外提供 WEB 服务。
对于 Nginx,可以将多个 server
添加到 http
这个 context
中,定义多个虚拟服务器。不同 server
可以通过 server_name
、address
或 port
进行区分。
多虚拟主机示例 需求:在一台服务器上,根据 server_name
不同,同时对外提供 blog 和 homepage 两个服务。
由于在默认配置文件所示,通过 include
指令在 http
这个 context
中引入了 conf.d
目录下的所有配置,因此可以在 conf.d
目录下创建多个配置文件,实现虚拟主机的模块化配置。
创建 blog.conf
,提供博客服务:
blog.conf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 server { listen 80; listen [::]:80; server_name sannaha.moe; index index.html; root /user/git/www/hexo/; location / { } error_page 404 =301 http://sannaha.moe; error_page 500 502 503 504 /50x.html; location = /50x.html { } }
创建 homepage.conf
,提供主页服务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 server { listen 80; listen [::]:80; server_name thinklong.me; index index.html; root /data/website/homepage/; location / { } error_page 404 =301 http://thinklong.me; error_page 500 502 503 504 /50x.html; location = /50x.html { } }
反向代理 了解代理服务器 代理服务器处于客户端和目标服务器之间。客户端发起请求,代理服务器接收请求后转发给目标服务器,目标服务器收到请求并将响应数据发给代理服务器,代理服务器再将响应数据返回给客户端。
代理服务器的主要作用如下:
提高响应速度:有时候客户端经代理服务器到目标服务器的链路比客户端直接连接目标服务器更快;客户端可能无法直接连接目标服务器,通过代理服务器才能实现访问;代理服务器有做缓存,对于相同的请求可以直接从代理服务器本地返回;
设置防火墙:客户端的所有请求都会经过代理服务器,在代理服务器上设置的防火墙可以过滤所有认为是不安全的信息,方便管理客户端能获取的内容。
正向代理和反向代理 将客户比作顾客,代理服务器比作服务员,目标服务器比作厨师,正向、反向代理对应的场景如下:
正向代理:
顾客 :“服务员,我要吃唐牛做的佛跳墙。”
服务员:“好嘞,这就叫唐牛给您做!”
反向代理:
顾客:“服务员,我要一份蛋炒饭。”
服务员:“好嘞”。然后去找史提芬周做蛋炒饭。
正向代理和反向代理的区别:
正向代理:客户端提出想要获得目标服务器的服务,代理服务器将客户端的请求转发给目标服务器。即代理服务器的代理角色是客户端,去和目标服务器交互;
反向代理:客户端提出服务需求,代理服务器选择一个目标服务器去实现该需求。即代理服务器代理的角色是目标服务器,去和客户端交互。
反向代理示例 需求:反向代理服务器,将前缀字符串匹配到 /read/doc/
的请求转发到目标服务器 sannaha.moe
,将 php 请求转发到本地的 8080
端口。
要将请求传递给 HTTP 服务器,需要在 location
中指定 proxy_pass
指令:
reverse-proxy.conf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 server { listen 80; listen [::]:80; server_name reverse-proxy.thinklong.me; location /read /doc/ { proxy_pass http://sannaha.moe/archive/; } location ~ \.php { proxy_pass http://127.0.0.1:8080; } }
反向代理的目标服务器地址可以是域名或 IP,可以指定端口。
对于像第一个 proxy_pass
这样在地址后还跟了 URI 的,请求的 URI 中与 location
参数匹配的部分将被替换。例如,/read/doc/page.html
的请求将被代理到http://sannaha.moe/archive/page.html
。如果指定的地址后没跟 URI,或无法确定要替换 URI 的哪些部分,则会传递请求的完整 URI。
负载均衡 负载均衡的作用 当网站的访问量达到一定程度后,单台服务器无法满足大量用户的访问,需要将多台服务器组成集群,通过 Nginx 作反向代理来响应用户的请求,可以在性能低的主机分配少一些的负载,在性能高的主机上分配更多的负载,充分利用主机的性能,降低服务器的总压力。
负载均衡示例 要配置负载均衡,首先创建一个 upstream
,在其中列出用于分发客户端请求的多个服务器,然后在一个或多个 proxy_pass
中引用 upstream
,实现反向代理和负载均衡。
Nginx 的 upstream
默认是以轮询的方式分发请求(平均分配),但也支持使用 weight
实现权重的手动分配。
启动三个 Tomcat 服务,端口分别为 8080
、8081
和 8082
,模拟三台服务器;
修改 Nginx 配置文件,在 upstream
中配置上三个 Tomcat 服务地址,使用 weight
手动分配权重;
在 proxy_pass
中配置反向代理;
load-balancing.conf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 upstream blog-servers { server s1.sannaha.moe weight=2; server s2.sannaha.moe weight=1; server s3.sannaha.moe weight=1; } server { listen 80; server_name sannaha.moe; location / { proxy_pass http://blog-servers; index index.html; } }
注意:用户的请求会按照权重分发到不同服务器上,在一次点击行为中,可能会向服务器 A 请求 a.css
和 a.html
、向服务器 B 请求 b.js
、向服务器 C 请求 c.jsp
,因此要求每个服务器上都能够完整地提供用户需要的资源。如果某个服务器无法提供用户请求的资源,就会出现 404。
问题 ipv6 only 问题
1 2 3 $ nginx -t nginx: [emerg] duplicate listen options for [::]:443 in /etc/nginx/conf.d/homepage.conf:7 nginx: configuration file /etc/nginx/nginx.conf test failed
https://github.com/certbot/certbot/issues/5550
参考资料 Nginx - Beginner’s Guide Nginx - Admin Guide