什么是nginx
nginx是一款高性能的http和反向代理web服务器,同时也提供了imap/pop3/smtp服务,因为其稳定、丰富的功能集,简单的配置文件和地系统的资源消耗而闻名
注意:
- nginx的主要功能是实现反向代理
- 通过配置文件可以实现集群和负载均衡
- 静态资源虚拟化
- nginx底层是用c语言进行开发的
进入安装好nginx的sbin目录
- ./nginx:启动
- ./nginx -s stop:快速停止
- ./nginx -s quit:优雅关闭,在退出前完成已经接受的连接请求
- ./nginx -s reload:重新加载配置
访问时注意关闭防火墙
关闭防火墙:systemctl stop firewalld.service
禁止防火墙开机自启:systemctl disable firewalld.service
访问虚拟机:http://192.168.126.129
注意:默认会跳到nginx内html目录下的index.html页面
注意:
- nginx每次启动时都会有2个进程,一个主进程,一个守护进程;
- 主进程:主要提供反向代理服务,占用内存空间大
- 守护进程:防止主进程意外关闭
- 如果要关闭nginx则需要先关闭守护进程,然后再关闭主进程(window内关服务的话)
conf:存放nginx的主配置文件
注意:nginx.conf为nginx的核心配置文件,里面进行nginx的一些策略设置等,在该配置文件里面会引用到其他配置文件
html:存放默认情况下(成功、失败等)的网页和其他的一些静态资源
logs:用来记录访问日志(分别有成功访问日志以及失败访问日志)
sbin:存放nginx的主程序,用于nginx的启动与关闭等
理解:nginx服务开启(此时nginx已经通过sbin目录下的主程序开启),首先nginx的master主进程会把nginx.conf配置文件的内容读取进来并校验,若配置文件没有错误,则他的会开启多个子进程,来等待客户端发起的请求,worker对请求进行响应与解析,找到html目录,并将对应的资源返回给用户。
注意:nginx的主进程不处理业务,他的主要作用就是协调这些子进程worker
#说明在启动nginx的时候要启动多少个子进程
worker_processes 1;
#事件驱动模块
events {
#每一个work进程能够创建多少个连接
worker_connections 1024;
}
#http协议(里面可有多个主机,客户端请求按照顺序进行)
http {
#include作用是把另外一个配置文件引入到我们当前的配置文件当中
#mime.types-请求头,头里面会表明当前给客户端发送的文件的类型
include mime.types;
#如果类型不包含在mime.types里,那么就会用下面的默认类型
default_type application/octet-stream;
#数据零拷贝,若为off则nginx应用程序会读取资源后复制给网络接口,若为on,则nginx不去加载资源,会向网络接口添加信号;网络接口来读取资源(网络接口读到文件后直接通过网路将数据发送给用户)
sendfile on;
#保持连接超时的时间
keepalive_timeout 65;
#一个server代表一个虚拟主机,可写多个server(每个虚拟主机之间互相不干扰)
server {
#可以通过端口号的方式来区分主机的不同(当前服务器主机在80端口运行)
listen 80;
#表示当前主机的主机名(域名/主机名)
server_name localhost;
#localion表示拦截root目录下的子目录路径名(可写多个location)
location / {
#root表示以nginx目录下的什么目录为根目录(这里用到了相对路径-nginx内的html)
root html;
#index表示响应给具体目录下的具体页面
index index.html index.htm;
}
#如果发生下面错误码的错误,那么就会转向/50x.html这个地址
error_page 500 502 503 504 /50x.html;
#一旦用户访问/50.html,那么就会在root目录下寻找50x.html
location = /50x.html {
root html;
}
}
}
理解:把一台主机虚拟出来更多的主机(实现了一个ip地址可以访问多个域名),由nginx里判断,该客户端到底要访问哪个域名,nginx找到资源后将其返回给客户端
虚拟主机域名配置
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
server {
#访问端口号为88,打破http默认端口
listen 88;
#配置的域名,对应的是本机ip(域名可以写多个)
server_name cjc.com;
#拦截uri为/app的请求
location /{
#响应根目录下的www/main内的资源
root /www/main;
#响应的资源名
index main.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
#第二个虚拟主机(顺序执行)
server {
listen 80;
server_name localhost;
location /{
#这里用了相对路径,nginx下html内的static目录
root html/static;
index app.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 90;
server_name localhost;
location /{
#proxy_pass的作用:将拦截的请求响应到一个地址上
proxy_pass http://www.265.com/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
注意:
- server_name可以写多个域名,中间用空格隔开。
- server_name支持正则表达式匹配
- 一个server_name相当于一个服务端ip地址,当然,该位置也可以直接写成服务端ip地址
含义:客户端发送的请求会先经过代理服务器,然后代理服务器转发请求到目标服务器,代理服务器从目标服务器获得内容后响应给客户端,整个过程目标服务器不知道是哪个具体客户端发出的请求(客户端没法访问目标服务器,通过代理服务器进行转发)
含义:用户发送请求到目标服务器,由代理服务器决定访问哪个ip,整个后面的过程用户不清楚,也不清楚是哪个服务器为自己处理的请求,全是由反向代理服务器决定
理解:用户在访问系统时通过互联网到我们系统的网关路由上,网关会将请求转发到具体的nginx服务器上,此服务器为nginx反向代理服务器,他会把用户发来的所有请求转发到我们后端的应用服务器(用户不能够直接访问外网服务器,必须通过nginx将请求转发给服务器;然后服务器将结果返回给nginx,nginx再将数据传递给用户)
#虚拟主机
server {
listen 90;
server_name cjc.com;
location /getport{
#proxy_pass后面配置一个服务器地址(不支持https服务器)
proxy_pass http://192.168.18.16:8080;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
解释:访问cjc.com:90/getport就相当于访问后端http://192.168.18.16:8080/getpost
经测试向nginx服务器发送参数时,nginx会向目标服务器实现请求转发功能,该请求会发送到目标服务器内
即访问:cjc.com:90/getpost?name=lili
等价于:http://192.168.18.16:8080/getpost?name=lili
含义:请求发送到系统时,通过某些方式把请求均匀分发到多个节点上,使系统中的每个节点都能够均匀的处理请求负载,则可以认为系统是负载均衡的
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
#虚拟主机
server {
listen 88;
server_name cjc.com;
location /{
#proxy_pass后面配置一个服务器地址(不支持https服务器)
proxy_pass http://randomname/getport;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
#upstream定义一组服务器来使用,用来配置负载均衡
upstream randomname{
server 192.168.18.16:8080;
server 192.168.18.16:8081;
server 192.168.18.16:8082;
}
}
在后端开启了3个端口(8080、8081、8082)的服务
@restcontroller
public class testcontroller {
@value("${server.port}")
private string port;
@getmapping("/getport")
public string getport(string user){
system.out.println(user);
return "当前端口号" port;
}
}
注意:访问cjc.com:88?name=lili等价于向randomname服务器集群中/getport?name=lili
负载均衡策略
轮询策略
含义:按照配置文件的顺序依次访问(默认为轮询)
upstream randomname{
server 192.168.18.16:8080;
server 192.168.18.16:8081;
server 192.168.18.16:8082;
}
权重策略
分别给每个服务适当的权重,若没有设置权重,那么默认权重为1
#upstream定义一组服务器来使用,用来配置负载均衡
upstream randomname{
#为该服务设置权重为6
server 192.168.18.16:8080 weight=6;
#为该服务设置权重为3
server 192.168.18.16:8081 weight=3;
#为该服务设置权重为1
server 192.168.18.16:8082 weight=1;
}
ip_hash策略
判断来源的ip地址,相同的ip指向相同的服务器
upstream randomname{
#与第一个服务进行绑定
ip_hash;
server 192.168.18.16:8080;
server 192.168.18.16:8081;
server 192.168.18.16:8082;
}
注意:
- ip_hash;可以放在任意位置,但是最终只会与不是down的服务进行绑定
- 设置ip_hash;时ip一般不会与备用机进行绑定
least_conn策略
最少连接访问:寻找连接数最少的服务器进行访问
upstream randomname{
least_conn;
server 192.168.18.16:8080 backup;
server 192.168.18.16:8081;
server 192.168.18.16:8082;
}
注意:这里有一个问题,比如某个服务器由于性能原因,通过权重策略使得该服务器的流量变少,这时使用该最少连接访问那么就不合理
url_hash策略
判断来源的url路径,相同的url指向相同的服务器-比如注册的时候被转发到某台服务器(少用)
注意:使用该策略时需要安装第三方插件
fair策略
根据后端服务器响应速度来实现转发请求(有流量倾斜的风险)
注意:使用时还得安装插件很少用
nginx常见属性
down属性
理解:若down属性标识了该服务器,则nginx不会再次访问该服务器
upstream randomname{
#down掉第一个服务,ip_hash;自动绑定下一个服务
ip_hash;
server 192.168.18.16:8080 down;
server 192.168.18.16:8081;
server 192.168.18.16:8082;
}
backup属性
理解:设置备用机,正常情况下备用机不会被访问,但当主机遇忙或者down机后,备用机才会被访问
upstream randomname{
#将第一台机器设置为备用机
server 192.168.18.16:8080 backup;
server 192.168.18.16:8081;
server 192.168.18.16:8082;
}
理解:将动态请求和静态请求分离开,将静态资源前置到nginx里,将动态请求打到后端的tomcat中
作用:动静分离的基础是它可以根据配置不同的请求做不同的转发,动静分离有利于提高整个服务器系统的性能
静态页面
#访问cjc.com对应的ip地址:80
server {
listen 80;
server_name cjc.com;
#后接/static会返回nginx/html/static目录下的app.html页面
location /static{
root html;
index app.html;
}
#后接/fix会返回nginx/html/fix目录下的fix.html页面
location /fix{
root html;
index fix.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
动态请求
server {
listen 80;
server_name cjc.com;
location /{
proxy_pass http://randomname/getport;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
upstream randomname{
least_conn;
server 192.168.18.16:8080 backup;
server 192.168.18.16:8081;
server 192.168.18.16:8082;
}
关于静态资源location匹配
- location后面接的路径越复杂,则优先级越高,如/fix比/优先级高
- location后面的路径支持正则表达式写法(该正则里面不区分大小写)
后端开启8080端口
@restcontroller
public class testcontroller {
@requestmapping("/first.html")
public string getfirst(string username){
return "第一名:" username;
}
}
通过正则匹配实现用2.html代替后端first.html?username=lili这个请求
server {
listen 88;
server_name cjc.com;
location /{
rewrite ^/2.html$ /first.html?username=lili break; #break为flag标记
rewrite ^/1.html$ /first.html?username=lan break;
proxy_pass http://192.168.18.16:8080;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
请求:http://192.168.18.16:8080/2.html
相当于请求:http://192.168.18.16:8080/first.html?username=lili
注意:urlrewrite规则可以写多个
flag标记说明
- break:匹配到了当前这一条那么直接返回,不会再继续匹配了,浏览器地址不变,但会显示新页面
- last:本条规则匹配完成后继续向下匹配后面的location url规则(跳出当前location作用域,继续匹配下一个location作用域的规则[因为location可写多个])——用的极少
- redirect:返回302,临时重定向,浏览器地址栏会显示跳转后的url地址
- permanent:返回301,永久重定向,浏览器地址栏会显示跳转后的url地址
含义:存在我们服务器上的那些资源只能由我们自己的服务器来进行访问,其他地方的服务器地址来引入该资源则访问失败
防盗链与自定义错误文件
server {
listen 80;
server_name cjc.com;
location /static{
#设置可以访问该静态资源的地址(none标识防盗链的配置,最后面的域名可以设置多个,多个之间用空格隔开)
valid_referers none 192.168.18.16;
#如果不是白名单,则会报403错误
if ($invalid_referer) {
#这里也可以直接rewrite
#rewrite ^/ img/x.png break;
return 403;
}
root html;
index app.html;
}
#如果发生下面错误码的错误,那么就会转向/50x.html这个地址
error_page 500 502 503 504 /50x.html;
#一旦用户访问/50.html,那么就会在root目录下寻找50x.html
location = /50x.html {
root html;
}
error_page 403 /40x.html;
location = /40x.html {
root html;
}
}
注意:
- if与()之间有个空格,不然报错
- return也可以直接return页面,如return /40x.html;那么就会直接去nginx目录的html目录内去找对应的文件
防盗链配置
格式:valid_referers none server_name
- none:就是referer头(http报文里的)如果不存在的情况下允许访问(就是浏览器直接访问静态资源)
- server_name:设置一个或多个url,检测referer头域的值是否是这些url之间的一个
使用curl测试防盗链
linux下安装curl:yum install -y curl
curl基本命令
curl -i http://192.168.44.101/img/logo.png
解释:
- 直接访问服务器内的资源,最终返回响应头(-i参数)信息
- 相当于浏览器直接访问服务器内的logo.png
curl -e "http://baidu.com" -i http://192.168.44.101/img/logo.png
解释:表示访问192.168.44.101引用http://baidu.com内img下的logo.png资源
前言
我们知道后端的应用服务器通过nginx的负载均衡保证了后端服务的高可用(后端服务器冗余备份,以备不时之需);但是我们应该怎么保证nginx的高可用呢?
开两个nginx服务,通过keepalived通信机制,keepalived不需要nginx加一层机器,其跑在运行中的机器上;当keepalived跑起来以后两台keepalived的机器(nginx)上会互相通信,来检测对方是否挂掉;两台机器既然要同时提供服务,那么两台机器必然具有不同ip地址,那么前端的用户请求应该请求哪个ip地址呢?
keepalived会管理虚拟ip地址在两台服务器中切换,用户发的请求都会通过虚拟ip,当一台机器down后,那么虚拟ip地址就会在下一个机器中。
简单解释:就是一个两个nginx以及所在的机器和keepalived都运行着,一个nginx提供服务,另一个nginx当备胎,用户请求只请求那个虚拟ip地址;那么一个nginx机器down了,虚拟ip跑到下一个nginx机器上,备用机开始提供服务
keepalived的使用
安装keepalived:yum install -y keepalived
进入/etc/keepalived目录的keepalived.conf文件
! configuration file for keepalived
global_defs {
router_id lvs_devel
}
#vrrp为keepalived在内网当中通信的协议,vi_1为实例名称,可以随机写
vrrp_instance vi_1 {
#state表示当前机器是master
state master
#interface后面接网卡名称
interface ens33
virtual_router_id 51
#priority表示优先级,主备竞选来决定谁是master
priority 100
#间隔检测的时间
advert_int 1
#分组认证配置(同一组保持一致)
authentication {
auth_type pass
auth_pass 1111
}
#虚拟ip地址,可以添写多个
virtual_ipaddress {
192.168.126.130
}
}
启动keepalived:systemctl start keepalived
查看keepalived状态:systemctl status keepalived
查看ip地址:ip addr
可以看出多了个vip
然后在第二个含有nginx的linux服务器内配置keepalived
在对应的keepalived.conf文件内配置
! configuration file for keepalived
global_defs {
#改变router_id名称
router_id lvs_devel1
}
vrrp_instance vi_1 {
#将状态设置为备用机
state backup
interface ens33
virtual_router_id 51
#优先级相对于master设置的低一些,因为是备用机
priority 50
advert_int 1
authentication {
auth_type pass
auth_pass 1111
}
#虚拟ip地址,可以添写多个
virtual_ipaddress {
192.168.126.130
}
}
注意:
- vrrp_instance实例名称与virtual_router_id以及authentication必须是对应的(若对应不上则加入不到一组里)
- keepalived选举方式:通过keepalived配置文件中的优先级,优先级越高,则越容易成为master,一旦优先级比别的优先级低的话,那么自己就会把自己改成backup了
将第二个keepalived也启动
测试
通过外网ping 192.168.126.130会发现起初master主机可以给外网计算机发送数据,当把主机down掉,那么会发现备用机身上的ip突然多出了192.168.126.130,备用机开始给主机发送数据(实现了ip漂移)