文章目录

  • 支离破碎的概述
  • windows安装nginx
  • 服务器集群产生的问题
  • 使用nginx实现反向代理-windows
  • 使用nginx实现负载均衡-windows
  • 使用nginx实现宕机容错机制-windows
  • 使用nginx搭建API接口网关-windows
  • linux安装nginx
  • 部署keepalived+nginx



支离破碎的概述

nginx的作用?
搭建http服务器、做集群/负载均衡(减轻单台服务器的压力)、反向代理(多台服务器集群可以使用nginx做反向代理并且不暴露真实ip地址)、防盗链/黑白名单、解决跨域问题(搭建接口网关)、防ddos、虚拟服务器(可以实现在一台服务器虚拟出多个网站)、静态服务器(访问静态资源)、

nginx占内存小、轻量级服务器

分布式、微服务、高并发、高可用、消息中间件

类型nginx反向代理的服务器有lvs、F5(硬件)、Haproxy

nginx架构图

nginx 去除server信息_nginx

windows安装nginx

官网直接下,解压压缩包

nginx 去除server信息_nginx_02

目录结构

conf配置文件,配置信息都在这个nginx.conf里面配

html存放静态资源

启动,双击nginx即可,注意路径不要有中文。双击后查看logs error.log没有报错就说明开启了

访问 127.0.0.1:80,看到下面图片就说明开启成功了

nginx 去除server信息_html_03

在html目录下存放一个hello.html,里面随便写点东西

可以直接访问静态资源,这就是静态服务器

nginx 去除server信息_nginx 去除server信息_04

服务器集群产生的问题

单台服务器承受不住高并发的压力会扛不住宕机或者延迟请求

高并发解决方案?
集群、负载均衡

什么是反向代理?
客户端发起请求,首先到nginx服务器,通过nginx服务器进行负载均衡转发到某个服务器上去。还有个好处是不会暴露公网ip,通过转发进行隐藏,十分安全。nginx服务器与代理服务器需要在同一个局域网

负载均衡有哪些算法?
1、权重
2、轮询机制(常用这个)
3、IP绑定

集群会产生什么问题?
session共享问题(多个JVM)、分步式job幂等性问题(就是重复问题,如并发生成订单号)、分布式生成全局id(分布式锁)

如何解决订单号幂等性问题?
提前生成好,存放在redis中,快用完马上生成一批新的id,在同一时刻只允许生成一个订单号

使用nginx实现反向代理-windows

集群如何实现?
实现nginx实现负载均衡,反向代理是不暴露真实ip,注意区分。

集群的目的是减轻单台服务器的压力。

nginx反向代理工作流程:客户端先访问nginx的80端口,nginx转发到某个服务器项目地址

分布式的概念是将一个项目拆分成多个子项目,目的是完成同一个大体的功能,如拆分成会员、订单、支付、消息、前端系统

分布式开发:RPC远程调用技术

一开始单点应用,馒馒人多了演变成了面向服务架构开发SOA,在演化成微服务架构(区分springboot和springcloud)


说了那么多,那么开始吧

conf目录下找到nginx.conf,配置集群之前先配置反向代理,在配置负载均衡

为了方便实验,在host文件中添加两个域名a.a.com和b.b.com

# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host

# localhost name resolution is handled within DNS itself.
#	127.0.0.1       localhost
#	::1             localhost

127.0.0.1       a.a.com
127.0.0.1       b.b.com

启动一个java web项目,端口号为8080

nginx 去除server信息_服务器_05

这时候我们可以用a.a.com:8080/index进行访问

nginx 去除server信息_服务器_06


这时我不想要8080端口,我想用80端口进行访问,但是此时80端口被nginx占用了,但我们可以用nginx帮我们去做转发

如何配置?我们可以在配置文件下边一点的位置新增一段配置,server_name改成a.a.com,并且location 为/, 表示拦截所有a.a.com:80的访问,proxy_pass为转发路径

server {
        listen       80;
        server_name  a.a.com;
        location / {
			proxy_pass  http://127.0.0.1:8080;
			index  index.html index.htm;
        }
    }

nginx 去除server信息_nginx 去除server信息_07


这时候我们直接访问http://a.a.com就是等于访问http://a.a.com:8080,原理是nginx服务器帮我们做了反向代理

nginx 去除server信息_服务器_08

使用nginx实现负载均衡-windows

负载均衡的作用?
提高网站的吞吐量

负载均衡算法?
轮询机制(比如我访问一次到你访问一次进行轮替)、权重(比例分配,比如我两次你一次进行轮替)、ip绑定(只让一个ip地址进行访问,解决session共享问题,没用)

理解2分钟,配置2秒钟

轮询机制配置,在刚刚配的server上面加个upstream backserver配置,proxy_pass 改成backserver

# 轮询机制
 upstream backserver { 
		server 127.0.0.1:8080; 
		server 127.0.0.1:8081; 
        } 
        
 server {
        listen       80;
        server_name  a.a.com;
        location / {
			proxy_pass  http://backserver;
			index  index.html index.htm;
        }
    }

我们启动两个相同的项目,端口号分别为8080和8081

用任务管理器关掉nginx.exe,再重新打开nginx.exe

重新访问http://a.a.com/index,可以看到轮询访问两个端口

nginx 去除server信息_html_09

权重策略,指定轮询几率,weight和访问比率成正比

upstream backserver { 
server 127.0.0.1:8080 weight=2; 
server 127.0.0.1:8081 weight=1; 
}

ip绑定策略,每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。换句话说,就是一个客户端访问8080端口后,就一直访问8080端口,不会访问其他服务器了。

upstream backserver { 
ip_hash; 
server 127.0.0.1:8080; 
server 127.0.0.1:8081; 
}

使用nginx实现宕机容错机制-windows

如果哪一天某个服务器挂了,那么访问将不是会有灾难性后果?就举上面的例子,8080端口挂了,8081在运行,那么用户访问将有50%的概率访问不到页面?

不会的,nginx会有宕机容错机制,一主一备或者多主多备方式。需要自己配置

如果某个web服务器挂了,会有web服务器备机
如果主nginx挂了,还有nginx备机

如果主备机全挂了,使用keepalived重启web服务器或者nginx

如果重启N次仍挂了,发送警报邮件给运维人员。

这才是高可用,不要再说手动重启了,切记切记


keepalived在linux中讲吧

这里主要是nginx配置,那么我们开始实现,集群某台服务器宕机,自动轮询到下一台服务器

之前已经配置好集群了,在这基础上稍微加一点东西即可

添加超时响应proxy_connect_timeout等即可,超过1s自动轮询

# 轮询机制
 upstream backserver { 
		server 127.0.0.1:8080; 
		server 127.0.0.1:8081; 
        } 
        
 server {
        listen       80;
        server_name  a.a.com;
        location / {
			proxy_pass  http://backserver;
			index  index.html index.htm;
			# 添加超时配置
			proxy_connect_timeout 1;
            proxy_send_timeout 1;
            proxy_read_timeout 1;
        }
    }

暂时停掉8081端口服务器,重新测试访问,将会都访问到8080端口


发布版本的时候服务器能访问吗?我们的第一感觉是不能的,但是为什么csdn、淘宝等这些大网站经常在更新网站,我们却感受不到宕机呢?

大致实现思路就是主备宕机容错机制,有多台服务器,主服务器在更新,用户会访问到备服务器。

其实眼界放大一点,可以这么来看,主集群在更新,备用集群启动进行服务,是相当大型的架构,进行统一管理

此外,还要考虑一个问题,tomcat在发布版本的时候,session会失效,因为jvm重启了,那如何解决呢?
请使用redis,或者持久化到数据库中。因此尽量不使用jvm内置缓存机制,分布式架构中难以统一管理。

使用nginx搭建API接口网关-windows

解决跨域问题,之前在博客里挖了坑现在填回来,闭关修炼(二十四)浅入了解跨域问题

跨域问题简单的说在域名a.a.com下是不能访问其他域名的如b.b.com,aja访问请求的域名和浏览器访问的域名不相同。

目前主流解决方案还是使用nginx

先模拟出跨域问题,在A项目放一个静态图片,B项目静态页面去访问

A项目resources下创建static目录,里面放一张1.jpg
【假装我是1.jpg】

B项目resources下创建static目录,创建kuayu.html

<html>
<head>
    <title>$跨域测试$</title>
</head>

<script src="http://libs.baidu.com/jquery/1.7.2/jquery.min.js"></script>

<script type="text/javascript">
    $(document).ready(function (){
        $.ajax({
            type : "GET",
            async : false,
            url : "http://a.a.com:8080/1.jpg",
            dataType : "json",
           
        })
    })
</script>
<body>
</body>
</html>

访问http://b.b.com:8081/kuayu.html,模拟出跨域问题,可以看到ajax请求被限制了

nginx 去除server信息_nginx_10


这时我们可以,使用nginx网关拦截请求,进行转发,来解决跨域问题,原理是将项目反向代理到同一个域名下

换句话说,举个例子:如访问c.c.com/a就是访问a.a.com,访问c.c.com/b就是访问b.b.com,c.c.com是新设的域名,那么b.b.com要访问a.a.com就通过c.c.com/a进行反向代理访问

修改host一下文件,模拟域名:

nginx 去除server信息_nginx_11

修改nginx.conf,让nginx监听c.c.com域名,location /a和/b分别做拦截进行转发,注意proxy_pass地址最后面不要少了/

server {
        listen       80;
        server_name  c.c.com;

        location /a {
        	# 注意8080后面/不要少了
			proxy_pass  http://a.a.com:8080/;
			index  index.html index.htm;
	
       }
       location /b {
			proxy_pass  http://b.b.com:8081/;
			index  index.html index.htm;
	
       }
    }

启动nginx,测试c.c.com/a和c.c.com/b项目是否能正常访问,如果不能说明nginx.conf配置错了,或者host设置错了。

然后将b项目的图片url请求地址改成c域名下

<html>
<head>
    <title>$跨域测试$</title>
</head>

<script src="http://libs.baidu.com/jquery/1.7.2/jquery.min.js"></script>

<script type="text/javascript">
    $(document).ready(function (){
        $.ajax({
            type : "GET",
            async : false,
            url : "http://c.c.com/a/1.jpg",
            dataType : "json",
           
        })
    })
</script>
<body>
</body>
</html>

访问测试b项目,ajax访问a项目的1.jpg,成功跨域访问

nginx 去除server信息_html_12

linux安装nginx

docker run -d --name nginx01 -p 80:80 nginx

创建目录用来挂载文件
mkdir -p /docker/nginx01/{conf,html,logs}

将配置文件拷贝出来
docker cp nginx01:/etc/nginx/nginx.conf /docker/nginx01/conf

cp 命令代表复制
nginx01是我们nginx容器名
/etc/nginx/nginx.conf 是容器内部nginx.conf 路径

停止容器
docker stop nginx01 移除容器
docker rm nginx01 重新创建容器,这里挂成800端口,80端口得备案…
docker run -d --name nginx01 -p 800:80 -v /docker/nginx01/conf/nginx.conf:/etc/nginx/nginx.conf -v /docker/nginx01/logs:/var/log/nginx --privileged=true nginx

执行docker exec -it nginx01 /bin/bash 进入容器内部

进入到nginx容器内部后,我们可以cd /etc/nginx,可以看到相关的nginx配置文件都在/etc/nginx目录下

部署keepalived+nginx

keepalived作用是宕机服务器重启脚本,发送邮件给运维,心跳检测,自动执行脚本

nginx宕机带来的错误是致命性的,并且其中部署的服务都是内网ip,端口不暴露,不允许访问外网,只有nginx暴露外网ip地址,同时部署的服务器和nginx又在同一个局域网,客户端将无法访问到服务器了。

主nginx和备nginx一般在同一个局域网内,keepalived服务器和主备nginx建立通信,形成虚拟keepalived ip地址,类似于哨兵机制。

这是一主一备的形式,还有一主多备,因此要使用keepalived监听nginx,至少得有2台nginx,那么我们就先创建两个nginx

说了那么多,那我们开始吧~

自己写Dockerfile吧,用他们压缩的docker镜像各种环境不齐我都想死了

nano Dockerfile

FROM centos:7.8.2003

ENV LANG=zh_CN.UTF-8 \
    LANGUAGE=zh_CN:zh \
    LC_ALL=zh_CN.UTF-8

# Install tools
RUN yum update -y && \
    yum reinstall -y glibc-common && \
    yum install -y telnet net-tools && \
    yum clean all && \
    rm -rf /tmp/* rm -rf /var/cache/yum/* && \
    localedef -c -f UTF-8 -i zh_CN zh_CN.UTF-8 && \
    ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

# Define default command.
CMD ["bash"]

创建自己的yore/centos7_v1镜像
docker build -t yore/centos7_v1 .

build好了查看本地镜像
docker images

启动镜像,注意要用特权模式启动
docker run -p 800:80 --privileged=true --net=host --cap-add NET_ADMIN --cap-add SYS_ADMIN -it -d --name="centos01" yore/centos7_v1:latest /usr/sbin/init

docker exec -it centos01 /bin/bash【Master容器内】

[Master容器内]
yum install -y nanoyum -y install initscripts

安装gcc
yum install -y gcc openssl-devel popt-devel

安装keepalive
yum install keepalived

安装Nginx[Master容器内]

#使用yum安装nginx需要包括Nginx的库,安装Nginx的库
rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
# 使用下面命令安装nginx
yum install nginx
#安装网络包(需要使用ifconfig和ping命令)
yum install net-tools

[修改keepalived配置]
cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bakrm -rf /etc/keepalived/keepalived.confnano /etc/keepalived/keepalived.conf

! Configuration File for keepalived
 
vrrp_script chk_nginx {
	script "/etc/keepalived/nginx_check.sh"
	##(检测脚本执行的间隔)
	interval 1
	weight -20
}
vrrp_instance VI_1 {
	 state MASTER # 备份服务器上将 MASTER 改为 BACKUP 
	 interface eth0 //网卡
	 virtual_router_id 41 # 主、备机的 virtual_router_id 必须相同
	 priority 100 # 主、备机取不同的优先级,主机值较大,备份机值较小
	 advert_int 1
	 authentication {
	 auth_type PASS
	 auth_pass 1111
	}
	track_script {
        chk_nginx
    }
	 virtual_ipaddress {
		192.168.1.140
	} 
}

nano /etc/keepalived/nginx_check.sh

#检测nginx是否存活的脚本
A=`ps -ef | grep nginx | grep -v grep | wc -l`
if [ $A -eq 0 ];then
  nginx
  sleep 1
  if [ `ps -ef | grep nginx | grep -v grep | wc -l` -eq 0 ];then
      #killall keepalived
      ps -ef|grep keepalived|grep -v grep|awk '{print $2}'|xargs kill -9
  fi

fi

chmod 755 /etc/keepalived/nginx_check.sh

[启动keepalived]

#重新加载配置

systemctl daemon-reload #启动keepalived服务

systemctl start keepalived.service

#查看当前状态

systemctl status keepalived.service

nginx 去除server信息_nginx 去除server信息_13


修改Nginx默认页面

nano /usr/share/nginx/html/index.html

nginx 去除server信息_nginx_14


启动nginx

nginxkeepalived测试

ip addr 查看是否绑定虚拟ip,v-ip

nginx 去除server信息_服务器_15


nginx测试

curl 172.17.0.4

nginx 去除server信息_nginx 去除server信息_16

ctrl+p+q退出

保存Docker Master镜像
#查看刚运行的容器ID -> a61cee4dafe6
docker ps|grep "centos01";

#提交容器镜像到本地
docker commit a61cee4dafe6 keepalived_master:v1 #查看当前镜像
docker images;

【slave容器】

创建容器
docker run -p 801:80 --privileged=true --net=host --cap-add NET_ADMIN --cap-add SYS_ADMIN -it -d --name="keepalived_slave01" keepalived_master:v1 /usr/sbin/init

#进入[Slave]这个容器
docker exec -it keepalived_slave01 bash

(按照上面的步骤安装好环境,因为是用master的镜像已经配好就不用了)

修改Slave容器的keepalived配置
nano /etc/keepalived/keepalived.conf

# 修改这两项
         state BACKUP # 备份服务器上将 MASTER 改为 BACKUP
       
         priority 99 # 主、备机取不同的优先级,主机值较大,备份机值较小

重新加载keepalived配置、重启、查看状态【Slave容器】
#重新加载配置
systemctl daemon-reload #启动keepalived服务
systemctl start keepalived.service #查看当前状态
systemctl status keepalived.service

修改Nginx默认页面
nano /usr/share/nginx/html/index.html

nginx 去除server信息_服务器_17


启动nginx

nginx

Slave测试
ip addr

测试nginx
curl 192.168.0.6


测试用例

1、
我们可以进行测试,还是需要进入到容器中,首先看一下俩台机器的ip addr 命令下 都会出现一个虚拟ip,我们可以停掉,一个机器的keepalived,然后测试,命令:service keepalived stop。结果发现当前停掉的机器已经不可用,keepalived会自动切换到另一台机器上

在master 容器输入
service keepalived stop

回到slave容器输入
ip addr
我们看到keepalived会自动切换到slave的机器上

2、
我们可以测试在nginx出现问题的情况下,实现切换,这个时候我们只需要把nginx的配置文件进行修改,让其变得不可用,然后强杀掉nginx进程即可,发现也会实现自动切换服务器节点。

ps -ef | grep nginx

ps -ef | grep keepalived


3、
service keepalived stop 强制关闭
pkill nginx 再次启动
service keepalived start nginx自动重启


Keepalived配置重载(reload)
kill -HUP $(cat /var/run/keepalived.pid)


写在后面:
当然host主机自身也可以配keepalived,这里都用docker,容器本来就可以看作是一台虚拟机

注意一下一些问题:
在尝试部署keepalived容器之前,主机必须允许ipv4地址的非本地绑定。为此,请配置sysctl tunable net.ipv4.ip_nonlocal_bind=1。

除了启用非本地绑定之外,还必须同时使用主机网络(–net=host)和安全设置CAP_NET_ADMIN(–cap-add NET_ADMIN)来运行容器。这些使容器可以管理主机的网络配置,这对于keepalived功能至关重要。