Nginx
Nginx介绍
Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好
Nginx安装
- 在nginx: download下载Nginx安装包,选择稳定版本,然后上传到虚拟机上,如果虚拟机能连上网,也可以使用wget [安装地址],如果wget这个命令找不到,执行
yum install wget
安装相应资源 - 安装依赖包
yum -y install gcc pcre-devel zlib-devel openssl openssl-devel
- 解压
tar -xvzf nginx-1.24.0.tar.gz
- 进入目录
cd nginx-1.24.0
- 执行命令
./configure --prefix=/opt/module/nginx-1.24.0
,需要先创建目录/opt/module/nginx-1.24.0
- 编译并安装
make && make install
安装完成后,可以进入到/opt/module/nginx-1.24.0目录下查看目录结构
里面有四个文件:
- conf:配置文件夹
- html:静态资源文件夹
- logs:日志文件夹
- sbin:相关命令文件夹
Nginx命令
- 查看版本:
sbin/nginx -v
- 检查配置文件的正确性:
sbin/nginx -t
如果提示错误:
nginx: [emerg] bind() to 0.0.0.0:80 failed (13: Permission denied)
nginx: configuration file /opt/module/nginx-1.24.0/conf/nginx.conf test failed
说没有权限,就执行命令:sudo sbin/nginx -t 或者切换到root用户再执行这个命令
- 启动Nginx服务:
sbin/nginx
- 可以通过
ps -ef | grep nginx
查看nginx进程 - 可以看到默认有两个进程,master和worker,第三个进程是执行命令所对应的进程,忽略掉
- 可以通过修改配置文件修改,worker进程可以有多个
- 可以通过
启动起来后就可以访问到首页了也就是在html文件夹下的index.html文件
在浏览器输入IP地址,端口号为80(可以省略)
如果访问不了,有可能是防火墙的原因,关闭防火墙
systemctl stop firewalld
- 停止Nginx服务:
sbin/nginx -s stop
经过一次启停后,再次查看nginx-1.24.0的目录结果会发现多出几个临时文件(不用管)
进入logs文件夹,查看里面的文件,里面有一些日志文件保存在access.log,如果出错了,日志则会保存在error.log
再次启动nginx,查看logs里面的文件,可以看到里面多出一个pid的文件,可以使用
cat nginx.pid
查看里面内容,里面保存的是当前nginx的进程号,如果停掉当前的nginx,那这个nginx.pid的文件也就会消失
- 重新加载配置文件命令:
sbin/nginx -s reload
当修改Nginx配置文件后,需要重新加载才能生效
- 配置环境变量,简化命令,在/etc/profile.d/my_env.sh文件加上NGINX_HOME和PATH
#NGINX_HOME
export NGINX_HOME=/opt/module/nginx-1.24.0
export PATH=$PATH:$NGINX_HOME/sbin
Nginx配置文件结构
Nginx配置文件(nginx.conf)整体分为三部分:
- 全局块:和Nginx运行相关的全局配置
- events块:和网络连接相关的配置
- http块:代理、缓存、日志记录、虚拟主机配置
- http全局块
- Server块
- Server全局块
- location块
注意:http块中可以配置多个Server块,每个Server块中可以配置多个location块
以下是原始的删除注释后的nginx.conf文件内容:
#全局块
worker_processes 1; # 一个worker进程一般一个CPU内核对应一个
#events块
events {
worker_connections 1024; # 表示每个worker进程可以创建多少个连接
}
#http块
http {
#http全局块
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65; # 保持连接
#Server块
server {
#Server全局块
listen 80; #监听端口
server_name localhost; #服务器名称,域名/主机名
#location块
location / { #这里的'/'表示所有请求都归这个location处理,uri
root html; #root指的是根,就是Nginx目录下的html文件夹
#index表示首页,可以配置多个中间空格隔开,这里的意思是index.html没有就index.htm
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
Nginx具体应用
部署静态资源
Nginx可以作为静态web服务器来部署静态资源。静态资源指在服务端真实存在并且能够展示一些文件,比如:常见的html页面,css文件,js文件,图片,视频等资源
相对于Tomcat,Nginx处理静态资源的能力更加高效,所以在生产环境下,一般都会将静态资源部署到Nginx中。将静态资源部署到Nginx中非常简单,只需要将文件复制到Nginx安装目录下的html目录中即可,然后就是修改一些配置
#Server块
server {
#Server全局块
listen 80; #监听端口
server_name localhost; #服务器名称
#location块
location / { #这里的'/'表示所有请求都归这个location处理
root html; #root指的是根,就是Nginx目录下的html文件夹
#index表示首页,可以配置多个中间空格隔开,这里的意思是index.html没有就index.htm
index index.html index.htm;
}
反向代理
正向代理
是一个位于客户端和原始服务器之间的服务器,为了从原始服务器取得内容,客户端向代理服务器发送了一个请求并指定目标(原始服务器),然后代理服务器开始向原始服务器转交请求并将获得的内容返回给客户端。
正向代理的典型用途是为在防火墙内的局域网客户端提供访问Internet的途径
正向代理一般是在客户端设置代理服务器,通过代理服务器转发请求,最终访问到目标服务器
正向代理是明确知道我访问的原始服务器的过程中是经过了中间代理服务器的
- 反向代理
反向代理服务器位于用户与目标服务器之间,但是对于用户而言,反向代理服务器就相当于目标服务器,即用户直接访问反向代理服务器就可以获得目标服务器的资源,反向代理服务器负责将请求转发给目标服务器。
用户不需要直到目标服务器的地址,也无需在用户端作任何设定
也就是说,反向代理用户不知道自己访问的过程中还有代理服务器的存在
- 配置反向代理,在192.168.10.103的服务器上配置
server{
listen 82;
server_name location;
location / {
proxy_pass http://192.168.10.102:8080; #反向代理配置,将请求转发到指定服务
}
}
负载均衡
随着业务流量越来越大且业务逻辑也越来越复杂,单台服务器的性能及单点故障问题就凸显出来了,因此需要多台服务器组成应用集群,进行性能的水平扩展以及避免单点故障问题
- 应用集群:将同一应用部署到多台机器上,组成应用集群,接收负载均衡器分发的请求,进行业务处理并返回响应数据
- 负载均衡器:将用户请求根据对应的负载均衡算法分发到应用集群中的一台服务器进行处理
有点类似反向代理,但其实就是使用的反向代理,只不过代理服务器代理的不只是一台服务器
- 配置负载均衡:
upstream targetserver { #upstream指令可以定义一组服务器,后面的targetserver这个随意,一个名字而已
server 192.168.10.101:8080;
server 192.168.10.102:8081;
}
server {
listen 8080;
server_name localhost;
location / {
proxy_pass http://targetserver; #意思就是一个请求过来,转发到这组服务器,默认负载均衡策略是轮询
}
}
负载均衡策略:
名称 | 说明 |
---|---|
轮询 | 默认方式 |
weight | 权重方式,给服务器指定权重,越大处理越多请求 |
ip_hash | 依据ip分配方式 |
least_conn | 依据最少连接方式 |
url_hash | 依据url分配方式 |
fair | 依据响应时间方式 |
虚拟主机与域名解析
#虚拟主机
server {
listen 80;
server_name www.abcxxx.com;
#location块
location / {
root /www/abc;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
# 虚拟主机
server {
listen 80;
server_name www.defxxx.com; # 和上面的端口号一样,但是server_name不一样
#location块
location / {
root www/def;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
注意:
listen
+server_name
要唯一即,端口号相同,那主机名/域名一定不能相同
主机名/域名相同,端口号一定不能相同
不然报错!!
注意server块括号的位置,容易搞错
server_name匹配规则
- 可以在一个server_name 写多个站点,匹配多个,如下:
#虚拟主机
server {
listen 80;
server_name www.abc.com;
#location块
location / {
root /www/abc;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
# 虚拟主机
server {
listen 80;
server_name www.defxxx.com xxxdefxxx.com; # 这里就可以匹配上两个
#location块
location / {
root www/def;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
- 通配符匹配:可以使用
*
匹配任意字符
#虚拟主机
server {
listen 80;
server_name www.abc.com;
#location块
location / {
root /www/abc;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
# 虚拟主机
server {
listen 80;
server_name *.defxxx.com; # 前面是任意,后面必须是defxxx.com的
# server_name defxxx.*; # 前面必须是defxxx.后面可以任意
#location块
location / {
root www/def;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
- 正则匹配:可以使用正则匹配主机名
#虚拟主机
server {
listen 80;
server_name www.abc.com;
#location块
location / {
root /www/abc;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
# 虚拟主机
server {
listen 80;
server_name ^~[0-9]+\.abc\.com$; # 数字开头的:数字.abc.com
#location块
location / {
root www/def;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
配置中,是按照从上往下来找的,如果一个路径在一个配置文件中有两个匹配上的地方(就是它满足两个虚拟主机的筛选条件),谁先写,谁处理,后写的不会收到请求
反向代理
- 关键字:
proxy_pass
- 写了
proxy_pass
就不用写root
和index
了 - 配置在
location块
的
# 别名,和server同级
upstream httpsd {
server 192.168.10.100;
server 192.168.10.101;
}
server {
listen 80;
server_name localhost;
#location块
location / {
proxy_pass httpsd; # 这个`httpsd`是一个别名
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
负载均衡策略
轮询
- 默认方式,逐一转发,这种方式适用于无状态请求
- 缺点:无法保持会话,如果登录的请求在第一台服务器,那第一台服务器保存了其会话,那轮询访问另外一台服务器的时候,它是没有之前的会话消息的,那可能会提示用户还需要登录,所以轮询,就这么单纯的使用是不行的
weight(权重)
- weight:权重,给服务器加上
weight=数值
,数值越大,根据轮询的负载均衡算法,那这台服务器所分配到的请求也会更多 - backup:备用机,当当前状态下没有服务器可以正常工作,备用机上场,平时不会工作
- down:加上后就认为它宕机了,不会再给他分配任务
upstream httpsd {
# 配置在这里!!
server 192.168.10.100 weight=8;
server 192.168.10.101 weight=2 down;
server 192.168.10.102 weight=3 backup;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass httpsd; # 这个`httpsd`是一个别名
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
backup
和down
都不怎么常用
backup
备用机,在前面没有工作的服务器的时候工作,那么前面工作的服务器为什么没法工作了,难道备用机上场就有用了?一般来讲服务器处在同一环境,到底是因为网络带宽或者什么其他原因导致服务器无法工作,备用机上场也不一定好使。但也是可以留一台备用机down
指定某个服务器宕机,我明确知道这台服务器宕机了,我还去配置文件去给它加个down,有这时间我可以快速去修复一台去启动一台服务器
weight
指定轮询权重,还是比较有用的,每台服务器的配置不同,配置高的服务器可以给他高点的权重,达到负载均衡
这几个关键字都是配置在upstream里的
想要动态地实现服务器的上下先,单靠Nginx的基础命令是不行的,因为每次修改配置文件都要去执行
systemctl reload nginx
重新加载一下
ip_hash
- 根据客户端的ip地址转发同一台服务器,可以保持会话
这个目前基本不用,拿手机举例,我在某个地方发送了请求,这网络时好时坏,我走几步换个地方,它给我换个基站,拿我的ip就变了,所以这样也没法保证会话
least_conn
- 最少连接访问
url_hash
- 根据用户的url定向转发请求
fair
- 根据后端服务器响应时间转发请求
ip_hash,least_conn,url_hash,fair,这四种负载均衡策略目前都不再使用了
动静分离
- 这是一种常用的性能优化技术
- 通过将动态请求和静态资源请求分发到不同的服务器或处理程序上,可以提高网站的响应速度和并发能力
通常情况下,网站由动态内容和静态资源组成。
动态内容是指需要经过服务器端处理的数据,比如动态网页、数据库查询等。
静态资源是指不需要经过服务器端处理的文件,如HTML、CSS、JavaScript、图片、音视频等。
步骤:
- 配置静态资源服务器:将网站的静态资源(如图片、CSS、JavaScript等)存放在一个或多个独立的静态资源服务器上,可以是单独的物理服务器或者虚拟主机。
- 配置动态内容服务器:将网站的动态内容(如PHP、Java、Python等程序生成的网页)存放在一个或多个独立的动态内容服务器上,同样可以是单独的物理服务器或者虚拟主机
- 配置Nginx作为反向代理服务器:通过Nginx的配置文件,设置反向代理规则将用户的请求分发到静态资源服务器或动态内容服务器上。可以使用Nginx的proxy_pass指令来实现代理转发。
# 动态资源发送请求反向代理到本地的tomcat处理
location / {
proxy_pass http://127.0.0.1:8080;
root html;
index index.html index.htm;
}
# 这里是将静态资源放到了Nginx的目录下
location /css {
root /usr/local/nginx/static;
index index.html index.htm;
}
location /images {
root /usr/local/nginx/static;
index index.html index.htm;
}
location /js {
root /usr/local/nginx/static;
index index.html index.htm;
}
location配置(使用正则):
- location前缀:
/
通用匹配,任何请求都会匹配到=
精准匹配,不是以指定模式开头~
正则匹配,区分大小写~*
正则匹配,不区分大小写^~
非正则匹配,匹配以指定模式开头的location- location匹配顺序
- 多个正则location直接按书写顺序匹配,成功后就不会继续往后面匹配
- 普通(非正则)location会一直往下,直到找到匹配度最高的(最大前缀匹配)
- 当普通location与正则location同时存在,如果正则匹配成功,则不会再执行普通匹配
- 当所有类型location存在,“
=
>^~
>正则匹配
>普通匹配(最大前缀匹配)
”
- 使用正则修改上面的动静分离配置
# 动态资源发送请求反向代理到本地的tomcat处理
location / {
proxy_pass http://127.0.0.1:8080;
root html;
index index.html index.htm;
}
# 这里是将静态资源放到了Nginx的目录下
location ~*/(css|js|html) {
root /usr/local/nginx/static;
index index.html index.htm;
}
Url Rewrite
rewrite语法格式及参数语法
- rewrite是实现URL重写的关键指令,根据
regex(正则表达式)
部分内容,重定向到replacement
结尾是flag
标记 - 格式如下:
rewrite <regex> <replacement> [flag]
关键字 正则 替代内容 flag标记
关键字:其中关键字error_log不能改变
rewrite参数的标签段位置:server、location、if
flag标记说明:
1.last 本条规则匹配完成后,继续向下匹配新的location URI规则
2.break 本条规则匹配完成后即终止,不再匹配后面的任何规则
3.redirect 返回302临时重定向,浏览器地址会显示跳转后的URL地址
4.permanent 返回301永久重定向,浏览器地址栏会显示跳转后的URL地址
示例:
rewrite ^/([0-9+]).html$ /index.jsp?pageNum=$1 break;
将Nginx变成网关服务器
- 原先Nginx的功能就是做一个反向代理,是个反向代理服务器
- 现在一个Nginx实现的功能有:反向代理,负载均衡,URL Rewrite ,动静分离(如果直接去访问后端服务器,那么将访问不到静态资源css,js等),必须通过Nginx反向代理
- 那么这个时候,就可以称这个Nginx服务器是我后端服务器集群的网关,但是真实环境中,我的后端服务器集群是不应该被外网访问到的,想要访问就必须通过Nginx服务器才行,相对于后端的服务器集群而言是内网,外网是无法访问的,内网可以相互通信
- 通过配置防火墙,模拟内网环境,命令如下:
systemctl start firewalld
开启防火墙(之前关了)
systemctl restart firewalld
重启防火墙
firewall-cmd --reload
重载规则
firewall-cmd --list-all
查看已配置的规则
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.44.101" port protocol="tcp" port="8080" accept"
指定端口和ip访问(192.168.101为此时的Nginx的ip,即允许nginx访问)
firewall-cmd --permanent --remove-rich-rule="rule family="ipv4" source address="192.168.44.101" port port="8080" protocol="tcp" accept"
移除规则
防盗链
什么是盗链
- 在实际生产过程中,我们线上的图片等静态资源,经常会被其他网站盗用,他们发大财的同时,成本确实我们在买单,下面来说下,如何杜绝这种行为。
- 应该说只要是静态资源都是可以防盗链的,只需要在Server字段加上几行代码即可。众所周知网站出名了后,会有各种刁民来找茬的,最常见的就是爬你网站的东西。
- 关于防盗链这里不得不提一下网页的加载顺序是先加载HTML相关的内容,然后解析HTML的内容,那些需要加载图片,那些需要加载文件,是逐步加载的,所以可以在加载静态资源的时候做防盗链的操作,例如:在加载图片的时候直接跳转去其他链接,或者直接返回404,403等错误代码,拒绝它的请求
如何区分哪些是不正常用户
HTTP Referer
是Header的一部分,当浏览器向Web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器借此可以获得一些信息用于处理,例如防止未经允许的网站盗链图片、文件等。因此HTTP Referer头信息是可以通过程序来伪装生成的,所以通过Referer信息防盗链并非100%可靠,但是,它能够限制大部分的盗链情况- 比如在www.google.com 里有一个 www.baidu.com 链接,那么点击这个www.baidu.com ,它的header 信息里就有:Referer=http://www.google.com
防盗链配置
- 为了模拟盗链,在这里让101为网站服务站点,102为网关服务器,103访问101进行盗链
- 修改 102 Nginx 配置文件,让102代理到101:
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://192.168.10.101; # 代理101网站服务器
}
location ~*/(css|js|html) {
root /usr/local/nginx/static;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
- 此时在浏览器输入102ip,可以正常访问101站点
- 如果不想被盗链,则对101站点服务修改Nginx配置文件,防盗链的配置可以在任意的 location 模块下设置,不能在 server 下,你不想让别人盗链哪个资源就在那个资源的 location 模块下设置防盗链:
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://192.168.10.101; # 代理101网站服务器
}
location ~*/(css|js|html) {
valid_referers 192.68.10.101; #只允许101ip访问静态资源,其他访问返回状态码403
if($valid_referer){
return 403;
}
root /usr/local/nginx/static;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
- 此时再使用102ip去访问101就会返回403,获取不到
配置格式:
# 格式: valid_referers none | blocked | server_names | strings ....; --none:允许没有http_refer的请求访问资源,检测 Referer 头域不存在的情况,则可以访问。 --blocked:检测 Referer 头域的值被防火墙或者代理服务器删除或伪装的情况。这种情况该头域的值不以 “http://” 或 “https://” 开头。允许不是http://开头的,不带协议的请求访问资源。 --server_names :只允许指定ip/域名来的请求访问资源(白名单)。可设置一个或多个 URL ,检测 Referer 头域的值是否是这些 URL 中的某一个。在生产环境中尽量使用域名,不使用ip。 2.# 举例 valid_referers 192.168.10.101; if ($invalid_referer) { return 403; }
实际使用
- 在实际使用中,我们一般不直接返回403状态码,而是通过一个简单的错误页面来提示用户
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://192.168.10.101; # 代理101网站服务器
}
location ~*/(css|js|html) {
valid_referers 192.68.10.101; #只允许101ip访问静态资源,其他访问返回状态码403
if($valid_referer){
return 403;
}
root /usr/local/nginx/static;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
error_page 403 /403.html;
location = /403.html {
root html; #会返回一个html/403.html页面
}
}
- 也可以在判断的时候使用UrlRewrite重写请求
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://192.168.10.101; # 代理101网站服务器
}
location ~*/(css|js|html) {
valid_referers 192.68.10.101; #只允许101ip访问静态资源,其他访问返回状态码403
if($valid_referer){
rewrite ^/ /img/xxx.png break; #匹配所有,break隐藏地址,即不管是什么,不被允许的ip都重写
#return 403;
}
root /usr/local/nginx/static;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
error_page 403 /403.html;
location = /403.html {
root html; #会返回一个html/403.html页面
}
}
高可用配置
安装keepalived(使用yum安装)
命令:yum install keepalived
配置
-
使用yum安装后,配置文件在
/etc/keepalived/keepalived.conf
-
第一台机器:
! Configuration File for keepalived
global_defs {
router_id lb111
}
vrrp_instance dsk {
state MASTER
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.44.200
}
}
配置完启动后,输入命令`ip addr`查看,会发现多了一个地址192.168.44.200(即虚拟ip)
- 第二台机器:
! Configuration File for keepalived
global_defs {
router_id lb110
}
vrrp_instance dsk { # 'dsk'是实例名称,和第一台机器保持一致
state BACKUP # 状态,这里表示备用机
interface ens33 # ens33网卡的名字,使用命令 ip addr 查看
virtual_router_id 51 # 和第一台机器保持一致
priority 50 # 表示优先级,在主备竞选的时候,谁的优先级高谁就是Master
advert_int 1 # 间隔检测的时间
authentication { # 可以理解为分组,两个同一组的keepalived一样就行,这里和第一台机器保持一致
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { #虚拟ip,就是所有用户都访问这个ip
192.168.44.200
}
}
- 启动服务:
systemctl start keepalived