一、使用RabbitMQ实现松耦合设计
创建项目
pom配置文件
<?xml version="1.0" encoding="UTF-8"?>
全局配置文件
Consumer
spring.application.name=springcloud-mq
spring.rabbitmq.host=192.168.226.128
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=1111
#设置交换器的名称
mq.config.exchange=order.fanout
#短信服务队列的名称
mq.config.queue.sms=order.sms
#push服务队列名称
mq.config.queue.push=order.push
#红包服务队列名称
mq.config.queue.red=red
Provider
spring.application.name=springcloud-mq
spring.rabbitmq.host=192.168.226.128
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=1111
#设置交换器的名称
mq.config.exchange=order.fanout
消息接收者
SmsReceiver
package
PushReceiver
import
RedRecevier
@Component
消息消费者
/**
测试
@RunWith
二、RabbitMQ消息处理
1.RabbitMQ的消息持久化处理
消息的可靠性是 RabbitMQ 的一大特色,那么 RabbitMQ 是如何保证消息可靠性的呢——消息持久化。
搭建环境
创建项目参考direct交换器工程
模拟消息丢失
修改测试方法
//测试消息队列
开启consumer和provider
关闭consumer,再开启consumer
autoDelete 属性
@Queue: 当所有消费客户端连接断开,是否自动删除队列 true:删除 false:不删除
@Exchange:当所有绑定队列都不在使用时,是否自动删除交换器 true:删除 false:不删除
实验:
修改队列的自动删除属性,例如:@Queue(value="${mq.config.queue.error}",autoDelete="false")
@RabbitListener
测试:
三、RabbitMQ 中的消息确认 ACK 机制
1.什么是消息确认ACK?
如果在处理消息的过程中,消费者的服务器在处理消息时出现异常,那可能这条正在处理的消息就没有完成消息消费,数据就会丢失。为了确保数据不会丢失,RabbitMQ支持消息确认-ACK.
2. ACK的消息确认机制
ACK机制是消费者从RabbitMQ收到消息并处理完成后,反馈给RabbitMQ,RabbitMQ收到反馈后才将此消息从队列中删除。
1)如果一个消费者在处理消息出现了网络不稳定、服务器异常等现象,那么就不会有ACK反馈,RabbitMQ会认为这个消息没有正常消费,会将消息重新放入队列中。
2)如果在集群的情况下: RabbitMQ会立即将这个消息推送给这个在线的其他消费者。这种机制保证了在消费者服务端故障的时候,不丢失任何消息和任务。
3)消息永远不会从RabbitMQ中删除:只有当消费者正确发送ACK反馈,RabbitMQ确认收到后,消息才会从RabbitMQ服务器的数据中删除。
4)消息的ACK确认机制默认是打开的。
3. ACK机制的开发注意事项
如果忘记了ACK,那么后果很严重。当Consumer退出时,Message会一 直 重新分发。然后RabbitMQ会占用越来越多的内存,由于RabbitMQ会长时间运行,因此这个“内存泄漏”是致命的。
搭建环境
创建项目
模拟消息处理异常
修改ErrorReceiver
public
实验结果
解决 ACK 反馈问题
修改 Consusmer 配置文件
spring.application.name=springcloud-mq
spring.rabbitmq.host=192.168.226.128
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=1111
#设置交换器的名称
mq.config.exchange=log.direct
#info队列的名称
mq.config.queue.info=log.info
#info路由键
mq.config.queue.info.routing.key=log.info.routing.key
#error队列名称
mq.config.queue.error=log.error
#error路由键
mq.config.queue.error.routing.key=log.error.routing.key
#开启重试
spring.rabbitmq.listener.simple.retry.enabled=true
#重试次数,默认为3次
spring.rabbitmq.listener.simple.retry.max-attempts=5
四、Eureka 服务注册中心
1.什么是服务注册中心
服务注册中心是服务实现服务化管理的核心组件,类似于目录服务的作用,主要用来存储服务信息,譬如提供者 url 串、路由信息等。服务注册中心是 SOA 架构中最基础的设施之一。
服务注册中心的作用
- 服务的注册
- 服务的发现
例如QQ群
常见的注册中心有哪些
- Dubbo 的注册中心 Zookeeper
- Sringcloud 的注册中心 Eureka
2.服务注册中心解决了什么问题
- 服务管理
- 服务的依赖关系管理
3.什么是 Eureka 注册中心
Eureka 是 Netflix 开发的服务发现组件,本身是一个基于 REST 的服务。Spring Cloud将它集成在其子项目 spring-cloud-netflix 中,以实现 Spring Cloud 的服务注册于发现,同时 还提供了负载均衡、故障转移等能力。
Eureka 注册中心三种角色
1)Eureka Server
通过 Register、Get、Renew 等接口提供服务的注册和发现。
2)Application Service (Service Provider)
服务提供方
把自身的服务实例注册到 Eureka Server 中
3)Application Client (Service Consumer)
服务调用方
通过 Eureka Server 获取服务列表,消费服务。
五、Eureka 入门案例
1 创建项目
修改 pom 文件添加依赖
<?xml version="1.0" encoding="UTF-8"?>
修改 application.properties 全局配置文件
spring.application.name=eureka-server
server.port=8761
#是否将自己注册到Eureka-server中,默认的为true
eureka.client.register-with-eureka=false
#是否从Eureka-server中获取服务注册信息,默认为true
eureka.client.fetch-registry=false
修改启动类
package
通过浏览器访问 Eureka-Server 服务管理平台
六、搭建高可用 Eureka 注册中心(Eureka 集群)
1.创建项目
配置文件
#设置 eureka 实例名称,与配置文件的变量为主
eureka.instance.hostname=eureka2
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://eureka1:8761/eureka/
在搭建 Eureka 集群时,需要添加多个配置文件,并且使用 SpringBoot 的多环境配置方
式。集群中需要多少节点就添加多少个配置文件。
2.在配置文件中配置集群节点
eureka1
spring.application.name=eureka-server
server.port=8761
#设置 eureka 实例名称,与配置文件的变量为主
eureka.instance.hostname=eureka1
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://eureka2:8761/eureka/
eureka2
spring.application.name=eureka-server
server.port=8761
#设置 eureka 实例名称,与配置文件的变量为主
eureka.instance.hostname=eureka2
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://eureka1:8761/eureka/
3.添加 logback 日志配置文件
4.Eureka 集群部署
部署环境:需要安装 jdk1.8,正确配置环境变量。
注意:需要关闭 linux 的防火墙,或者是开放 8761 端口
将项目打包
Maven install
上传实例
在/usr/local/创建一个 eureka 的目录
将项目的 jar 包拷贝到/usr/local/eureka
编写一个启动脚本文件
#!/bin/bash
cd `dirname $0`
CUR_SHELL_DIR=`pwd`
CUR_SHELL_NAME=`basename ${BASH_SOURCE}`
JAR_NAME="项目名称"
JAR_PATH=$CUR_SHELL_DIR/$JAR_NAME
#JAVA_MEM_OPTS=" -server -Xms1024m -Xmx1024m -XX:PermSize=128m"
JAVA_MEM_OPTS=""
#如果是多环境配置需要在该选项中指定profile
SPRING_PROFILES_ACTIV="-Dspring.profiles.active=配置文件profile名称"
#如果没有多环境配置将 SPRING_PROFILES_ACTIV注释掉,将SPRING_PROFILES_ACTIV=""释放开
#SPRING_PROFILES_ACTIV=""
LOG_DIR=$CUR_SHELL_DIR/logs
LOG_PATH=$LOG_DIR/${JAR_NAME%..log
echo_help()
{
echo -e "syntax: sh $CUR_SHELL_NAME start|stop"
}
if [ -z $1 ];then
echo_help
exit 1
fi
if [ ! -d "$LOG_DIR" ];then
mkdir "$LOG_DIR"
fi
if [ ! -f "$LOG_PATH" ];then
touch "$LOG_DIR"
fi
if [ "$1" == "start" ];then
# check server
PIDS=`ps --no-heading -C java -f --width 1000 | grep $JAR_NAME | awk '{print $2}'`
if [ -n "$PIDS" ]; then
echo -e "ERROR: The $JAR_NAME already started and the PID is ${PIDS}."
exit 1
fi
echo "Starting the $JAR_NAME..."
# start
nohup java $JAVA_MEM_OPTS -jar $SPRING_PROFILES_ACTIV $JAR_PATH >> $LOG_PATH 2>&1 &
COUNT=0
while [ $COUNT -lt 1 ]; do
sleep 1
COUNT=`ps --no-heading -C java -f --width 1000 | grep "$JAR_NAME" | awk '{print $2}' | wc -l`
if [ $COUNT -gt 0 ]; then
break
fi
done
PIDS=`ps --no-heading -C java -f --width 1000 | grep "$JAR_NAME" | awk '{print $2}'`
echo "${JAR_NAME} Started and the PID is ${PIDS}."
echo "You can check the log file in ${LOG_PATH} for details."
elif [ "$1" == "stop" ];then
PIDS=`ps --no-heading -C java -f --width 1000 | grep $JAR_NAME | awk '{print $2}'`
if [ -z "$PIDS" ]; then
echo "ERROR:The $JAR_NAME does not started!"
exit 1
fi
echo -e "Stopping the $JAR_NAME..."
for PID in $PIDS; do
kill $PID > /dev/null 2>&1
done
COUNT=0
while [ $COUNT -lt 1 ]; do
sleep 1
COUNT=1
for PID in $PIDS ; do
PID_EXIST=`ps --no-heading -p $PID`
if [ -n "$PID_EXIST" ]; then
COUNT=0
break
fi
done
done
echo -e "${JAR_NAME} Stopped and the PID is ${PIDS}."
else
echo_help
exit 1
fi
设置启动脚本的运行权限
Chmod -R 755 server.sh
修改 linux 的 host 文件
Vim /etc/hosts
192.168.226.128 eureka1
192.168.226.129 eureka2
启动 eureka 注册中心
./server.sh start 启动
./server.sh stop 停止
通过浏览器访问注册中心的管理页面
七、在高可用的 Eureka 注册中心中构建 provider 服务
1.创建项目
修改pom文件
<?xml version="1.0" encoding="UTF-8"?>
修改启动类
@EnableEurekaClient
修改 provider 的配置文件
spring.application.name=eureka-provider
server.port=9090
eureka.client.serviceUrl.defaultZone=http://eureka1:8761/eureka/,http://eureka2:8761/eureka/
修改 windows 的 host 文件
路径:C:WindowsSystem32driversetc
2.编写服务接口
创建接口
package
pojo实体类
package
八、在高可用的 Eureka 注册中心中构建 consumer 服务
1 创建项目
服务的消费者与提供者都需要再 Eureka 注册中心注册。
Consumer 的配置文件
spring.application.name=eureka-consumer
server.port=9091
eureka.client.serviceUrl.defaultZone=http://eureka1:8761/eureka/,http://eureka2:8761/eureka/
在 Service 中完成服务的调用
@Service
Controller
@RestController
测试