文章目录
- 一.nginx简单介绍
- 二.安装nginx和tomcat
- 三.nginx配置
- 四.负载均衡策略
-
- 4.1 轮询
- 4.2 最少连接
- 4.3 权重
- 4.4 ip_hash
- 五. session共享
-
- 5.1 不使用session,换作cookie
- 5.2 应用服务器自行实现共享
- 5.3 ip_hash
- 5.4 upstream_hash
- 六.关于限流
-
- 6.1 ngx_http_limit_conn_module
- 6.2 ngx_http_limit_req_module
- 七.vue打包dist放在nginx下的配置
-
- 7.1 配置文件
- 附录:
-
- 1.资料参考:
- 2. 零星知识点:
一.nginx简单介绍
Nginx是一款轻量级兼备高性能的Http和反向代理服务器。所谓反向代理就是指在用户发起访问请求,由代理服务器接收,然后将请求转发给正式服务器,并且将正式服务器处理完的数据返回给客户端,此时代理服务器就表现为一个服务器。这么做看起来多经过了一步,稍显麻烦,但实则是好处多多.
-
热部署
我个人觉得这个很不错。在master管理进程与worker工作进程的分离设计,使的Nginx具有热部署的功能,那么在7×24小时不间断服务的前提下,升级Nginx的可执行文件。也可以在不停止服务的情况下修改配置文件,更换日志文件等功能。
-
可以高并发连接
这是一个很重要的一个特性!在这一个 互联网 快速发展, 互联网 用户数量不断增加,一些大公司、网站都需要面对高并发请求,如果有一个能够在峰值顶住10万以上并发请求的Server,肯定会得到大家的青睐。理论上,Nginx支持的并发连接上限取决于你的内存,10万远未封顶。
-
低的内存消耗
在一般的情况下,10000个非活跃的HTTP Keep-Alive 连接在Nginx中仅消耗2.5M的内存,这也是Nginx支持高并发连接的基础。
-
处理响应请求很快
在正常的情况下,单次请求会得到更快的响应。在高峰期,Nginx可以比其他的Web服务器更快的响应请求。
-
具有很高的可靠性
Nginx是一个高可靠性的Web服务器,这也是我们为什么选择Nginx的基本条件,现在很多的网站都在使用Nginx,足以说明Nginx的可靠性。高可靠性来自其核心框架代码的优秀设计、模块设计的简单性;并且这些模块都非常的稳定。
二.安装nginx和tomcat
nginx的安装教程参见<使用fastDFS从头搭建文件服务器>;
tomcat的安装教程参见CentOS中的<阿里云centOS手工部署Java Web项目>.
三.nginx配置
常用命令:
#打开配置文件
# vi /usr/local/nginx/conf/nginx.conf
#查看nginx进程
#ps aux |grep nginx
# cd /usr/local/nginx/sbin/
# ./nginx
或者直接:
启动
# /usr/local/nginx/sbin/nginx
停止
# /usr/local/nginx/sbin/nginx -s stop
重启
# /usr/local/nginx/sbin/nginx -s reload
其它命令
# ./nginx -s stop
# ./nginx -s quit
# ./nginx -s reload
#使用用户与安装用户保持一致,不然可能会报403 Forbidden,window下不指定
user root;
#启动进程,通常设置成和cpu的数量相等
worker_processes 1;
#工作模式及连接数上限
events {
use epoll; #epoll是多路复用IO(I/O Multiplexing)中的一种方式,但是仅用于linux2.6以上内核,可以大大提高nginx的性能;使用网络IO模型linux建议epoll,FreeBSD建议采用kqueue,window下不指定。
worker_connections 1024; #51200=1024*50,单个后台worker process进程的最大并发链接数
}
#设定http服务器,利用它的反向代理功能提供负载均衡支持
http {
#设定mime类型,类型由mime.type文件定义
include /etc/nginx/mime.types;
default_type application/octet-stream;
#设定日志格式
#access_log /var/log/nginx/access.log;
#sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,对于普通应用,
#必须设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为 off,以平衡磁盘与网络I/O处理速度,降低系统的uptime.其主要作用是加快对静态文件的处理。默认情况下是开启(on)状态。
sendfile on;
tcp_nopush on;#属于nginx静态资源配置模块,把多个包一次性整合之后再发送给客户端,而不是一次次发,在sendfile开启的情况下,提高网络包的传输效率,可在http、server和location中配置,默认是关闭(off)状态。
tcp_nodelay on;#属于nginx静态配置模块,尽量的把包发送出去,不要等待,用在实时性有要求的场景。一般在keepalive连接下,提高网络 包的传输实时性,可在http、server和location中配置,默认是开启(on)状态。看上去是和tcp_nopush相反的功能,但是两边都为on时nginx也可以平衡这两个功能的使用。
#连接超时时间
#keepalive_timeout 0;
keepalive_timeout 65;
#设定负载均衡的服务器列表,这里的域名要和下面proxy_pass的一样
upstream test {
#weigth参数表示权值,权值越高被分配到的几率越大
#本机上的Squid开启3128端口
server 192.168.8.1:3128 weight=5;
server 192.168.8.2:80 weight=1;
server 192.168.8.3:80 weight=6;
}
server {
#侦听80端口
listen 80;
#限制文件上传的大小,默认为1m,设为0表示无限制
#client_max_body_size 32m;
#定义使用www.xx.com访问,一般没什么用.目前知道的作用是虚拟主机:两个域名解析到同一个IP地址,监听同一个端口号,但是用户通过两个域名却可以打开两个完全不同的网站,互相不影响,就像访问两个服务器一样,所以叫两个虚拟主机。虚拟主机的原理是通过HTTP请求头中的Host是否匹配server_name来实现的
server_name test;
#设定本虚拟主机的访问日志
#access_log logs/www.xx.com.access.log main;
#默认请求转发给后端服务器
location / {
#Host 这个不配置Request().getServerPort()拿到的端口会是默认的80
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://test;
}
#静态资源路径访问配置
location ^~/static/ {
alias /var/www/static/;
#或者用root /var/www/;
}
}
}
四.负载均衡策略
4.1 轮询
这种是默认的策略,把每个请求按顺序逐一分配到不同的server,如果server挂掉,能自动剔除。
upstream fengzp.com {
server 192.168.99.100:42000;
server 192.168.99.100:42001;
}
4.2 最少连接
把请求分配到连接数最少的server
upstream fengzp.com {
least_conn;
server 192.168.99.100:42000;
server 192.168.99.100:42001;
}
4.3 权重
使用weight来指定server访问比率,weight默认是1。以下配置会是server2访问的比例是server1的两倍。
upstream fengzp.com {
server 192.168.99.100:42000 weight=1;
server 192.168.99.100:42001 weight=2;
}
4.4 ip_hash
每个请求会按照访问ip的hash值分配,这样同一客户端连续的Web请求都会被分发到同一server进行处理,可以解决session的问题。如果server挂掉,能自动剔除。[如果只剩一个服务器了,ip_hash还是能访问到的,不用担心]
upstream fengzp.com {
ip_hash;
server 192.168.99.100:42000;
server 192.168.99.100:42001;
}
ip_hash可以和weight结合使用。
五. session共享
5.1 不使用session,换作cookie
能把session改成cookie,就能避开session的一些弊端,在从前看的一本J2EE的书上,也指明在集群系统中不能用session,否则惹出祸端来就不好办。如果系统不复杂,就优先考虑能否将session去掉,改动起来非常麻烦的话,再用下面的办法。
5.2 应用服务器自行实现共享
asp.net可以用数据库或memcached来保存session,从而在asp.net本身建立了一个session集群,用这样的方式可以令 session保证稳定,即使某个节点有故障,session也不会丢失,适用于较为严格但请求量不高的场合。但是它的效率是不会很高的,不适用于对效率 要求高的场合。
以上两个办法都跟nginx没什么关系,下面来说说用nginx该如何处理:
5.3 ip_hash
nginx中的ip_hash技术能够将某个ip的请求定向到同一台后端,这样一来这个ip下的某个客户端和某个后端就能建立起稳固的session,ip_hash是在upstream配置中定义的:
upstream backend {
server 127.0.0.1:8080 ;
server 127.0.0.1:9090 ;
ip_hash;
}
ip_hash是容易理解的,但是因为仅仅能用ip这个因子来分配后端,因此ip_hash是有缺陷的,不能在一些情况下使用:
- nginx不是最前端的服务器。ip_hash要求nginx一定是最前端的服务器,否则nginx得不到正确ip,就不能根据ip作hash。譬如使用的是squid为最前端,那么nginx取ip时只能得到squid的服务器ip地址,用这个地址来作分流是肯定错乱的。
- nginx的后端还有其它方式的负载均衡。假如nginx后端又有其它负载均衡,将请求又通过另外的方式分流了,那么某个客户端的请求肯定不能定位到同一台session应用服务器上。这么算起来,nginx后端只能直接指向应用服务器,或者再搭一个squid,然后指向应用服务器。最好的办法是用location作一次分流,将需要session的部分请求通过ip_hash分流,剩下的走其它后端去。
5.4 upstream_hash
为了解决ip_hash的一些问题,可以使用upstream_hash这个第三方模块,这个模块多数情况下是用作url_hash的,但是并不妨碍将它用来做session共享。
六.关于限流
6.1 ngx_http_limit_conn_module
官方文档
- limit_conn_zone:
语法规则:[key可以是$binary_remote_addr,$server_name,$server_port,$uri等]
Syntax: limit_conn_zone key zone=name:size;
Default: —
Context: http
- limit_conn:
语法规则:
Syntax: limit_conn zone number;
Default: —
Context: http, server, location
- 示例:
http {
limit_conn_zone $binary_remote_addr zone=addr:10m;
...
server {
...
location /download/ {
limit_conn addr 1;
}
}
...
}
6.2 ngx_http_limit_req_module
官方文档
- limit_req_zone
语法规则:
Syntax: limit_req_zone key zone=name:size rate=rate [sync];
Default: —
Context: http
- limit_req
Syntax: limit_req zone=name [burst=number] [nodelay | delay=number];
Default: —
Context: http, server, location
- 示例
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;#1r/s表示1秒钟一个请求,1r/m表示1分钟一个请求,但2r/m等价于30秒一个请求.如果想实现一分钟内瞬间接受两个请求,那就要用2r/m配合burst=1来实现了.
...
server {
...
location /search/ {
limit_req zone=one burst=5 nodelay;
}
}
...
}
- 酒店项目配置示例:
http {
limit_req_zone $server_name zone=reqperserver:10m rate=2r/m;
limit_conn_zone $server_name zone=perserver:10m;
limit_conn_zone $uri zone=peruri:10m;
include 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 logs/access.log main;
sendfile on;
tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 30;
tcp_nodelay on;
#gzip on;
upstream hotelmanage.jsjunyi.com {
ip_hash;
#weigth参数表示权值,权值越高被分配到的几率越大
#本机上的Squid开启3128端口
server 127.0.0.1:8081;
server 127.0.0.1:8082;
}
server {
#设置文件上传大小限制
client_max_body_size 200M;
listen 8080;
server_name hotelmanage.jsjunyi.com;
#charset koi8-r;
#access_log logs/host.access.log main;
location ^~/hotel/photo/ {
alias /data/hotel/photo/;
}
location ^~/hotel/uploads/software {
#limit_req zone=reqperserver burst=1 nodelay;
limit_rate 1000k;
limit_conn perserver 3;
#limit_conn peruri 3;
alias /data/hotel/software/;
}
location / {
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://hotelmanage.jsjunyi.com;
}
}
}
#以上配置一个灵异的点在于:
location ^~/hotel/uploads/software
改为
location ^~/uploads/software
时是不起作用的,这就说明location配置的时候,最好从端口号之后就开始匹配.
七.vue打包dist放在nginx下的配置
7.1 配置文件
server {
#侦听10010端口
listen 9191;
#限制文件上传的大小,默认为1m,设为0表示无限制
client_max_body_size 200m;
#定义使用www.xx.com访问
server_name 10.58.21.170;
#设定本虚拟主机的访问日志
#access_log logs/www.xx.com.access.log main;
location ^~/hotel/photo/ {
alias /data/hotel/photo/;
}
location ^~/hotel/uploads/software/ {
alias /data/hotel/software/;
}
#location /hotel/main/ {
# root /data/;
# index /hotel/dist/index.html;
# try_files $uri $uri/ /hotel/dist/index.html;
#}
#location /hotel/dist/ {
# alias /data/hotel/dist/;
#}
#前端路由配置,访问/fontEndHotel下的某个文件,找不到就返回/fontEndHotel/dist/index.html
location /fontEndHotel/ {
root /data/hotel/;
index /fontEndHotel/dist/index.html;
try_files $uri $uri/ /fontEndHotel/;#这里/fontEndHotel/也可以写成/fontEndHotel/dist/index.html
}
#默认请求转发给后端服务器
location / {
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://10.58.21.170;
}
}
#最重要的是做到前端路由和后端路由的区分,不能都是/hotel/...,这样就没办法用location进行区分,只要是区分开的,这边配置就简单了,就是两个location的事情.建议前端保持不变,后端不用hotel,用hotelapi之类的,前端毕竟是要展示在页面上的,用hotel比较好.
附录:
1.资料参考:
Nginx静态文件路径配置:root目录与alias目录的区别
使用Nginx实现Tomcat集群负载均衡
Nginx +tomcat 实现负载均衡集群
nginx反向代理后,jsp页面request.getServerPort()获取得端口号总是80解决方案
nginx+tomcat影响request值
Nginx http_limit_req模块详解
Nginx一种限流方案
nginx集群tomcat,session共享问题
NGINX 借助JEDIS 对TOMCAT做SESSION共享
2. 零星知识点:
- 语法规则: location [=||*|^~] /uri/ { … }
= 开头表示精确匹配
^~ 开头表示uri以某个常规字符串开头,理解为匹配 url路径即可。nginx不对url做编码,因此请求为/static/20%/aa,可以被规则^~ /static/ /aa匹配到(注意是空格)。
~ 开头表示区分大小写的正则匹配
~* 开头表示不区分大小写的正则匹配
!~和!~*分别为区分大小写不匹配及不区分大小写不匹配 的正则
/ 通用匹配,任何请求都会匹配到。
多个location配置的情况下匹配顺序为(参考资料而来,还未实际验证,试试就知道了,不必拘泥,仅供参考):
首先匹配 =,其次匹配^~, 其次是按文件中顺序的正则匹配,最后是交给 / 通用匹配。当有匹配成功时候,停止匹配,按当前匹配规则处理请求。
- 服务器集群的名称不能包含下划线??
- alias和root的区别:
root:真实的路径是root指定的值加上location指定的值。结尾的/可加可不加.
alias:指定的路径是location的别名,不管location的值怎么写,资源的真实路径都是 alias 指定的路径