一:概念
nginx用来作为网关暴露到外面,里面负载均衡其他的应用服务器tomcat,当然,静态资源,js,图片,之类的可以直接放到nginx服务器,来加快访问速度;
和haproxy对比
1.nginx可以支持几万的并发连接数,在性能方面应该和haproxy都差不多,
2.使用起来简单一点,主要是通过配置文件来使用相应的模块
3.没有监控页面(这里说的nginx只说免费版本),haproxy有
4.haproxy完全免费,可以拿到4,7层数据来定制我们想要的任何功能,不过需要深入学习;nginx的话如果现有的模块不支持某个功能,要不使用商业版本(如果支持),要不自己开发模块来支持,比较困难
二:版本
1.http://nginx.org/ 免费版本 就是我们常说的nginx open source
2.https://www.nginx.com/ 商业版本,全称nginx plus
三:安装
两种安装方式
a.使用yum install直接安装编译好的版本,参考http://nginx.org/en/linux_packages.html#RHEL-CentOS
b.自己编译源码,好处就是可以指定编译的模块
考虑到以后有可能会增加模块,我们使用第二种方法安装
1.安装编译需要的工具包
[root@deappa17 soft]# yum -y install make zlib zlib-devel gcc-c++ libtool openssl openssl-devel
2.安装PCRE让Nginx 支持 Rewrite 功能
[root@deappa17 soft]# wget https://nchc.dl.sourceforge.net/project/pcre/pcre/8.43/pcre-8.43.tar.gz
[root@deappa17 soft]# tar zxvf pcre-8.43.tar.gz
[root@deappa17 soft]# cd pcre-8.43
[root@deappa17 pcre-8.43]# ./configure
[root@deappa17 pcre-8.43]# make && make install
[root@deappa17 pcre-8.43]# pcre-config --version
8.43
3.安装nginx
[root@deappa17 soft]# wget http://nginx.org/download/nginx-1.16.1.tar.gz
[root@deappa17 soft]# tar xzvf nginx-1.16.1.tar.gz
[root@deappa17 soft]# cd nginx-1.16.1
[root@deappa17 nginx-1.16.1]# ./configure --prefix=/usr/local/webserver/nginx --with-http_stub_status_module --with-http_ssl_module
[root@deappa17 nginx-1.16.1]# make
[root@deappa17 nginx-1.16.1]# make install
[root@deappa17 nginx-1.16.1]# /usr/local/webserver/nginx/sbin/nginx -v
nginx version: nginx/1.16.1
四:常用操作
1.启动nginx
[root@deappa17 nginx-1.16.1]# /usr/local/webserver/nginx/sbin/nginx
2.检查配置文件的正确性
用于已经启动,调整了配置文件,重新加载之前使用
/usr/local/webserver/nginx/sbin/nginx -t
3.其他常用命令
/usr/local/webserver/nginx/sbin/nginx -s reload # 重新载入配置文件,如果配置文件中配置的目录不存在,则不报错,但不生效,需要看日志来确认是否重新载入是否成功
/usr/local/webserver/nginx/sbin/nginx -s reopen # 重新打开日志文件,并不是重启nginx
/usr/local/webserver/nginx/sbin/nginx -s stop # 停止 Nginx
/usr/local/webserver/nginx/sbin/nginx -s quit # 平缓停止 Nginx
五:常用配置
这里不罗列所有的配置,如果需要可以参考nginx官网http://nginx.org/en/docs/,模块内部有详细全面的指令说明,可用内部变量及例子
1.配置成web服务器
http {
server {
listen 127.0.0.1:8080;
}
server {
listen 80;
server_name example.org www.example.org;
}
server {
listen 80 default_server;
location /some/path/ {
#...
}
location ~ \.html? {
#...
}
location /images/ {
root /data;
}
location / {
proxy_pass http://www.example.com;
}
// 可以使用内置变量$remote_addr,
// 参考每个模块最下面的变量说明,例如ngx_http_core_module模块内部可以使用的内置变量
//https://nginx.org/en/docs/http/ngx_http_core_module.html?&_ga=2.205840795.900571110.1585708043-1368246722.1570772956#variables
// 返回特定的响应码
location /wrong/url {
return 404;
}
location /permanently/moved/url {
return 301 http://www.example.com/moved/here;
}
// 重写http相应的内容
location / {
sub_filter /blog/ /blog-staging/;
sub_filter_once off;
}
location / {
sub_filter 'href="http://127.0.0.1:8080/' 'href="https://$host/';
sub_filter 'img src="http://127.0.0.1:8080/' 'img src="https://$host/';
sub_filter_once on;
}
// 处理错误
location /old/path.html {
error_page 404 /404.html;
}
location /old/path2.html {
error_page 404 =301 http:/example.com/new/path.html;
}
// 出现404转到后端
location /images/ {
root /data/www;
open_file_cache_errors off;
error_page 404 = /fetch$uri;
}
location /fetch/ {
proxy_pass http://backend/;
}
}
}
location匹配优先级
首先说明:匹配字符串有两种,正则表达式和普通字符串(非正则表达式)
1)遇到=号,直接返回,优先级最高
2)找到最长匹配的普通字符串,如果前面有^~则直接返回
3)找到匹配的正则表达式,直接返回
4)没有找到匹配的正则表达式,则使用步骤2匹配到的最长普通字符串匹配
2.提供静态资源
server {
root /www/data; // 资源位置
location / {
index index.htm index.html;
}
location /images/ {
autoindex on; // 返回列表目录页面
}
location /images2/ {
try_files $uri /images/default.gif; // 如果请求资源不存在,则返回默认的
}
location /images3/ {
try_files $uri $uri/ $uri.html =404; // 如果请求资源不存在,则返回404
}
location /images4/ {
try_files $uri $uri/ @backend; // 如果请求资源不存在,则定向到下面backend
}
location ~ \.(mp3|mp4) {
root /www/media;
}
location @backend {
proxy_pass http://backend.example.com;
}
// 优化性能相关
location /mp3 {
//默认情况下,NGINX处理文件传输本身,并在发送之前将文件复制到缓冲区中。启用
//sendfile指令消除了将数据复制到缓冲区的步骤,并允许将数据从一个文件描述符直接
//复制到另一个文件描述符。或者,为了防止一个快速连接完全占用工作进程,可以使用
//sendfile_max_chunk指令来限制单个sendfile()调用中传输的数据量(在本例中为1 MB):
sendfile on;
sendfile_max_chunk 1m;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
}
}
3.反向代理
location /some/path/ {
proxy_pass http://www.example.com/link/;
}
location ~ \.php {
proxy_pass http://127.0.0.1:8000;
}
// 设置header
location /some/path/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://localhost:8000;
}
// 阻止传递header
location /some/path/ {
proxy_set_header Accept-Encoding "";
proxy_pass http://localhost:8000;
}
// 配置缓存大小,默认已经启动
location /some/path/ {
proxy_buffers 16 4k;
proxy_buffer_size 2k;
proxy_pass http://localhost:8000;
}
// 关闭缓存
location /some/path/ {
proxy_buffering off;
proxy_pass http://localhost:8000;
}
// 绑定sorceip,比如有多网卡,或者其他的需求
location /app1/ {
proxy_bind 127.0.0.1;
proxy_pass http://example.com/app1/;
}
location /app2/ {
proxy_bind 127.0.0.2;
proxy_pass http://example.com/app2/;
}
location /app3/ {
proxy_bind $server_addr;
proxy_pass http://example.com/app3/;
}
4.http负载均衡
http {
upstream backend {
# no load balancing method is specified for Round Robin
#least_conn;
#ip_hash;
#Random 还可以加其他的参数,请参考官网
#https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/
server backend1.example.com;
server backend2.example.com;
server 192.0.0.1 backup;
# 如果一个服务器需要暂时从负载平衡循环中移除,可以使用down参数来标记它,
# 以保持当前客户端IP地址的散列。本服务器处理的请求被自动发送到组中的下一个服务器
server backend3.example.com down;
# 30秒内3次失败,则这台服务器标识为不可用30秒(30秒是否又可用了?)
server backend2.example.com max_fails=3 fail_timeout=30s;
#设置服务器将其权重从0恢复到一个标称值的时间,当不健康的服务器变得健康时,
#或服务器在一段时间后变得可用时(服务器被认为不可用)。默认值为0,即禁用慢启动。
server backend1.example.com slow_start=30s;
}
server {
location / {
proxy_pass http://backend;
}
}
}
5.TCP负载均衡
stream {
# ...
server {
listen 127.0.0.1:12345;
proxy_pass backend.example.com:12345;
proxy_bind 127.0.0.1:12345;
}
upstream stream_backend {
server backend1.example.com:12345;
server backend2.example.com:12345;
server backend3.example.com:12346;
# ...
}
}
6.限流
1)限制并发连接数
http {
limit_conn_zone $server_name zone=servers:10m;
server {
limit_conn servers 1000;
}
}
2)限制访问速率
http {
#...
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
server {
#...
location /search/ {
# 每秒处理一个请求,超出的直接返回503
limit_req zone=one;
}
location /search2/ {
# 每秒处理一个请求,超出的进入桶中延迟处理(以指定的速率处理,客户端会卡着),如果桶满了,则直接返回503
limit_req zone=one burst=5;
}
location /search3/ {
# 每秒处理一个请求,超出的进入桶中立即处理,好像桶中有个计时器,每进入一个请求加1,每过一秒
# 减1,如果计时器=5,则此时新来的请求直接返回503,此种配置可以应对突发的情况并且不延迟,突发的缓冲是5
# 个人认为此种方式比较完美
limit_req zone=one burst=5 nodelay;
}
}
}
3)限制下载带宽
http {
limit_conn_zone $binary_remote_address zone=addr:10m
server {
root /www/data;
// 正常可以打开5个连接,现代浏览器会直接打开3个连接
limit_conn addr 5;
location / {
}
location /download/ {
#限制打开1个连接
limit_conn addr 1;
#1M后开始限制,可以不要此参数,直接限制
limit_rate_after 1m;
limit_rate 50k;
}
}
}
7.缓存
http {
# 定义缓存的名称,单个缓存内容的最大size,总缓存的最大size,和缓存的目录(必须存在)
proxy_cache_path /data/nginx/cache keys_zone=mycache:10m max_size=10g;
# 定义一个变量$purge_method,他的值有$request_method决定
map $request_method $purge_method {
PURGE 1;
default 0;
}
# 创建变量,其值依赖于客户端IP地址
geo $purge_allowed {
default 0; # 默认不允许
192.168.100.17 1; # 本地允许
192.168.0.0/24 1; # 同一个网段允许
}
map $request_method $purge_method2 {
PURGE $purge_allowed;
default 0;
}
server {
# 使用缓存
proxy_cache mycache;
# 定义缓存的key
proxy_cache_key "$host$request_uri$cookie_user";
# 被请求多少次才被缓存,默认是1
proxy_cache_min_uses 5;
# 定义各种响应码的缓存时间(测试过程发现如果不定义此参数缓存不生效)
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
# 仅仅200, 301, and 302会被缓存
proxy_cache_valid 5m;
# 所有响应码会被缓存
proxy_cache_valid any 1m;
# 指定忽略响应头的内容,内容是否被缓存,还和响应头中的内容有关,比如响应头中有Set-Cookie字段
# 则响应的内容不会被缓存
proxy_ignore_headers Set-Cookie Cache-Control;
# 如果后面的几个参数,任何一个参数值不为空或者不等0,nginx就不会查找缓存,直接进行代理转发
proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment;
# 定义不需要缓存的情况,参数使用和proxy_cache_bypass一样
proxy_no_cache $http_pragma $http_authorization;
# 清除缓存,如果收到请求method=PURGE ,则清除指定的缓存,如果路径/*结尾,则清除匹配的所有缓存
# 并不会真正从磁盘清除,有三种条件可以真正从磁盘清除,如下
# proxy_cache_path使用purger=on或者inactive参数,或者下次访问此缓存时
proxy_cache_purge $purge_method;
# 除了清除缓存功能,可以限制访问此清除功能的客户端ip
proxy_cache_purge $purge_method2;
# 如果缓存的文件比较大,比如视频文件,可以切片缓存,具体可以参考
# https://docs.nginx.com/nginx/admin-guide/content-cache/content-caching/
location / {
proxy_pass http://localhost:8000;
}
}
}
六:常见问题
1.上传大文件失败,小文件可以
- client_body_buffer_size 配置请求体缓存区大小
- client_body_temp_path 设置临时文件存放路径,只有当上传的请求体超出缓存区大小时,才会写到临时文件中
- client_max_body_size 设置上传文件的最大值
通过设置client_max_body_size 100m解决掉
2.防止恶意攻击某个地址,比如发短信
location ~ /account(/.*)
{
if ($http_referer ~ "https://www.xxxxxxxx.net/account/sendPhoneCode") {
#如果匹配就直接返回200,返回404,也行啊,自己定。给可爱的攻击者,不传给后端web
return 200;
}
#不匹配,传给后端web
proxy_pass http://web_group;
}
参考网站: