一、关键文件、目录和命令
NGINX 文件和目录
/etc/nginx
服务器的默认配置根
/etc/nginx/nginx.conf
默认配置文件
/etc/nginx/conf.d/
目录包含默认的HTTP服务器配置文件
/var/log/nginx/
nginx的默认日志位置
PS:以上默认目录和文件均可在安装nginx或者nginx.conf文件修改
二、nginx命令
nginx -h
显示NGINX帮助菜单
nginx -v
显示NGINX版本
nginx -V
显示NGINX版本、build信息和配置参数
nginx -t
测试NGINX配置
nginx -T
测试NGINX配置并将验证后的配置打印到屏幕上。
nginx -s signal
-s 标记向 NGINX master 进程发送信号。您可以发送 stop、quit、reload 和reopen 等信号。stop 信号可立即停止 NGINX 进程。quit 信号会在完成当前正在处理的请求后停止 NGINX 进程。reload 信号可重新加载配置。reopen 信号指示NGINX 重新打开日志文件。
三、获取客户端真实IP
1.配置nginx
首先,我们需要在Nginx的配置文件nginx.conf中添加如下配置
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
各参数的含义如下所示。
Host包含客户端真实的域名和端口号;X-Forwarded-Proto表示客户端真实的协议(http还是https);X-Real-IP表示客户端真实的IP;X-Forwarded-For这个Header和X-Real-IP类似,但它在多层代理时会包含真实客户端及中间每个代理服务器的IP。
2.通过Java方法获取客户端信息
仅仅配置Nginx不能彻底解决问题,那如何才能解决这个问题呢?一种解决方式就是通过Java方法获取客户端信息,例如下面的Java方法。
/***
* 获取客户端IP地址;这里通过了Nginx获取;X-Real-IP
*/
public static String getClientIP(HttpServletRequest request) {
String fromSource = "X-Real-IP";
String ip = request.getHeader("X-Real-IP");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Forwarded-For");
fromSource = "X-Forwarded-For";
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
fromSource = "Proxy-Client-IP";
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
fromSource = "WL-Proxy-Client-IP";
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
fromSource = "request.getRemoteAddr";
}
return ip;
}
这种方式虽然能够获取客户端的IP地址,但是我总感觉这种方式不太友好,因为既然Servlet API提供了request.getRemoteAddr()方法获取客户端IP,那么无论有没有用反向代理对于代码编写者来说应该是透明的。
接下来,就Tomcat服务器为大家介绍下如何进行配置才能更加友好的获取客户端信息。
3.Tomcat服务器
使用Tomcat作为应用服务器,可以通过配置Tomcat的server.xml文件,在Host元素内最后加入:
<Valve className="org.apache.catalina.valves.RemoteIpValve" />
四、负载均衡
HTTP配置
upstream backend{
server 10.10.12.45:80 weight=1;
server app.example.com:80 weight=2;
server spare.example.com:80 backup;
}
server{
location / {
proxy_pass http://backend;
}
}
HTTP 的 upstream 模块控制着 HTTP 负载均衡。该模块定义了一个目标池 -- 它可以是 Unix 套接字、IP 地址和 DNS(域名服务)记录的任意组合,也可以是它们的混合使用配置。upstream 模块还定义了如何将任一个请求分发给任何上游(upstream)服务器。
负载均衡方式
例如最少连接、最短时间、通用哈希、随机算法或IP哈希
最少连接案例如下
upstream backend{
least_conn;
server backend1.example.com;
server backend2.example.com;
}
各方式详解
轮询
轮询是默认的负载均衡方式,还可以在轮询中加入权重,权重背后的算法只是加权平均值的统计概率。
最少连接
least_conn,顾名思义将当前请求代理到连接数最少的服务器,也会考虑权重
最短时间
least_time,与最少连接算法类似,它将请求代理到当前连接数最少的服务器,但首选平均响应时间最短的。此方法是最复杂的负载均衡算法之一,能够满足高性能 Web 应用的需求。最短时间在最少连接的基础上进行了优化,因为少量连接并不一定意味着最快的响应。使用此算法时,切记要考虑服务请求时间的统计差异。
通用哈希
hash,使用请求或运行时给定的文本、变量或两者的组合定义哈希值。NGINX 能够为当前请求生成哈希值并将其放在服务器上,从而在这些服务器之间分发负载。
随机
random,该方法用于指示 NGINX 从组中随机选择一台服务器,同时考虑服务器的权重。
IP哈希
ip_hash,此方法仅适用于 HTTP。IP 哈希算法使用客户端 IP 地址作为哈希。IP 哈希与通用哈希存在细微的不同,前者使用 IPv4 地址的前三个八进制位或整个IPv6 地址,而后者使用的是远程变量。也会考虑权重
五、健康检查
被动健康检查
upstream backend {
server backend1.example.com:1234 weight=1 max_fails=2 fail_timeout=60s;
server backend2.example.com:1234 weight=2 max_fails=2 fail_timeout=60s;
}
意思是在fail_timeout时间内失败了max_fails次请求后,则认为该上游服务器不可用,然后将该服务地址踢除掉。fail_timeout时间后会再次将该服务器加入存活列表,进行重试。
Nginx-plus主动健康检查
HTTP方式
http{
server{
#...
location / {
proxy_pass http://backend;
health_check interval=2s;
fails=2
passes=5
uri=/
match=welcome;
}
}
# 状态码是200,内容类型是"text/html"
# 正文包含"Welcome to nginx!"
match welcome{
status 200;
header Content-type = text/html;
body ~ "Welcome to nginx!";
}
}
此处的 HTTP 服务器健康检査配置通过每 2 秒向 UR!“!”发送 HTTP GET 请求来检查上游服务器的健康状况。我们无法为健康检査定义 HTTP 方法,只能执行 GET 请求,因为其他方法可能会更改后端系统的状态。上游服务器只有连续通过五次健康检查才能被认为是健康的。如果它们连续两次未通过检查,则被认定为不健康。上游服务器的响应必须匹配定义的 match 代码块,后者将状态码定义为 200,将请求头的Content-Type 值定义为'texthtm’,同时定义了响应正文中的字符串“Welcome tonginx!”。HTTP match 代码块具有三个指令:status、header 和 body。这三个指令均带有比较标记。
六、Nginx限流配置
配置参数
limit_req_zone只领设置参数
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
- limit_req_zone定义在http块中,$binary_remote_addr表示保存客户端IP地址的二进制形式。
- Zone定义IP状态及URL访问频率的共享内存区域。zone=keyword标识区域的名字,以及冒号后面跟区域大小。16000个IP地址的状态信息约1MB,所以示例中区域可以存储160000个IP地址。
- Rate定义最大请求速率。示例中速率不能超过每秒10个请求
设置限流
location / {
limit_req zone=mylimit burst=20 nodelay;
proxy_pass http://real_server;
}
burst排队大小,nodelay不限制单个请求间的时间
不限流白名单
geo $limit {
default 1;
192.168.2.0/24 0;
}
map $limit $limit_key {
1 $binary_remote_addr;
0 "";
}
limit_req_zone $limit_key zone=mylimit:10m rate=1r/s;
location / {
limit_req zone=mylimit burst=1 nodelay;
proxy_pass http://real_server;
}
上述配置中,192.168.2.0/24网段的IP访问是不限流的,其他限流。
IP后面的数字含义:
- 24表示子网掩码:255.255.255.0
- 16表示子网掩码:255.255.0.0
- 8表示子网掩码:255.0.0.0
七、缓存配置
浏览器配置
静态资源缓存用expire
location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
expires 2d;
}
# d表示天,day
Response Header中添加了Expires和Cache-Control,
静态资源包括(一般缓存)
- 普通不变的图像,如logo,图标等
- js、css静态文件
- 可下载的内容,媒体文件
协商缓存(add_header ETag/Last-Modified value)
- HTML文件
- 经常替换的图片
- 经常修改的js、css文件
- 基本不变的API接口
不需要缓存
- 用户隐私等敏感数据
- 经常改变的api数据接口
Nginx黑名单
一般配置
location / {
deny 192.168.1.1;
deny 192.168.1.0/24;
allow 10.1.1.0/16;
allow 2001:0db8::/32;
deny all;
}