菜鸟笔记
提升您的技术认知

nginx服务器

什么是nginx

nginx是一款高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务,因为其稳定、丰富的功能集,简单的配置文件和地系统的资源消耗而闻名

注意:

  • nginx的主要功能是实现反向代理
  • 通过配置文件可以实现集群和负载均衡
  • 静态资源虚拟化
  • nginx底层是用C语言进行开发的

使用nginx的命令

进入安装好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页面 

注意:

  1. nginx每次启动时都会有2个进程,一个主进程,一个守护进程
  2. 主进程:主要提供反向代理服务,占用内存空间大
  3. 守护进程:防止主进程意外关闭
  4. 如果要关闭nginx则需要先关闭守护进程,然后再关闭主进程(window内关服务的话)

nginx的目录结构

conf:存放nginx的主配置文件

注意:nginx.conf为nginx的核心配置文件,里面进行nginx的一些策略设置等,在该配置文件里面会引用到其他配置文件

html:存放默认情况下(成功、失败等)的网页和其他的一些静态资源

logs:用来记录访问日志(分别有成功访问日志以及失败访问日志)

sbin:存放nginx的主程序,用于nginx的启动与关闭等

nginx的基本请求流程

理解:nginx服务开启(此时nginx已经通过sbin目录下的主程序开启),首先nginx的Master主进程会把nginx.conf配置文件的内容读取进来并校验,若配置文件没有错误,则他的会开启多个子进程,来等待客户端发起的请求,worker对请求进行响应与解析,找到html目录,并将对应的资源返回给用户。

注意:nginx的主进程不处理业务,他的主要作用就是协调这些子进程worker

nginx的基础配置文件

#说明在启动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后面的路径支持正则表达式写法(该正则里面不区分大小写)

urlRewrite

后端开启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的高可用呢?

开两个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漂移)