Appearance
Nginx 简明入门教程
1. 简介
Nginx 是一个轻量级、高性能、稳定性高、并发性好的 HTTP 和反向代理服务器。也是由于其的特性,其应用非常广。
Nginx 本身也是一个静态资源的服务器,当只有静态资源的时候,就可以使用 Nginx 来做服务器,如果一个网站只是静态页面的话,那么就可以通过这种方式来实现部署。
除了静态资源和代理服务器之外,还有哪些应用场景呢?
2. 场景示例
2.1. HTTP 服务器
首先在文档根目录(
/usr/share/nginx)下创建html目录,然后在html中放一个index.html;配置
nginx.conf中的serverNginxuser mengday staff; http { server { listen 80; server_name localhost; client_max_body_size 1024M; # 默认 location location / { root /usr/share/nginx/html; index index.html index.htm; } } }访问测试
http://localhost/指向/usr/share/nginx/index.html(此index.html是 Nginx 自带的html);http://localhost/test.html指向/usr/share/nginx/html/test.html。
信息
如果访问图片出现 403 Forbidden 错误,可能是因为
nginx.conf的第一行user配置不对,默认是#user nobody;是注释的,Linux 下改成user root;,MacOS 下改成用户名所在组。然后重新加载配置文件或者重启,再试一下就可以了,用户名可以通过who am i命令来查看。
指令简介:
server:用于定义服务,http中可以有多个server块;listen:指定服务器侦听请求的 IP 地址和端口,如果省略地址,服务器将侦听所有地址,如果省略端口,则使用标准端口;server_name:服务名称,用于配置域名;location:用于配置映射路径 URL,一个server中可以有多个location,location后面跟一个 URL,可以是一个正则表达式,/表示匹配任意路径,当客户端访问的路径满足这个 URL 时就会执行location块里面的代码;root:根路径,当访问http://localhost/test.html,/test.html会匹配到/URL, 找到root为/usr/share/nginx/html,用户访问的资源物理地址 =root+ URL =/usr/share/nginx/html+/test.html=/usr/share/nginx/html/test.html;index:设置首页,当只访问server_name时后面不跟任何路径是不走root直接走index指令的;如果访问路径中没有指定具体的文件,则返回index设置的资源,如果访问http://localhost/则默认返回index.html。
2.2. 静态资源服务器
在公司中经常会遇到静态资源服务器,通常会提供一个上传的功能,其他应用如果需要静态资源就从该静态资源服务器中获取。
在 /usr/share/nginx 下分别创建 images 和 img 目录,分别在每个目录下放一张 test.jpg:
Nginx
http {
server {
listen 80;
server_name localhost;
set $doc_root /usr/share/nginx;
# 默认 location
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location ^~ /images/ {
root $doc_root;
}
location ~* \.(gif|jpg|jpeg|png|bmp|ico|swf|css|js)$ {
root $doc_root/img;
}
}
}使用 set 指令自定义变量 $doc_root。
静态资源服务器 location 的映射一般有两种方式:
- 使用路径,如
/images/一般图片都会放在某个图片目录下; - 使用后缀,如
.jpg、.png等后缀匹配模式。
访问 http://localhost/test.jpg 会映射到 $doc_root/img。
访问 http://localhost/images/test.jpg,当同一个路径满足多个 location 时,优先匹配优先级高的 location,由于 ^~ 的优先级大于 ~,所以会走 /images/ 对应的 location。
location 的匹配类型主要有 4 种:
| 匹配类型 | 语法 | 含义 | 示例 |
|---|---|---|---|
| 精确匹配 | location = /uri | 只有当请求 URL 与 /uri 完全相等时才匹配 | location = /login |
| 普通前缀匹配 | location /uri | 匹配所有以 /uri 开头的请求(默认类型) | location /images |
| 优先前缀匹配 | location ^~ /uri | 匹配所有以 /uri 开头的请求,但一旦命中,就不再进行正则匹配 | location ^~ /static/ |
| 正则匹配 | location ~ pattern(区分大小写)location ~* pattern(不区分大小写) | 使用正则表达式匹配请求 URL | location ~ \.php$ |
location 优先级:= > ^~ > ~ / ~* > 普通前缀匹配(最长路径)。
2.3. 反向代理
反向代理应该是 Nginx 使用最多的功能了,反向代理(Reverse Proxy)方式是指以代理服务器来接受 Internet 上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 Internet 上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。
简单来说就是真实的服务器不能直接被外部网络访问,所以需要一台代理服务器,而代理服务器能被外部网络访问的同时又跟真实服务器在同一个网络环境,当然也可能是同一台服务器,端口不同而已。
反向代理通过 proxy_pass 指令来实现。
启动一个 Java Web 项目,端口号为
8081:Nginxserver { listen 80; server_name localhost; location / { proxy_pass http://localhost:8081; proxy_set_header Host $host; # 设置真实客户端 IP 地址 proxy_set_header X-Forwarded-For $remote_addr; # 当请求服务器出错去寻找其他服务器 proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; } }当我们访问
localhost的时候,就相当于访问localhost:8081了。
2.4. 负载均衡
负载均衡也是 Nginx 常用的一个功能,负载均衡其意思就是分摊到多个操作单元上进行执行,例如 Web 服务器、FTP 服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。
简单而言就是当有 2 台或以上服务器时,根据规则随机的将请求分发到指定的服务器上处理,负载均衡配置一般都需要同时配置反向代理,通过反向代理跳转到负载均衡。
2.4.1. 轮询
每个请求按时间顺序逐一分配到不同的后端服务器,也就是说第一次请求分配到第一台服务器上,第二次请求分配到第二台服务器上,如果只有两台服务器,第三次请求继续分配到第一台上,这样循环轮询下去,也就是服务器接收请求的比例是 1:1,如果后端服务器 down 掉,能自动剔除。轮询是默认规则。
同一个项目分别使用
8081和8082端口启动项目:Nginxupstream web_servers { server localhost:8081; server localhost:8082; } server { listen 80; server_name localhost; #access_log logs/host.access.log main; location / { proxy_pass http://web_servers; proxy_set_header Host $host; } }此时访问
localhost:80就将会在8081、8082之间轮询了。
2.4.2. 权重
指定轮询几率,weight 和访问比率成正比,也就是服务器接收请求的比例就是各自配置的 weight 的比例,用于后端服务器性能不均的情况,比如服务器性能差点就少接收点请求,服务器性能好点就多处理点请求。
Nginx
upstream test {
server localhost:8081 weight=1;
server localhost:8082 weight=3;
server localhost:8083 weight=4 backup;
}示例是 4 次请求只有一次被分配到 8081 上,其他 3 次分配到 8082 上。backup 是指热备,只有当 8081 和 8082 都宕机的情况下才走 8083。
2.4.3. ip_hash
上面的 2 种方式都有一个问题,那就是下一个请求来的时候请求可能分发到另外一个服务器,当我们的程序不是无状态的时候(采用了 Session 保存数据),这时候就有一个很大的很问题了,比如把登录信息保存到了 Session 中,那么跳转到另外一台服务器的时候就需要重新登录了,所以很多时候我们需要一个客户只访问一个服务器,那么就需要用 ip_hash 了,ip_hash 的每个请求按访问 IP 的 Hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决 Session 丢失的问题。
Nginx
upstream test {
ip_hash;
server localhost:8080;
server localhost:8081;
}2.4.4. fair
按后端服务器的响应时间来分配请求,响应时间短的优先分配。这个配置是为了更快的给用户响应。
Nginx
upstream backend {
fair;
server localhost:8080;
server localhost:8081;
}2.4.5. hash
还可以按访问 URL 的 Hash 结果来分配请求,使每个 URL 定向到同一个后端服务器,后端服务器为缓存时比较有效。在 upstream 中加入 hash 语句,server 语句中不能写入 weight 等其他的参数,hash_method 是使用的 hash 算法。
Nginx
upstream backend {
hash $request_uri;
hash_method crc32;
server localhost:8080;
server localhost:8081;
}Nginx 还支持根据任意请求头(Header)的值进行一致性哈希(Consistent Hash)负载均衡。
Nginx 会自动将请求头转换为变量,格式为 $http_<header_name>(小写,下划线替换 -)。
以下是一个根据 X-User-ID 请求头进行一致性哈希的示例:
Nginx
upstream backend {
hash $http_x_user_id consistent; # 根据 X-User-ID 头哈希
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
}
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
}
}还可以用 map 模块设置默认值,避免哈希失败:
Nginx
map $http_x_user_id $hash_key {
"" $remote_addr; # 如果没有 X-User-ID,用客户端 IP
default $http_x_user_id; # 否则用该 header
}
upstream backend {
hash $hash_key consistent;
server backend1.example.com;
server backend2.example.com;
}
server {
location / {
proxy_pass http://backend;
}
}3. 内置变量
Nginx 的配置文件中可以使用的内置变量(全局变量)以美元符 $ 开始。其中,部分预定义的变量的值是可以改变的。
$args:这个变量等于请求行中的参数,同$query_string;$content_length:请求头中的Content-Length字段;$content_type:请求头中的Content-Type字段;$document_root:当前请求在root指令中指定的值;$host:请求主机头字段,否则为服务器名称;$http_user_agent:客户端 agent 信息;$http_cookie:客户端 cookie 信息;$limit_rate:这个变量可以限制连接速率;$request_method:客户端请求的动作,通常为 GET 或 POST;$remote_addr:客户端的 IP 地址;$remote_port:客户端的端口;$remote_user:已经经过 Auth Basic Module 验证的用户名;$request_filename:当前请求的文件路径,由root或alias指令与 URL 请求生成;$scheme:HTTP 方法(如 http,https);$server_protocol:请求使用的协议,通常是 HTTP/1.0 或 HTTP/1.1;$server_addr:服务器地址,在完成一次系统调用后可以确定这个值;$server_name:服务器名称;$server_port:请求到达服务器的端口号;$request_uri:包含请求参数的原始 URL,不包含主机名,如/foo/bar.php?arg=baz;$uri:不带请求参数的当前 URL,$uri不包含主机名,如/foo/bar.html;$document_uri:与$uri相同。
4. 第三方模块
官方社区组织,包含 500+ 个 Nginx 模块仓库(如
nginx-rtmp-module、lua-nginx-module)。搜索具体模块名即可找到;精选列表,列出热门第三方模块(如
echo-nginx-module、headers-more-nginx-module)。从这里发现模块,然后去其 GitHub 仓库下载。
5. 其他
return指令:返回 HTTP 状态码和可选的第二个参数可以是重定向的 URL。
Nginxlocation /permanently/moved/url { return 301 http://www.example.com/moved/here; }rewrite指令:重写 URL 请求
rewrite,通过使用rewrite指令在请求处理期间多次修改请求 URL,该指令具有一个可选参数和两个必需参数。第一个参数(必需)是请求 URL 必须匹配的正则表达式;
第二个参数(必需)是用于替换匹配 URL 的 URL;
第三个参数(可选)是可以停止进一步重写指令的处理或发送重定向(代码 301 或 302)的标志。
Nginxlocation /users/ { rewrite ^/users/(.*)$ /show?user=$1 break; }error_page指令:使用
error_page指令(与location同级),您可以配置 Nginx 返回自定义页面以及错误代码,替换响应中的其他错误代码,或将浏览器重定向到其他 URL。Nginxerror_page 500 502 503 504 /50x.html;deny指令:禁止访问某个目录
Nginxlocation ~* \.(txt|doc)${ root $doc_root; deny all; }启用 Gzip 压缩以提高传输效率:
Nginxgzip on; gzip_types text/plain text/css application/javascript;使用缓存头减少静态文件请求:
Nginxlocation ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { expires 30d; add_header Cache-Control "public"; }