赞
踩
其中,nacos,nginx,mysql,mq,redis,gateway,服务均为集群模式。使用docker模拟集群分布。
所有的环境都是在服务器上用docker模拟分布式集群的方式搭建的
curl -sSL https://get.daocloud.io/docker | sh
在服务器终端中运行该指令
1. 拉取 MySQL 镜像
docker pull mysql:5.7
2. 设置 MySQL 配置文件
将全部的配置文件和关联的文件夹统一放到 /opt/docker/mysql 中
创建 MySQL 配置文件文件夹
mkdir -p /opt/docker/mysql/conf.d
增加并修改配置文件 config-file.cnf
vim /opt/docker/mysql/conf.d/config-file.cnf
输入如下内容:
[mysqld]
# 设置表名不区分大小写 linux下默认是区分的,windows下默认不区分
lower_case_table_names=1
#server-id=1
datadir=/var/lib/mysql
#socket=/var/lib/mysql/mysqlx.sock
#symbolic-links=0
# sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
3. 启动
创建 MySQL 数据文件夹
mkdir -p /opt/docker/mysql/var/lib/mysql
启动,设置默认密码 root,TZ 设置容器的默认时区
docker run —name mysql \
—restart=always \
-p 3306:3306 \
-v /opt/docker/mysql/conf.d:/etc/mysql/conf.d \
-v /opt/docker/mysql/var/lib/mysql:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-e TZ=Asia/Shanghai \
-d mysql:5.7
4. 修改密码
docker exec -it mysql bash
进入 MySQL
mysql -uroot -p
输入刚才我们设置的密码 root
授权
mysql> GRANT ALL ON *.* TO 'root'@'%';
刷新权限
mysql> flush privileges;
更新加密规则
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'root' PASSWORD EXPIRE NEVER;
更新 root 密码
mysql> ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
刷新权限
mysql> flush privileges;
查看用户
mysql> use mysql;mysql> select user,host from user;
退出容器
exit
有此条记录即成功
navicat链接数据库测试,成功。
直接docker启动两个mysql容器,分别叫mysql-master和mysql-slave;从数据库映射到3302端口。
进入主数据库,安装vim,编辑my.cnf文件如下
[mysqld]
log-bin=/var/log/mysql/mysql-bin
server-id=1
gtid_mode=ON
enforce_gtid_consistency=1 # 强制执行GTID一致性。
如果省略server-id(或将其显式设置为默认值0),则主服务器拒绝来自从服务器的任何连接。如果省略server-id(或将其显式设置为默认值0),则主服务器拒绝来自从服务器的任何连接。
创建日志目录并赋予权限
mkdir /var/log/mysql
chown mysql.mysql /var/log/mysql
重启服务:systemctl restart mysqld
创建一个专门用于复制数据的用户
每个从服务器需要使用MySQL 主服务器上的用户名和密码连接到主站。计划使用用户 repl 可以从任何主机上连接到 master 上进行复制操作, 并且用户 repl 仅可以使用复制的权限。
创建repl用户CREATE USER 'repl'@'%' IDENTIFIED BY '123456789';
用户名:repl
主机:使用通配符%,允许任意远程主机登陆
密码:123456789
对repl用户进行授权GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
在从库测试用户有效性mysql -urepl -p'123456789' -h192.168.0.101
之后再配置从库的my.cnf
vim /etc/my.cnf
[mysqld]
server-id=2
gtid_mode=ON
enforce_gtid_consistency=1
# 可选项, 把连接到 master 的信息存到数据库中的表中
master-info-repository=TABLE
relay-log-info-repository=TABLE
read_only=1#可以设置只读
重启从数据库服务
systemctl restart mysqld
开启Master-Slave主从复制
进入Master库mysql客户端:输入show master status查看Master状态:
change master to master_host='172.18.0.3',
master_user='slave',
master_password='123456',
master_port=3306,
master_log_file='master-bin.000001',
master_log_pos=617,
master_connect_retry=30;
在从数据库中执行start slave;
开启主从show slave status \G
查看主从状态。
新建数据库nacos
之后运行sql脚本
脚本地址:nacos/nacos-mysql.sql at develop · alibaba/nacos · GitHub
version: "3"
services:
nacos1:
container_name: nacos-server01
hostname: nacos-server01
image: nacos/nacos-server:2.0.3
environment:
- MODE=cluster
- PREFER_HOST_MODE=hostname
- NACOS_SERVERS=nacos-server01:8848 nacos-server02:8848 nacos-server03:8848
- SPRING_DATASOURCE_PLATFORM=mysql
- MYSQL_SERVICE_HOST=你的mysql 地址
- MYSQL_SERVICE_PORT=3306
- MYSQL_SERVICE_USER=root
- MYSQL_SERVICE_PASSWORD=123456
- MYSQL_SERVICE_DB_NAME=nacos
- JVM_XMS=256m
- JVM_XMX=256m
- JVM_XMN=256m
volumes:
- /home/nacos/cluster-logs/nacos-server01:/home/nacos/logs
- /home/nacos/init.d:/home/nacos/init.d
ports:
- 8846:8848
- 9555:9555
- 9847:9849
restart: on-failure
nacos2:
container_name: nacos-server02
hostname: nacos-server02
image: nacos/nacos-server:2.0.3
environment:
- MODE=cluster
- PREFER_HOST_MODE=hostname
- NACOS_SERVERS=nacos-server01:8848 nacos-server02:8848 nacos-server03:8848
- SPRING_DATASOURCE_PLATFORM=mysql
- MYSQL_SERVICE_HOST=你的mysql地址
- MYSQL_SERVICE_PORT=3306
- MYSQL_SERVICE_USER=root
- MYSQL_SERVICE_PASSWORD=123456
- MYSQL_SERVICE_DB_NAME=nacos
- JVM_XMS=256m
- JVM_XMX=256m
- JVM_XMN=256m
volumes:
- /home/nacos/cluster-logs/nacos-server02:/home/nacos/logs
- /home/nacos/init.d:/home/nacos/init.d
ports:
- 8847:8848
- 9848:9849
restart: on-failure
nacos3:
container_name: nacos-server03
hostname: nacos-server03
image: nacos/nacos-server:2.0.3
environment:
- MODE=cluster
- PREFER_HOST_MODE=hostname
- NACOS_SERVERS=nacos-server01:8848 nacos-server02:8848 nacos-server03:8848
- SPRING_DATASOURCE_PLATFORM=mysql
- MYSQL_SERVICE_HOST=你的mysql地址
- MYSQL_SERVICE_PORT=3306
- MYSQL_SERVICE_USER=root
- MYSQL_SERVICE_PASSWORD=123456
- MYSQL_SERVICE_DB_NAME=nacos
- JVM_XMS=128m
- JVM_XMX=128m
- JVM_XMN=128m
volumes:
- /home/nacos/cluster-logs/nacos-server03:/home/nacos/logs
- /home/nacos/init.d:/home/nacos/init.d
ports:
- 8848:8848
- 9849:9849
restart: on-failure
8848端口是nacos后台管理界面的端口,9849端口是nacos集群之间互相通信需要的端口。 为了三个nacos的通信,必须映射到宿主机。
运行上面的docker文件,创建docker容器docker-compose -f cluster-hostname.yaml up -d
访问三个nacos服务,查看是否配置成功。
还要使用nignx来做nacos集群的负载均衡
Nginx 的部署与其他服务部署略有不同,我们需要先启动一个 Nginx 容器实例,然后从容器事例中拷贝出 Nginx 的配置文件到指定目录,之后我们将复制出的配置文件与 Nginx 容器的数据卷进行挂载,从而达到可以在容器外部修改配置文件的目的。这么做是因为,如果直接挂载,那么容器实例中的的目录将会被外部的挂载所覆盖。这是官方 Nginx 镜像的一个小缺陷,注意一下就行了。
运行 Nginx 容器
$ docker run --name temp-nginx -p 8080:8080 -d nginx:latest
在宿主机创建 Nginx 的挂载目录
# 实际创建时以自己的机器环境为准
$ mkdir -p <宿主机挂载目录>
拷贝容器中的配置到宿主机的挂载目录
$ docker cp <Nginx容器ID>:/etc/nginx/ <宿主机挂载目录>
停止并删除容器实例
$ docker stop <Nginx容器ID>
$ docker rm <Nginx容器ID>
修改 Nginx 配置文件
位置:<宿主机挂载目录>/conf.d/default.conf
配置文件主要修改两个部分,一个是新增 upstream,通过负载均衡来配置 Nacos 服务的节点;第二个是修改 server 下的 location,在其中添加反向代理配置。另外,如果你的 Nginx 没有配置过 server_name,那么还需要修改 server 下的 server_name 配置。
完整配置文件如下:
# 添加负载均衡配置
upstream nacos {
server 服务器地址:8846 weight=2 max_fails=2 fail_timeout=10s;
server 服务器地址:8847 weight=2 max_fails=2 fail_timeout=10s;
server 服务器地址:8848 weight=1 max_fails=2 fail_timeout=10s;
}
server {
listen 80;
listen [::]:80;
# 修改为宿主机的 IP地址
server_name 服务器地址;
#access_log /var/log/nginx/host.access.log main;
location / {
# 添加代理配置
proxy_pass http://nacos;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
add_header X-Cache $upstream_cache_status;
add_header Cache-Control no-cache;
#root /usr/share/nginx/html;
#index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
编排 Nginx启动文件
version: "3"
services:
nacos-nginx:
container_name: nacos-nginx
image: nginx:latest
volumes:
- /home/naocs-nginx:/etc/nginx
##注意这里容器挂在的位置
ports:
- 18848:80
restart: on-failure
访问http://服务器ip:18848/nacos/ 查看效果
在本机上下载安装idea2021(具体方法baidu)
新建父工程cloud-demo
打开pom文件,在properties中控制整个项目的版本
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR8</spring-cloud.version>
<mysql.version>5.1.47</mysql.version>
<mybatis.version>2.1.1</mybatis.version>
</properties>
依赖管理
<dependencyManagement>
<dependencies>
<!-- springCloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--nacos的管理依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
新建module:service-provider1
修改pom文件,在resources中新建application.yml文件。新建启动类。写一个简单的接口,如下。
server:
port: 9001
spring:
datasource:
url: jdbc:mysql://10.245.153.168:3306/cloud_order?useSSL=false
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
application:
name: service-provider
cloud:
nacos:
server-addr: 10.245.153.168:18848 # nacos服务地址
@SpringBootApplication
@EnableDiscoveryClient
public class TestServiceMain {
public static void main(String[] args) {
SpringApplication.run(TestServiceMain.class,args);
}
}
@RestController
public class TestController {
@GetMapping(value = "/test/gethello")
public String getHello(){
return "hello,service provider 1";
}
}
再仿照service-provider1创造项目service-provider2。记得修改端口为9002
很简单就是用openfeign同步调用生产者的接口。不要忘记也将消费者注册进nacos。
使用的docker来运行springboot程序
maven clear;
maven install;
将jar包命名为service-provider1,service-provider2,上传到服务器,用指令sudo rz。
之后拉取一个有java运行环境的镜像。
docker run -d --name service-provider1 -p 9001:9001 -p 19001:19001 \
-v /mydata/service-provider1.jar:/usr/app.jar java:8 \
java -jar -Xms256m -Xmx256m /usr/app.jar
docker run -d --name service-provider2 -p 9002:9002 -p 19002:19002 \
-v /mydata/service-provider2.jar:/usr/app.jar java:8 \
java -jar -Xms256m -Xmx256m /usr/app.jar
由于是测试,就先搭建一个集群,里面运行两个网关服务
module名:gateway
选择本机的jdk1.8,创建一个空白的maven项目。设置项目坐标gav,其中groupid为父工程groupid
在pom文件中导入依赖
<dependencies>
<!--nacos服务注册发现依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--网关gateway依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
编写application.yml文件,启动的端口为10010
server:
port: 10010
logging:
level:
cn.itcast: debug
pattern:
dateformat: MM-dd HH:mm:ss:SSS
spring:
application:
name: gateway
cloud:
nacos:
server-addr: 10.245.153.168:18848 # nacos地址
gateway:
routes:
default-filters:
- AddRequestHeader=Truth,Itcast is freaking awesome!
- AddRequestHeader=origin,gateway
创建主启动类
写一个权限过滤器组件
@Component
public class AuthorizeFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1.获取请求参数
ServerHttpRequest request = exchange.getRequest();
MultiValueMap<String, String> params = request.getQueryParams();
// 2.获取参数中的 authorization 参数
String auth = params.getFirst("authorization");
// 3.判断参数值是否等于 admin
if ("admin".equals(auth)) {
// 4.是,放行
return chain.filter(exchange);
}
// 5.否,拦截
// 5.1.设置状态码
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
// 5.2.拦截请求
return exchange.getResponse().setComplete();
}
@Override
public int getOrder() {
return -1;
}
}
在创建一个几乎完全相同的子项目gateway2,但是启动端口为10011,服务名不要改动
在两个网关服务中的yml文件里新增路由配置:
启动编写的网关集群,查看nacos服务列表
通过网关访问下我们的服务提供者
可见服务调用默认为轮询策略
将gateway与gateway2进行一些maven install来生成jar包,然后用rz
指令上传的服务器
我们都知道jar是运行在java环境中,所以只要容器中有java环境就可以运行jar包,镜像方式运行的原理也是如此。因此我们基于java镜像就可以实现jar包运行。
拉取java镜像docker pull java:8
之后使用docker运行jar包
docker run -d --name gateway1 -p 10010:10010 \
-v /mydata/gateway1.jar:/usr/app.jar java:8 \
java -jar -Xms256m -Xmx256m /usr/app.jar
docker run -d --name gateway2 -p 10011:10011 \
-v /mydata/gateway2.jar:/usr/app.jar java:8 \
java -jar -Xms256m -Xmx256m /usr/app.jar
运行完后查看下效果
可见,gateway网关运行在的docker上时,显示的ip为docker中的虚拟ip,可以在application.yml文件中添加属性:spring.cloud.nacos.discovery.ip:外网ip
来修改。
类比做nacos集群的负载均衡,方法是一样的。
需要注意的是nginx配置文件要挂在到gateway-nginx文件夹下,防止产生冲突。
拉取镜像
docker pull bladex/sentinel-dashboard
运行docker file
docker run -dit \
--name sentinel-nacos \
-p 18858:8858 \
--restart=always \
-e NACOS_SERVER_ADDR=10.245.153.168:18848 \
-e NACOS_USERNAME=nacos \
-e NACOS_PASSWORD=nacos \
-e NACOS_NAMESPACE=public \
-e NACOS_GROUP_ID=SENTINEL_GROUP \
bladex/sentinel-dashboard
访问http://你的ip:18858/ , 输入用户名密码都是sentinel
看看后台页面
将之前的service-provider1项目进行sentinel流控,修改yml文件
注意,由于我们的sentinel运行在服务器里的docker中,故要添加spring.cloud.sentinel.transport.client-ip属性,该属性为你的电脑的公网ip,也就是service-provider1项目运行在的主机的ip
运行起项目,访问几次gethello接口
添加一个流控规则,在看看访问接口的反应
当我们一旦重启sentinel应用,sentinel写的规则消失,生产环境需要将配置规则进行持久化。
在我们之前建立的service-provider1项目中的pom文件里 ,添加依赖
yml文件中,添加
在nacos配置中心新增配置
注意属性的一一对应
运行下sentinel,访问刚才添加配置的接口,规则成功
再重启sentinel,发现规则还在。
只能通过Nacos修改规则配置,通过Dashboard修改规则配置不自动刷新Nacos配置,重启Dashboard后只保留Nacos中数据!!!
1.主从复制
2.哨兵集群
3.redis-cluster集群
我们本次使用redis主从复制的形式搭建redis集群
什么是主从复制?
答:就是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave),数据的复制是单向的,只能由主节点到从节点。默认情况下,每台Redis服务器都是主节点,且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。给大家个图来理解下:
主从复制有什么作用?
答:①:数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
②:故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。换句话说就是主服务器挂掉了,从服务器顶上去。
③:负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
目标:一主,一从,测试用
先拉取镜像
docker run —name redis-master -d -p 16379:6379 redis:latest
docker run —name redis-master -d -p 16380:6379 redis:latest
使用指令docker exec 和redis-cli
分别进入两个redis数据库,查看ip信息输入info
172.17.0.4
172.17.0.5
我们把172.17.0.5作为随从数据库,在其reids终端中输入
SLAVEOF 主ip 主端口(均是前面的ip与端口)
之后再用info
指令查看是否修改成功。
我们在主节点设置一个属性 set name : why
我们在从随从节点获取 get name : why
成功
可以在部署哨兵模式或者分片集群模式。
在线拉取镜像
docker pull rabbitmq:3-management
执行下面的命令来运行MQ容器
docker run \
-e RABBITMQ_DEFAULT_USER=admin \
-e RABBITMQ_DEFAULT_PASS=123456 \
--name mq \
--hostname mq1 \
-p 15672:15672 \
-p 5672:5672 \
-d \
rabbitmq:3-management
启动成功后访问地址:http://服务器ip:15672
按照上面的用户名密码登录
在RabbitMQ的官方文档中,讲述了两种集群的配置方式:
我们先来看普通模式集群,我们的计划部署两节点的mq集群:
| mq1 | 15672 —-> 15672 | 5672 —-> 5672 |
| mq2 | 15673 —-> 15672 | 5673 —-> 5672 |
集群中的节点标示默认都是:rabbit@[hostname]
,因此以上三个节点的名称分别为:
获取cookie值
RabbitMQ底层依赖于Erlang,而Erlang虚拟机就是一个面向分布式的语言,默认就支持集群模式。集群模式中的每个RabbitMQ 节点使用 cookie 来确定它们是否被允许相互通信。
要使两个节点能够通信,它们必须具有相同的共享秘密,称为Erlang cookie。cookie 只是一串最多 255 个字符的字母数字字符。
每个集群节点必须具有相同的 cookie。实例之间也需要它来相互通信。
我们先在之前启动的mq容器中获取一个cookie值,作为集群的cookie。执行下面的命令:
docker exec -it mq cat /var/lib/rabbitmq/.erlang.cookie
可以看到cookie值如下:
HGANYJSVWWMCPJXVSYHG
接下来,停止并删除当前的mq容器,我们重新搭建集群。
在/tmp目录新建一个配置文件 rabbitmq.conf:
cd /tmp
# 创建文件
touch rabbitmq.conf
文件内容如下:
loopback_users.guest = false
listeners.tcp.default = 5672
cluster_formation.peer_discovery_backend = rabbit_peer_discovery_classic_config
cluster_formation.classic_config.nodes.1 = rabbit@mq1
cluster_formation.classic_config.nodes.2 = rabbit@mq2
再创建一个文件,记录cookie
# 创建cookie文件
touch .erlang.cookie
# 写入cookie
echo "HGANYJSVWWMCPJXVSYHG" > .erlang.cookie
# 修改cookie文件的权限
chmod 600 .erlang.cookie
准备目录,mq1、mq2:
cd /tmp
# 创建目录
mkdir mq1 mq2
然后拷贝rabbitmq.conf、cookie文件到mq1、mq2:
# 进入/tmp
cd /tmp
# 拷贝
cp rabbitmq.conf mq1
cp rabbitmq.conf mq2
cp .erlang.cookie mq1
cp .erlang.cookie mq2
创建一个网络:
docker network create mq-net
运行命令
docker run -d --net mq-net \
-v ${PWD}/mq1/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf \
-v ${PWD}/.erlang.cookie:/var/lib/rabbitmq/.erlang.cookie \
-e RABBITMQ_DEFAULT_USER=whycast \
-e RABBITMQ_DEFAULT_PASS=123456 \
--name mq1 \
--hostname mq1 \
-p 5672:5672 \
-p 15672:15672 \
rabbitmq:3-management
docker run -d --net mq-net \
-v ${PWD}/mq2/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf \
-v ${PWD}/.erlang.cookie:/var/lib/rabbitmq/.erlang.cookie \
-e RABBITMQ_DEFAULT_USER=whycast \
-e RABBITMQ_DEFAULT_PASS=123456 \
--name mq2 \
--hostname mq2 \
-p 5673:5672 \
-p 15673:15672 \
rabbitmq:3-management
测试
在mq1这个节点上添加一个队列:
如图,在mq2控制台也都能看到:
到此为止,普通版集群已经部署成功,但是普通模式集群不进行数据同步,每个MQ都有自己的队列、数据信息(其它元数据信息如交换机等会同步)。例如我们有2个MQ:mq1,和mq2,如果你的消息在mq1,而你连接到了mq2,那么mq2会去mq1拉取消息,然后返回给你。如果mq1宕机,消息就会丢失。
从RabbitMQ 3.8版本开始,引入了新的仲裁队列,他具备与镜像队里类似的功能,但使用更加方便。
在任意控制台添加一个队列,一定要选择队列类型为Quorum类型。
因为仲裁队列默认的镜像数为5。如果你的集群有7个节点,那么镜像数肯定是5;而我们集群只有2个节点,因此镜像数量就是2.
此时停掉mq1,mq2中还存在该队列。
待续
在Keepalived + Nginx高可用负载均衡架构中,keepalived负责实现High-availability (HA) 功能控制前端机VIP(虚拟网络地址),当有设备发生故障时,热备服务器可以瞬间将VIP自动切换过来,实际运行中体验只有2秒钟切换时间,DNS服务可以负责前端VIP的负载均衡。
nginx负责控制后端web服务器的负载均衡,将客户端的请求按照一定的算法转发给后端处理,而Real Server将响应直接返回给客户端。
nginx-master、nginx-slave两台服务器均通过keepalived软件把你的网卡绑上一个虚拟IP(VIP)地址192.168.200.199,此VIP当前由谁承载着,服务就绑定在谁的网卡上,当nginx-master发生故障时,nginx-slave会通过keepalived配置文件中设置的心跳时间advert_int检查,无法获取nginx-master正常状态的话,keepalived首先会执行脚本来重启nginx-master,重启仍然失败,会切换到备机运行。nginx-slave会瞬间绑定VIP来接替nginx_master的工作,当nginx-master恢复后keepalived会通过priority参数判断优先权将虚拟VIP地址192.168.200.199重新绑定给nginx-master的网卡。
1.实现了可弹性化的架构,在压力增大的时候可以临时添加web服务器添加到这个架构里面去;
2.upstream具有负载均衡能力,可以自动判断后端的机器,并且自动踢出不能正常提供服务的机器;
3.相对于lvs而言,正则分发和重定向更为灵活。而Keepalvied可保证单个nginx负载均衡器的有效性,避免单点故障;
4.用nginx做负载均衡,无需对后端的机器做任何改动。
5.nginx部署在docker容器里,即大量地节约开发、测试、部署的时间,又可以在出现故障时通过镜像快速恢复业务。
1.准备两台服务器,都安装好docker
2.docker pull nginx #这里获取的是最新的 nginx
3.创建文件夹用于使用自己定义的配置文件以及日志文件
mkdir -p /mydata/docker/nginx # 配置文件
#docker 起一个nginx来获取配置文件
docker run --name temp-nginx -p 80:80 -d nginx:latest
#拷贝配置文件
$ docker cp temp-nginx:/etc/nginx/ /mydata/docker/
之后再删除刚才的容器
4.在 /mydata/docker/nginx 目录下修改配置文件: vi nginx.conf,再修改conf.d下的default.conf文件
user root;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
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 /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
upstream gateway {
server 10.245.153.169:10010 weight=1 max_fails=2 fail_timeout=5s;
server 10.245.153.169:10011 weight=1 max_fails=2 fail_timeout=5s;
}
server {
listen 80;
listen [::]:80;
# 修改为宿主机的 IP地址
server_name 10.245.153.169;
#access_log /var/log/nginx/host.access.log main;
location / {
# 添加代理配置
proxy_pass http://gateway;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
add_header X-Cache $upstream_cache_status;
add_header Cache-Control no-cache;
#root /usr/share/nginx/html;
#index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {docker
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
5.在 /mydata/docker/nginx/html 目录下创建首页(仅仅是后面用来判断请求落在了哪个机器上,主机和备机能区分开就行): vi index.htmlMaster machine
6.启动nginx
docker run --name nginx-master --privileged=true --restart=always -p 80:80 \
-v /mydata/docker/nginx:/etc/nginx \
-v /mydata/docker/nginx/html:/usr/share/nginx/html \
-d nginx:latest
docker run --name nginx-slave --privileged=true --restart=always -p 80:80 \
-v /mydata/docker/nginx:/etc/nginx \
-v /mydata/docker/nginx/html:/usr/share/nginx/html \
-d nginx:latest
由于都是启动的80端口,故可以直接用ip+接口名来访问
可见,成功代理。
下面就要引入keepalived进行高可用
7.安装keepalived插件
这里不用docker,直接在服务器终端里输入以下指令yum install keepalived -y
进入/etc/keepalived/下 vi keepalived.conf
下面是运行着nginx-master容器的服务器的配置
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc #定义利用什么邮箱发送邮件
smtp_server smtp.163.com #定义邮件服务器信息
smtp_connect_timeout 30 #定义邮件发送超时时间
router_id 10.245.153.168 #(重点参数)局域网keppalived主机身份标识信息(每台唯一)
script_user root #添加运行健康检查脚本的用户
enable_script_security #添加运行健康检查脚本的组
}
vrrp_script chk_http_port {
script "/usr/local/src/nginx_check.sh" #表示将一个脚本信息赋值给变量check_web,down机后就运行这个文件
interval 5 #检测脚本执行的间隔
weight -20 #监测失败,则相应的vrrp_instance的优先级会减少20个点,这样主服务器会切换
}
vrrp_instance VI_1 {
state MASTER #keepalived角色描述信息,备份服务器上将 MASTER 改为 BACKUP
interface ens192 #将虚拟ip用于那块网卡
virtual_router_id 51 #主、备机的 virtual_router_id 必须相同
priority 100 #主、备机取不同的优先级,主机值较大,备份机值较小取90
advert_int 1 #主服务器组播包发送间隔时间
authentication { # 主备主机之间的认证表示信息
auth_type PASS #采用明文认证机制
auth_pass 1111 #编写明文密码
}
virtual_ipaddress {
服务器所在网段未分配的ip地址 #设置虚拟ip地址信息,此参数备节点设置和主节点相同
}
track_script {
chk_http_port #调用执行脚本
}
}
添加检查nginx状态的脚本vim /usr/local/src/nginx_check.sh
#!/bin/bash
# 传入容器名称
containerName=nginx-slave
currTime=`date +"%Y-%m-%d %H:%M:%S"`
# 查看进程是否存在
exist=`docker inspect --format '{{.State.Running}}' ${containerName}`
if [ "${exist}" != "true" ]; then
pkill keepalived #杀死所有keepalived服务进程
# 记录
echo "${currTime} docker容器宕机,容器名称:${containerName}" >> /mnt/xvde1/ms_ctynyd/scripts/wbwf_monitor.log
fi
一定要给这个脚本文件可执行权限(看到变成可执行的颜色),执行命令:chmod u+x /usr/local/src/nginx_check.sh
之后,在两台服务器上分别执行systemctl restart keepalived.service
命令。开启keepalived插件。
访问我们之前设置的虚拟ip发现可以访问成功
之后shutdown掉一个nginx,看看keepalived插件能否进行vip的迁移。还能够访问到我们的服务,成功。
压力配置均以上图所示进行。
访问虚拟ip,两个nginx+keepalived,来进行转发请求。
5000个线程的请求有14个超时未连接
直接通过网关访问请求
请求异常率大幅降低,但是响应时间最大值非常高
从上面两组测试对比可以知道,处理请求并发量受到nginx集群转发速度的影响。
上网查阅资料找到,可以在nginx.conf中修改nginx处理并发请求的能力
图中worker_connection值本来是1024,修改成为8192,再次测试查看结果。
异常率降低到零。说明1s内5000线程量的请求完全可以接受。
提高到两万
提高到三万
这是异常率变高,且请求响应时间大幅增加。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。