微服务

1.认识微服务

微服务是一种经过良好架构设计的分布式架构方案,微服务架构特征:

  • 单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责,避免重复业务开发
  • 面向服务:微服务对外暴露业务接口
  • 自治:团队独立、技术独立、数据独立、部署独立
  • 隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题

1

单体架构特点?

  • 简单方便,高度耦合,扩展性差,适合小型项目。例如:学生管理系统

分布式架构特点?

  • 松耦合,扩展性好,但架构复杂,难度大。适合大型互联网项目,例如:京东、淘宝

微服务:一种良好的分布式架构方案

  • 优点:拆分粒度更小、服务更独立、耦合度更低
  • 缺点:架构非常复杂,运维、监控、部署难度提高

2

2.服务远程调用

基于java通过RestTemplate发送Http请求
1、注册restTemplate到Spring容器

3

2、使用restTemplate发送Http请求

4

3.Eureka(注册中心)

提供者与消费者

  • 服务提供者:一次业务中,被其它微服务调用的服务。(提供接口给其它微服务)
  • 服务消费者:一次业务中,调用其它微服务的服务。(调用其它微服务提供的接口)

一个服务既可以是服务消费者也可以是服务消费者,两者是相对的。

eureka的作用

1、消费者该如何获取服务提供者具体信息?

  • 服务提供者启动时向eureka注册自己的信息
  • eureka保存这些信息
  • 消费者根据服务名称向eureka拉取提供者信息

2、如果有多个服务提供者,消费者该如何选择?

  • 服务消费者利用负载均衡算法,从服务列表中挑选一个

3、消费者如何感知服务提供者健康状态?

  • 服务提供者会每隔30秒向EurekaServer发送心跳请求,报告健康状态
  • eureka会更新记录服务列表信息,心跳不正常会被剔除
  • 消费者就可以拉取到最新的信息

5

4、在Eureka架构中,微服务角色有两类:

  1. EurekaServer:服务端,注册中心
  • 记录服务信息
  • 心跳监控
  1. EurekaClient:客户端
  2. Provider:服务提供者,例如案例中的user-service
    - 注册自己的信息到EurekaServer
    - 每隔30秒向EurekaServer发送心跳
  3. consumer:服务消费者,例如案例中的order-service
    - 根据服务名称从EurekaServer拉取服务列表
    - 基于服务列表做负载均衡,选中一个微服务后发起远程调用

4.服务注册

引入依赖

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

配置yml

6

拉取服务

服务拉取是基于服务名称获取服务列表,然后在对服务列表做负载均衡
1、修改OrderService的代码,修改访问的url路径,用服务名代替ip、端口:

1
String url = "http://userservice/user/"+ order.getUserId();

2、在order-service项目的启动类OrderApplication中的RestTemplate添加负载均衡注解:

1
2
3
4
5
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}

总过程

1、搭建EurekaSerer

  • 引入eureka-server依赖
  • 添加@EnableEurekaServer注解
  • 在application.yml中配置eureka地址

2、服务注册

  • 引入eureka-client依赖
  • 在application.yml中配置eureka地址

3、服务发现

  • 引入eureka-client依赖
  • 在application.yml中配置eureka地址
  • 给RestTemplate添加@LoadBalanced注解
  • 用服务提供者的服务名称远程调用

问题:Springcloud使用eureka客户端报错:
com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException:
解决方案:yml文件层级出错,改正即可

6.Ribbon负载均衡

负载均衡流程

7

负载均衡策略

通过定义IRule实现可以修改负载均衡规则,有两种方式:
1、代码方式:在order-service中的OrderApplication类中,定义一个新的IRule:

1
2
3
4
@Bean
public IRule myRule(){
return new RandomRule();//定义为随机
}

2、配置文件方式:在order-service的application.yml文件中,添加新的配置也可以修改规则:

1
2
3
userservice:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则

总结

  1. Ribbon负载均衡规则
  • 规则接口是IRule
  • 默认实现是ZoneAvoidanceRule,根据zone选择服务列表,然后轮询
  1. 负载均衡自定义方式
  • 代码方式:配置灵活,但修改时需要重新打包发布
  • 配置方式:直观、方便,无需重新打包发布但是无法做全局配置
  1. 饥饿加载
  • 开启饥饿加载
  • 指定饥饿加载的微服务名称

7.Nacos注册中心

启动服务

1
startup.cmd -m standalone

访问

1
在浏览器输入地址:http://127.0.0.1:8848/nacos  即可:

导入依赖包

1
2
3
4
5
6
7
8
9
10
11
12
13
<-- 父工程 -->
<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>
<!--nacos客户端依赖包 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

配置yml文件

1
2
3
4
//客户端
cloud:
nacos:
server-addr: localhost:8848 #nacos的注册中心地址

集群分级存储服务

8

优先同集群负载均衡访问策略

  • NacosRute负载均衡策略
    1. 优先选择同集群服务实例列表
    2. 本地集群找不到提供者,才去其它集群寻找,并且会报警告
    3. 确定了可用实例列表后,再采用随机负载均衡挑选实例
  • 实例的权重控制
    1. Nacos控制台可以设置实例的权重值,
    2. 0~1之间同集群内的多个实例,
    3. 权重越高被访问的频率越高权重设置为0则完全不会被访问
  • Nacos环境隔离
    1. namespace用来做环境隔离
    2. 每个namespace都有唯一id不同
    3. namespace下的服务不可见

8.Nacos配置中心

统一配置管理

  • 配置获取步骤:
    9
  1. pom文件中引入配置依赖
1
2
3
4
5
<!--nacos配置管理客户端依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
  1. 对应微服务模块导入配置文件
1
2
3
4
5
6
7
8
9
10
11
bootstrap.yml文件
spring:
application:
name: userService #服务名称
profiles:
active: dev #开发环境,这里是dev
cloud:
nacos:
server-addr: localhost:8848 #Nacos地址
config:
file-extension: yaml #文件后缀名
  1. 读取配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1、Controller中加入@RefreshScope注解 //动态刷新配置,配置热更新、
@RefreshScope
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@Value("${pattern.dateformat}")
private String dateformat;
@Autowired
private PatternConfig patternConfig;
@GetMapping("/now")
public String now() {
return LocalDateTime.now().format(DateTimeFormatter.ofPattern(patternConfig.getDateformat()));
}
2、注入PatternConfig配置类对象,届时自动热加载
@Component
@Data
@ConfigurationProperties(prefix = "pattern")
public class PatternConfig {
private String dateformat;
}
  1. Nacos配置更改后,微服务可以实现热更新,方式:
  • 通过@Value注解注入,结合@RefreshScope来刷新
  • 通过@ConfigurationProperties注入,自动刷新
  1. 注意事项:
  • 不是所有的配置都适合放到配置中心,维护起来比较麻烦
  • 建议将一些关键参数,需要运行时调整的参数放到nacos配置中心,一般都是自定义配置
  1. 微服务会从nacos读取的配置文件:
  • [服务名]-[spring.profile.active].yaml,环境配置
  • [服务名].yaml,默认配置,多环境共享
  1. 优先级:
    [服务名]-[环境].yaml>[服务名].yaml>本地配置

Nacos集群搭建步骤:

  1. 搭建MySQL集群并初始化数据库表
  2. 下载解压nacos
  3. 修改集群配置(节点信息)、数据库配置
  4. 分别启动多个nacos节点
  5. nginx反向代理

9.Feign (Http客户端,用于发送Http请求)

1、 引入依赖

1
2
3
4
5
<!--feign依赖包-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2、 启动类上加@EnableFeignClients注解

3、 编写Feign客户端

1
2
3
4
5
@FeignClient("userService")
public interface UserClient {
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id)
}

4、 编写FeignClient接口

5、 使用FeignClient中定义的方法代替RestTemplate

自定义feign配置

10

  1. 方式一:在配置文件中配置
1
2
3
4
5
feign:
client:
config:
default:
loggerLevel: FULL
  1. 方式二:java代码方式,需要先声明一个Bean
1
2
3
4
5
6
public class FeignClientConfiguration{
@Bean
public Logger.Level feignLogLevel(){
return Logger.Level.BASIC;
}
}
  • 而后如果是全局配置,则把它放到@EnableFeignClients这个注解中:
1
@EnableFeignClients(defaultConfiguration = FeignClientConfiguration.class)
  • 如果是局部配置,则把它放到@FeignClient这个注解中:
1
@FeignClient(value ="userservice",configuration = FeignClientConfiguration.class)

Feign的日志级别

  • 级别从低到高分为:
    1. NONE:默认的,不记录任何日志
    2. BASIC:仅记录请求方法、URL、响应状态码及执行时间
    3. HEADERS:在BASIC的基础上,额外记录请求和响应的header
    4. FULL:在HEADERS的基础上,额外记录请求和响应的body

Feign的日志配置:

  1. 方式一是配置文件,feign.client.config.xxx.loggerLevel
  • 如果xxx是default则代表全局
  • 如果xxx是服务名称,例如userservice则代表某服务
  1. 方式二是java代码配置Logger.Level这个Bean
  • 如果在@EnableFeignClients注解声明则代表全局
  • 如果在@FeignClient注解中声明则代表某服务

feign性能调优

Feign底层的客户端实现:

  • URLConnection:默认实现,不支持连接池
  • Apache HttpClient:支持连接池
  • OKHttp:支持连接池
    因此优化Feign的性能主要包括:
    使用连接池代替默认的URLConnection日志级别,最好用basic或none
  1. 引入依赖
1
2
3
4
5
<!--httpClient的依赖-->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
  1. 设置配置
1
2
3
4
5
6
7
8
9
feign:
client:
config:
default:
loggerLevel: FULL
httpclient: #配置连接池
enabled: true #开启feign对HttpClient的支持
max-connections: 200 #最大连接数
max-connections-per-route: 50 #每一个路经的最大连接数

Feign的优化:
1.日志级别尽量用basic
2.使用HttpClient或OKHttp代替URLConnection引入feign-httpClient依赖,配置文件开启httpClient功能,设置连接池参数

  1. Feign的最佳实践:
  • 让controller和FeignClient继承同一接口
  • 将FeignClient、POJO、Feign的默认配置都定义到一个项目中,供所有消费者使用
  1. 当定义的FeignClient不在SpringBootApplication的扫描包范围时,这些FeignClient无法使用。有两种方式解决:
  • 方式一:指定FeignClient所在包
1
@EnableFeignClients(basePackages ="cn.itcast.feign.clients")
  • 方式二:指定FeignClient字节码
1
GEnableFeignClients(clients={UserClient.class})

10.Gateway网关

  • 网关的作用:
    1,对用户请求做身份认证、权限校验
    2,将用户请求路由到微服务,并实现负载均衡
    3,对用户请求做限流

  • 搭建网关服务:
    网关本身也属于一个微服务,因此需要注册到Nacos服务发现中

1、新建一个微服务,引入依赖

1
2
3
4
5
6
7
8
9
10
<!--网关依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服务发现依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2、配置路由,和nacos地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
server:
port: 10010
spring:
application:
name: gateway
cloud:
nacos:
server-addr: localhost:8848 #nacos地址
gateway:
routes:
- id: user-service #路由标识,必须唯一
uri: lb://userService #路由的目标地址
predicates: #路由断言,判断请求是否符合规则
- Path=/user/** #路径断言,判断路径是否是以/user开头,如果是则符合
- id: order-service
uri: lb://orderService
predicates:
- Path=/order/**

3、流程:
11

路由断言工厂

12

过滤器

13

  1. 全局过滤器 GlobalFilter
    14

15

全局过滤器的作用是什么?
1,对所有路由都生效的过滤器,并且可以自定义处理逻辑
实现全局过滤器的步骤?
1,实现GlobalFilter接口
2,添加@Order注解或实现Ordered接口
3,编写处理逻辑

4、过滤器执行顺序

路由过滤器、defaultFilter、全局过滤器的执行顺序?
1,order值越小,优先级越高
2,当order值一样时,顺序是defaultFilter最先,然后是局部的路由过滤器,最后是全局过滤器

5、网关的CORS跨域配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
globalcors: # 全局的跨域处理
add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
corsConfigurations:
'[/**]':
allowedOrigins: # 允许哪些网站的跨域请求
- "http://localhost:8090"
- "http://www.leyou.com"
allowedMethods: # 允许的跨域ajax的请求方式
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求中携带的头信息
allowCredentials: true # 是否允许携带cookie
maxAge: 360000 # 这次跨域检测的有效期

11.Docker

原理

1、Docker是一个快速交付应用、运行应用的技术:

  1. 可以将程序及其依赖、运行环境一起打包为一个镜像可以迁移到任意Linux操作系统
  2. 运行时利用沙箱机制形成隔离容器,各个应用互不干扰
  3. 启动、移除都可以通过一行命令完成,方便快捷
    16

镜像与容器

镜像(Image): Docker将应用程序及其所需的依赖、函数库、环境、配置等文件打包在一起,称为镜像。
容器(Container): 镜像中的应用程序运行后形成的进程就是容器,只是Docker会给容器做隔离,对外不可见。
17

Docker架构

Docker是一个CS架构的程序,由两部分组成:

  • 服务端(server):Docker守护进程,负责处理Docker指令,管理镜像、容器等
  • 客户端(client):通过命令或RestAPI向Docker服务端发送指令。可以在本地或远程向服务端发送指令
    18

1,镜像:
将应用程序及其依赖、环境、配置打包在一起

2,容器
镜像运行起来就是容器,一个镜像可以运行多个容器

3,Docker结构:
服务端:接收命令或远程请求,操作镜像或容器客户端:发送命令或者请求到Docker服务端

4,DockerHub :
一个镜像托管的服务器,类似的还有阿里云镜像服务,统称为DockerRegistry

Docker镜像命令

19

1
2
3
4
5
6
7
systemctl start docker //启动Docker
docker pull 服务名 //拉取镜像
docker images //查看镜像
docker rmi //删除
docker push //推送
docker save //保存镜像到本地
docker load //读取本地镜像文件

Docker容器命令

20

1
2
3
4
5
6
7
8
9
10
11
docker run //创建并启动容器
docker ps //查看运行中的容器
docker stop //停止容器
docker start //启动容器
docker restart //重启容器
docker rm //删除容器
docker exec //进入容器
docker attach //进入容器
docker logs //查看日志
docker top //查看容器中运行的进程
docker inspect //查看容器内部细节

docker run --name containerName -p 80:80 -d nginx
命令解读:

  • docker run:创建并运行一个容器
  • –name:给容器起一个名字,比如叫做mn
  • -p:将宿主机端口与容器端口映射,冒号左侧是宿主机端口,右侧是容器端口
  • -d:后台运行容器
  • nginx:镜像名称,例如nginx

docker exec -it mn bash
命令解读:

  • docker exec:进入容器内部,执行一个命令
  • -it:给当前进入的容器创建一个标准输入、输出终端,允许我们与容器交互
  • mn:要进入的容器的名称
  • bash:进入容器后执行的命令,bash是一个linux终端交互命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
docker logs -f 镜像名 //持续跟踪日志
//进入容器并进行交互
docker exec -it mn bash
//进入nginx主页文件夹
cd /usr/share/nginx/html
//容器内安装Vim编辑器
apt get update && apt get install vim
//查看容器状态:
docker ps -a //添加-a参数查看所有状态的容器删除容器:
docker rm -f //不能删除运行中的容器,除非添加-f参数进入容器:
docker exec-t[容器名][要执行的命令]exec命令可以进入容器修改文件,但是在容器内修改文件是不推荐的
//创建redis容器
docker run --name mr -p 6379:6379 -d redis redis-server --appendonly yes
//进入容器并进行交互
docker exec -it mr bash/redis-cli

Docket数据卷命令

数据卷:是一个虚拟目录,指向宿主机文件系统中的某个目录
作用:将容器与数据分离,解耦合,方便操作容器内数据,保证数据安全
21

1、常见数据卷命令

1
2
3
4
5
6
7
8
9
10
//创建数据卷
docker volume creat [数据卷名称]
//显示一个或多个volume的信息
docker volume inspect
//列出所有的volume
docker volume ls
//删除未使用的volume
docker volume prune
//删除一个或多个指定的volume
docker volume rm [数据卷名称]

2、挂载数据卷并与容器相连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
docker run: 就是创建并运行容器
--name mn: 给容器起个名字叫mn
-v html:/root/htm: 把html数据卷挂载到容器内的/root/html这个目录中
-p 8080:80: 把宿主机的8080端口映射到容器内的80端口
nginx: 镜像名称
docker run --name mn -p 80:80 -v html:/usr/share/nginx/html -d nginx
//如果数据卷不存在,docker会自动创建数据卷,不用刻意去创建数据卷

//创建并运行mysql容器
docker run \
--name mysql \
-e MYSQL_ROOT_PASSWORD=123 \
-p 3306:3306 \
-v /tmp/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf \
-v /tmp/mysql/data:/var/lib/mysql \
-d \
mysql:5.7.25

数据卷挂载方式对比
22

  1. docker run的命令中通过-v参数挂载文件或目录到容器中:
    -v volume名称:容器内目录
    -v宿主机文件:容器内文件
    -v宿主机目录:容器内目录
  2. 数据卷挂载与目录直接挂载的
  • 数据卷挂载耦合度低,由docker来管理目录,但是目录较深,不好找
  • 目录挂载耦合度高,需要我们自己管理目录,不过目录容易寻找查看

镜像结构

镜像是分层结构,每一层称为一个Layer

  1. Baselmage层:包含基本的系统函数库、环境变量、文件系统
  2. Entrypoint:入口,是镜像中应用启动的命令
  3. 其它:在Baselmage基础上添加依赖、安装程序、完成整个应用的安装和配置

自定义镜像

Dockerfile就是一个文本文件,其中包含一个个的指令(Instruction),用指令来说明要执行什么操作来构建镜像。每
-个指令都会形成一层Layer。
23

1
2
3
4
1.Dockerfile的本质是一个文件,通过指令描述镜像的构建过程
2.Dockerfile的第一行必须是FROM,从一个基础镜像来构建
3.基础镜像可以是基本操作系统,如Ubuntu。也可以是其他人制作好的镜像,例如:java:8-alpine
update user set authentication string=password('123') where user='985211'

DockerCompose

  1. Docker Compose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器
  2. Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。
1
2
systemctl start docker //启动Docker
docker-compose up -d nacos //优先启动nacos注册中心

Docker镜像仓库

24

  1. 推送本地镜像到仓库前都必须重命名(docker tag)镜像,以镜像仓库地址为前缀
  2. 镜像仓库推送前需要把仓库地址配置到docker服多的daemon.json文件中,被docker信任
  3. 推送使用docker push命令
  4. 拉取使用docker pull命令

12.异步通信

基于Feign同步调用:
同步调用的优点:

  • 时效性较强,可以立即得到结果

同步调用的问题:

  • 耦合度高
  • 性能和吞吐能力下降有额外的资源消耗
  • 有级联失败问题

异部调用:

  • 也就是说只有支付成功后请求才会被发送到这个服务,如果支付失败,在第一步调用接口时就会返回失败
  • 这里要表示的就是,用户只关心支付成功没有,也就是说只关心第一步成功没有
  • 至于后面的订单或者是短信通知相对来说不重要了,因为用户知道钱已经给了,如果有问题就再说
    25

异步通信的优点:

  1. 耦合度低
  2. 吞吐量提升
  3. 故障隔离
  4. 流量削峰
    异步通信的缺点:
  5. 依赖于Broker的可靠性、安全性、吞吐能力
  6. 架构复杂了,业务没有明显的流程线,不好追踪管理

大多数情况下用的是同步通讯

13.消息队列(MQ)

26

RabbitMQ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//安装
1,docker pull rabbitmq
//运行mq
docker run \
-e RABBITMQ_DEFAULT_USER=iTddey \
-e RABBITMQ_DEFAULT_PASS=123321 \
--name mq \
--hostname mq1 \
-p 15672:15672 \
-p 5672:5672 \
-d \
rabbitmq:latest
//进入容器内部
docker exec -it mq /bin/bash
//步骤二:开启web界面管理插件
rabbitmq-plugins enable rabbitmq_management

27

常见消息模型

28

基本消息队列的消息发送流程:

  1. 建立connection
  2. 创建channel
  3. 利用channel声明队列
  4. 利用channel向队列发送消息

基本消息队列的消息接收流程:

  1. 建立connection
  2. 创建channel
  3. 利用channel声明队列
  4. 定义consumer的消费行为handleDelivery()
  5. 利用channel将消费者与队列绑定

SpringAMQP

  1. 基本队列BasicQueue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//1,父类中引依赖
<!--AMQP依赖,包含RabbitMQ-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
//2,导入配置
spring:
rabbitmq:
host: 192.168.50.80
port: 5672
username: iTddey
password: 123321
virtual-host: /
//3,编写消息发送测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringAMQPTest {
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
public void testSimpleQueue(){
String queueName = "simple.queue";
String message = "hello,spring amqp";
rabbitTemplate.convertAndSend(queueName,message);
}
}
//在消费者中编写消息接收监听器
@Component
public class SpringRabbitListener {
@RabbitListener(queues = "simple.queue")
public void listenSimpleQueueMessage(String msg) throws InterruptedException {
System.out.println("spring消费者接收到消息︰【" + msg + "】 ");
}
}

SpringAMQP如何接收消息?

  • 引入amqp的starter依赖
  • 配置RabbitMQ地址
  • 定义类,添加@Component注解
  • 类中声明方法,添加@RabbitListener注解,方法参数接收消息
  • 注意:消息一旦消费就会从队列删除,RabbitMQ没有消息回溯功能
  1. 工作队列WorkQueue

29

消息预取机制:修改消费者服务yml配置文件中的preFetch的值,可以设置预取消息的上限

1
2
3
4
5
6
7
8
9
10
spring:
rabbitmq:
host: 192.168.50.80 #主机名
port: 5672 #端口
username: iTddey #用户名
password: 123321 #密码
virtual-host: / #虚拟主机
listener:
direct:
prefetch: 1 #每次只能获取一条消息,处理完成才能获取下一个消息

Publish,Subscribe(发布,订阅模型)

30

Fanou Exchange 广播

31
32
33

交换机的作用是什么?

  1. 接收publisher发送的消息
  2. 将消息按照规则路由到与之绑定的队列
  3. 不能缓存消息,路由失败,消息丢失
  4. FanoutExchange的会将消息路由到每个绑定的队列

声明队列、交换机、绑定关系的Bean是什么?

  1. Queue
  2. FanoutExchange
  3. Binding
Direct Exchange 路由

34
35

描述下Direct交换机与Fanout交换机的差异?

  1. Fanout交换机将消息路由给每一个与之绑定的队列
  2. Direct交换机根据RoutingKey判断路由给哪个队列
  3. 如果多个队列具有相同的RoutingKey,则与Fanout功能类似

基于@RabbitListener注解声明队列和交换机有哪些常见注解?

  1. @Queue
  2. @Exchange
Topic Exchange 话题

36

消息转换器

1
2
3
4
5
6
//父工程引入依赖
<!--Json转换器-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>

SpringAMQP中消息的序列化和反序列化是怎么实现的?

利用MessageConverter实现的,默认是JDK的序列化

注意发送方与接收方必须使用相同的Messageconverter