Java进阶-Nginx基础
Nginx简介
- Nginx (engine x) 是一个高性能的HTTP(网络静态资源服务器)和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。
- 也就是说Nginx有2大作用
- 第一作用作为网络静态资源服务器:用来部署web的静态资源
- 第二作用是作为反向代理服务器:作为n个tomcat服务器的代理
- 动态请求:需要后台程序处理逻辑,比如:查询数据库数据-》后台技术:web技术
- 静态请求:处理静态资源(html、js、css)
- Nginx只能处理静态请求,Tomcat技能处理动态请求也能处理动态请求。
- 也就是说Nginx有2大作用
- Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日、开源。也有商业版本:Nginx plus–> 商业版
- 其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。
- Tomcat: 150并发; Nginx: 并发量官方文档5w,实际3w没有问题,而且占用内存150M左右
- 总结:
- Nginx就是一个后台服务器软件,跟tomcat一样,把项目包放到软件某个目录下即可
- Tomcat既可以存放静态资源、也可以存放动态资源;Nginx专门用来存放静态资源
正向代理和反向代理
正向代理
-
正向代理:比如要访问youtube,但是不能直接访问,只能先找个翻墙软件,通过翻墙软件才能访问youtube. 这种方式就叫做正向代理。
- 分析
- 客户端做代理服务器的相关配置(代理服务器的地址等),然后访问推特网站
- 代理服务器会将推特访问包装成访问代理服务器的请求
- 防火墙没有对代理服务器进行限制,会访问到墙外部署的代理服务器
- 代理服务器获取到封装请求,解封装去访问推特网站服务器
- 推特网站响应数据,代理服务器将响应数据进行包装,翻墙到客户端
- 客户端拿到包装的响应进行解包展示
- 正向代理的特点:
- 客户端是知道目标访问地址(代理服务器的地址)
- 代理服务器专门对客户端工作的
- 这台服务器专门为客户端工作,就是一个代理,所以叫代理服务器
反向代理
-
反向代理:指的是用户要访问youtube,但是youtube悄悄地把这个请求交给后台N台服务器中的其中一台来做,这种方式就是反向代理了。
- 分析:
- 客户端发送域名请求数据
- 由于请求量并发量非常大,因此后台部署了n台服务器
- 客户端请求数据先到nginx服务器
- nginx服务器来进行分配具体的目标服务器
- 目标服务器响应数据给nginx服务器,然后返回给客户端
- 这里的nginx服务器也是一个代理作用,但是它不是为客户端做代理,而是为服务器做代理,因此也叫反向代理服务器
- 反向代理特点:
- 主要给后台应用提供服务,代理的就是服务端,保护服务端,防止对外暴露,客户端有请求找我就行
- 对于客户端来说根本不知道请求的URI是有哪个服务器提供的服务
- 总结:
- 正向与反向:前端->后台,这是代表正方向,代理前端发请求就是正向代理,代理后端接收请求就是反向代理
- 正向代理服务就是代替客户端(前端)去向已知的服务器发送请求
- 反向代理服务器就是代替后端服务器去接收客户端的请求
负载均衡
常见的负载均衡策略
- 使用硬件负载均衡策略,如使用F5,Array等负载均衡器.(比较贵)
- 使用软件进行负载均衡Nginx, 自己封装的负载均衡服务器
- 如使用阿里云服务器均衡SLB
- 使用Nginx+Keepalived
- 其他软件负载均衡如LVS(Linux Virtual Server),haproxy等技术
Nginx优点
- Nginx 可以在大多数 Unix、Linux OS 上编译运行,并有 Windows 移植版。 Nginx 的1.4.0稳定版已经于2013年4月24日发布,一般情况下,对于新建站点,建议使用最新稳定版作为生产版本,已有站点的升级急迫性不高。
- Nginx 的源代码使用 2-clause BSD-like license。
- Nginx 是一个很强大的高性能Web和反向代理服务器,它具有很多非常优越的特性:
- 在连接高并发的情况下,Nginx是Apache服务器不错的替代品:Nginx在美国是做虚拟主机生意的老板们经常选择的软件平台之一。能够支持高达 50,000 个并发连接数的响应,感谢Nginx为我们选择了 epoll and kqueue作为开发模型。
nginx安装(单机)
Linux环境
- 下载安装包
- 打开网址
https://nginx.org/
,点击右侧download
,下载最新的Stable version,点击nginx-1.20.1
即可下载nginx-1.20.1.tar.gz
- 打开网址
- 将安装包上传到Linux的文件目录下:
/usr/local/software
文件夹下 -
安装所需要的依赖库文件:
yum install pcre -y yum install pcre-devel -y yum install zlib -y yum install zlib-devel -y
-
将安装包源码解压到指定安装目录
tar -zxvf nginx-1.20.1.tar.gz -C /usr/local/src
cd /usr/local/src/nginx-1.20.1
中,ls查看,会发现有个configure命令./configure --prefix=/usr/local/nginx
配置将源码编译到哪个目录下- 编译安装: 当前目录下执行
make && make install
-
在 /usr/local/nginx目录下,可以看到如下4个目录
conf 配置文件目录 html 默认的HTML页面目录 logs 日日志存放目录 sbin 执行命令目录
-
常用命令
启动命令:/usr/local/nginx/sbin/nginx 关闭命令:/usr/local/nginx/sbin/nginx -s stop 重启命令:/usr/local/nginx/sbin/nginx -s reload
- 注意:nginx默认使用的是80端口
- 可以使用
netstat -ano| grep 80
查看端口
- 访问浏览器:http://192.168.122.133(看到欢迎页面说明没问题)
- 注意:如果出现这个错误:./configure: error: C compiler cc is not found
- 执行这个命令:yum -y install gcc gcc-c++ autoconf automake make
MacOS环境
-
安装(可以用 brew 安装)
//安装(可以用 brew 安装) brew install nginx //查看 nginx 版本 nginx -v //启动 nginx nginx //也可以使用下面的命令启动,但是配置文件nginx.conf修改后用这个命令执行不生效,故不建议使用: brew services start nginx //查看 nginx 是否启动成功 //在浏览器中访问http://localhost:8080,如果出现欢迎界面,证明成功. //备注:端口号是在配置文件 nginx.conf 里面配置的,默认端口是 8080 ,配置文件的位置 /usr/local/etc/nginx //关闭nginx nginx -s stop //也可以使用下面的命令启动,但是配置文件nginx.conf修改后用这个命令执行不生效,故不建议使用: brew services stop nginx //修改配置后,重新加载nginx nginx -s reload //可能遇到的问题 端口被占用: 解决方法,修改 nginx.conf 文件里的端口号
Nginx的配置文件
Nginx基础概念
- 多进程模式
- 在Nginx中会启动Master和Worker两种进程
- 启动nginx之后,可以执行
ps -ef |grep nginx
命令查看,当前默认有1个master 2个worker 进程运行
- 启动nginx之后,可以执行
- 其中Master进程主要的工作:
- 接收客户端的请求
- 向Worker进程发送信号
- 监控Worker进程的状态
- 当Worker进程退出以后, 会自动重新启动新的Worker进程
- 其中Worker进程主要是用来处理客户端的连接
- 就是Master进程用来管理,Worker进程用来具体处理任务
-
至于多少个Worker进程,在nginx.conf中配置
//2个worker进程 worker_processes 2; events { # 每个worker进程的最大请求连接数 worker_connections 1024; }
- 在Nginx中会启动Master和Worker两种进程
- 配置文件结构
- 在/usr/local/nginx/conf目录下有个nginx.conf文件
- nginx.conf由多个块组成,最外面的块是main,main包含events和http,http包含多个upstream和多个server,server又包含多个location:
-
main(全局设置)、server(虚拟主机设置)、upstream(上游服务设置, 负载均衡服务器设置)和 location(URL匹配特定位置的设置)。
main块设置的指令将影响其他所有设置; server块的指令主要用于指定主机和端口;如果有多个服务器,那么对应的就有多个server upstream指令主要用于负载均衡,设置一系列的后端服务器; location块用于匹配网页位置,就是url中IP地址、域名后面的路径,到底去哪访问
-
这四者之间的关系式:server继承main,location继承server,upstream既不会继承其他设置也不会被继承。
-
Nginx通用语法
- 配置文件有指令和指令块构成
- 每条指令以分号(;)结尾, 指令和参数之间用空格符号进行分隔
- 指令块以
{}
大括号将多条指令组织在一起 include
语句允许组合多个配置文件以提升可维护性,导入其他配置文件- 使用
#
符号添加注释, 提高可读性 - 使用
$
符号引用变量 - 部分指令的参数支持正则表达式
常用配置
1.虚拟主机配置
//用于设置监听客户端访问的IP地址、域名 + 端口
server {
#端口 一个server就对应一个服务,每个服务都有端口
listen 80;
#域名
server_name localhost;
#资源路径,可以有多个location,用于匹配请求路径
location / { # /代表默认路径,根,如果找不到其他的路径,就默认到这个路径下
# nginx服务器的根目录
root html;
# 目录下的文件
index index.html index.htm;
}
}
- 一旦访问 http://localhost:80,则就会来到这个server,然后到html文件夹下找到index.html文件
2.日志文件
- nginx访问日志放在log/host.access.log下,并且使用main格式(支持自定义格式)
-
对于main格式配置如下:
#日志文件输出格式这个位置相当于全局设置,就是每一通到nginx的日志信息格式 #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; 查看日志内容命令:tail -n 100 -f access.log
- 日志文件切分
- 系统运行起来之后,我们需要对nginx日志的分析,得到响应耗时的url,请求时间,以及这段时间的请求量和并发量.通过分析找到优化系统的方案.所以需要运维人员对nginx的日志进行切割和分析处理.我们会通过定时器定时将日志按天/小时进行备份.
- 实现定时备份日志:
-
第一步:分析如何去实现日志切分,编写shell脚本(backuplog.sh)
#!/bin/sh BASE_DIR=/usr/local/nginx BASE_FILE_NAME=access.log CURRENT_PATH=$BASE_DIR/logs BAK_PATH=$BASE_DIR/datalogs CURRENT_FILE=$CURRENT_PATH/$BASE_FILE_NAME BAK_TIME=`/bin/date -d yesterday +%Y%m%d%H%M` BAK_FILE=$BAK_PATH/$BAK_TIME-$BASE_FILE_NAME mv $CURRENT_FILE $BAK_FILE $BASE_DIR/sbin/nginx -s reopen
- 修改脚本文件的访问权限:
chmod +x backuplog.sh
-
第二步:定时任务对脚本进行调度:
//添加定时调度,会打开一个文本编辑,用于添加任务内容 crontab -e //执行的任务内容,每隔1分钟,执行一下backuplog.sh脚本 */1 * * * * sh /usr/local/nginx/sbin/backuplog.sh
-
3.location配置(就是要在location中写哪些东西)
- 语法规则
-
语法规则:
location [=|~|~*|^~] /uri/ { … }
= 开头表示精确匹配 ^~ 开头表示uri以某个常规字符串开头,理解为匹配 url路径即可。nginx不对url做编码 ,因此请求为/static/20%/aa,可以被规则^~ /static/ /aa匹配到(注意是空格)。 ~ 开头表示区分大小写的正则匹配 ~*开头表示不区分大小写的正则匹配 / 通用匹配,任何请求都会匹配到。 多个location配置的情况下匹配顺序为: 首先匹配 =,其次匹配^~, 其次是按文件中顺序的正则匹配,最后是交给 / 通用匹配。当 有匹配成功时候,停止匹配,按当前匹配规则处理请求。
-
- 举例使用
-
匹配规则如下:
location = / { #规则A } location = /login { #规则B } location ^~ /static/ { #规则C } location ~ \.(gif|jpg|png|js|css)$ { #规则D } location ~* \.png$ { #规则E } location / { #规则H }
-
生产效果如下
访问根目录/, 比如http://localhost/ 将匹配规则A 访问 http://localhost/login 将匹配规则B http://localhost/register 则匹配规则H 访问 http://localhost/static/a.html 将匹配规则C 访问 http://localhost/a.gif, http://localhost/b.jpg 将匹配规则D和规则E,但是规则D顺序优先,规则E不起作用,而 http://localhost/static/c.png 则优先匹配到 规则C 访问 http://localhost/a.PNG 则匹配规则E, 而不会匹配规则D,因为规则E不区分大小写。 访问 http://localhost/a.xhtml 不会匹配规则F和规则G,http://localhost/a.XHTML不会匹配规则G,因为不区分大小写。规则F,规则G属于排除法,符合匹配规则但是不会匹配到,所以想想看实际应用中哪里会用到。 访问 http://localhost/category/id/1111 则最终匹配到规则H,因为以上规则都不匹配,这个时候应该是nginx转发请求给后端应用服务器,比如FastCGI(php),tomcat(jsp),nginx作为方向代理服务器存在。
-
-
实际应用配置如下
# 不输入任何路径,只输入域名+端口,就直接到首页 #直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。 #这里是直接转发给后端应用服务器了,也可以是一个静态首页 # 第一个必选规则 location = / { # proxy_pass 配置反向代理,转发给其他服务 proxy_pass http://tomcat:8080/index; } # 第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项 # 有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用 location ^~ /static/ { # root代表到当前nginx服务器的目录中去寻找 root /webroot/static/; } location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ { root /webroot/res/; } # 没找到任何路径,就会到这个 #第三个规则就是通用规则,用来转发动态请求到后端应用服务器 #非静态文件请求就默认是动态请求,自己根据实际把握 #毕竟目前的一些框架的流行,带.php,.jsp后缀的情况很少了 location / { proxy_pass http://tomcat:8080/ }
4.全局变量
-
官方内置的一些全局变量,配置文件中可以直接使用
官方配置:http://nginx.org/en/docs $args #请求中的参数值 $query_string #同 $args $arg_NAME #GET请求中NAME的值 $is_args #如果请求中有参数,值为"?",否则为空字符串 $uri #请求中的当前URI(不带请求参数,参数位于$args),可以不同于浏览器传递的$request_uri的值,它可以通过内部重定向,或者使用index指令进行修改,$uri不包含主机名,如"/foo/bar.html"。 $document_uri #同 $uri $document_root #当前请求的文档根目录或别名 $host #优先级:HTTP请求行的主机名>"HOST"请求头字段>符合请求的服务器名 $hostname #主机名 $https #如果开启了SSL安全模式,值为"on",否则为空字符串。 $binary_remote_addr #客户端地址的二进制形式,固定长度为4个字节 ...还有很多。。。
5.rewrite语法
- 用户重定向转发使用,客户端发送一个请求,可以使用rewrite语法重定向到其他地址
-
if(条件为: =~~*) return、break、rewrite
if ($remote_addr = 192.168.122.1) { return 401; }
-
rewrite是实现URL重写的关键指令,根据regex(正则表达式)部分内容,重定向到replacement,结尾是flag标记。
rewrite <regex> <replacement> [flag]; 关键字 正则 替代内容 flag标记
- 关键字:其中关键字rewrite不能改变
- 正则:兼容正则表达式语句进行规则匹配
- 替代内容:将正则匹配的内容替换成replacement
- flag标记:rewrite支持的flag标记
- flag标记说明:
- last #本条规则匹配完成后,继续向下匹配新的location URI规则
- break #本条规则匹配完成即终止,不再匹配后面的任何规则
- redirect #返回302临时重定向,浏览器地址会显示跳转后的URL地址
- permanent #返回301永久重定向,浏览器地址栏会显示跳转后的URL地址
- rewrite 可以配置在server,location,ifs
6.反向代理配置
-
在配置反向代理:
//proxy_pass url; proxy_pass http://192.168.182.100:8080
-
注意:反向代理之后,服务端获取客户端ip地址为nginx服务器地址,那么如何获取客户端地址呢?需要nginx设置真实的ip地址:
#设置客户端真实ip地址 # proxy_set_header x-real-ip $remote_addr; location = / { #设置客户端真实ip地址 proxy_set_header x-real-ip $remote_addr; # proxy_pass 配置反向代理 proxy_pass http://tomcat:8080/index; }
$remote_addr:
是全局变量,客户端的地址proxy_set_header
:设置请求头- 服务器端要从请求头中获取客户端的真实地址
-
使用步骤
- 把后台服务搭建好
- 部署数据库mysql,运行jar包
- 修改配置文件,把请求转发到后台应用
- 在/usr/local/nginx/conf/nginx.conf中的location中配置
- 把后台服务搭建好
7.负载均衡配置
- 就是一个地址对应n台服务器,那么nginx如何进行转发呢?这里就是配置转发的规则
-
设定负载均衡的服务器列表在Server模块配置
#upstream myproject { # 这里可以配置负载均衡的策略,默认是Round Robin #weigth参数表示权值,权值越高被分配到的几率越大 #max_fails 当有#max_fails个请求失败,就表示后端的服务器不可用,默认为1,将其设置为0可以关闭检查 #fail_timeout 在以后的#fail_timeout时间内nginx不会再把请求发往已检查出标记为不可用的服务器 #}
-
使用默认Round Robin 举例
#webapp upstream myapp { # 这里默认值 Round Robin server 192.168.122.133:8080 weight=1 max_fails=2 fail_timeout=30s; server 192.168.122.134:8080 weight=1 max_fails=2 fail_timeout=30s; }
- 负载均衡的策略
- upstream第一行可以设置负载均衡的策略,就是当一个地址有n台服务器对应时,以什么规则转发到某个服务器
Round Robin 每个轮流转发 默认 Least Connections 最少连接数,那个转发的少就转发到哪个 IP Hash 客户端请求的ip进行Hash运算 Generic Hash 自定义Hash的一个取值 Random 随机发送
-
举例
# 定义p2p upstream p2p { ip_hash; server 192.168.11.130:8888 weight=1; server 192.168.11.194:8888 weight=1; server 192.168.11.225:8888 weight=1; } # 转向p2p location / { proxy_pass http://p2p; }
动静分离
-
静态资源交给nginx处理最合适,动态资源转发给tomcat
-
举例:
//静态资源访问地址 location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|css|js)$ { root /datas/crm/static/; } //动态请求访问地址 location / { proxy_pass http://localhost:8080; }
- 第一步: 把静态资源存放到nginx可以访问的目录
- 第二部: 配置静态资源的目录
- 文件上传问题
- 文件、图片上传肯定是走动态资源,图片上传到tomcat服务器,那么会将文件资源存储到oss云存储,或者本地磁盘,如果存到了本地磁盘(oss云存储直接通过http访问,无需同步),那么这些静态资源如何同步到 nginx呢?
- 解决办法: nginx服务器有个网络磁盘,可以通过ntfs把网络磁盘映射为本地磁盘(百度查询)
- 对于静态资源的压缩处理
- 满足的条件
- 客户端发送的HTTP报头必须含有 “Accept-Encoding” 字段,且其值包含 “gzip” 这个压缩类型。一般浏览器都会发 “Accept-Encoding:gzip, deflate, sdch” 这样的报头。
- 服务器启用了gzip压缩,那么响应头会包含 Content-Encoding:gzip, 客户端根据这个来判断服务器返回的内容是否真正为gzip压缩过的内容。
- nginx.conf做如下配置
- 打开配置文件后,默认是
#gzip on;
注释的
# 开启gzip压缩 gzip on; # 文件达到多大开始压缩 gzip_min_length 1k; # 压缩基本, 1-9 级别越高, 越消耗cpu, 默认值为1 gzip_comp_level 2; # 压缩文件的类型, 对于jpg,png图片压缩效率不高 gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript; #根据客户端的HTTP头来判断,是否需要解压缩 gzip_vary on;
- 打开配置文件后,默认是
- 做压缩的目的是,会将js等静态资源进行压缩发送给浏览器,浏览器然后进行解压,提高传输效率
- 满足的条件