一、前言
本篇将同时讲一下服务间的调用和消息中间件的使用。我们会简单的了解一下cloud框架体系中自带的feign完成服务间通信的例子(详情请移步官网文档:openFeign),还会初步探索一下stream-rabbit的使用(官方文档:stream)。
二、Feign
cloud自带的服务间的通信机制-feign,是cloud框架采用的最多的,以下是一些简单的实现
依赖添加
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
定义feign接口,其中FeignClient注解value指向的是eureka中的服务名。
@FeignClient(value = "user")
public interface UserFeignClient {
@GetMapping(value = "user/list")
List<User> getUserList();
@GetMapping(value = "user/updateError")
void updateError() throws Exception;
}
在需要用到的服务启动项上添加feign接口扫描
@EnableFeignClients(basePackages = {"接口路径"})
然后在需要用到的地方注入接口,如:
@RestController
public class TestController {
private final UserFeignClient client;
public TestController(UserFeignClient client) {
this.client = client;
}
@GetMapping("/test")
public List<User> getUserList() {
return client.getUserList();
}
}
如此就完成了一次简单的服务调用的逻辑代码,至于熔断机制本次并不涉及,感兴趣可以移步官方文档。
效果展示
左下方启动的服务有:eureka注册中心(8761),config配置中心(19000),user服务(8081),feign测试服务(8083)
右边编码区做了一个测试接口
三、stream-rabbit
依赖添加
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
定义客户端
(此处样例定义了两个客户端,取名如下,需并且通过@Input和@Output完成基础方法实现)
public interface StreamClient {
String STREAM_FIRST = "STREAM_FIRST";
String STREAM_SECOND = "STREAM_SECOND";
@Input(StreamClient.STREAM_FIRST)
SubscribableChannel firstInput();
@Output(StreamClient.STREAM_FIRST)
MessageChannel firstOutput();
@Input(StreamClient.STREAM_SECOND)
SubscribableChannel secondInput();
@Output(StreamClient.STREAM_SECOND)
MessageChannel secondOutput();
}
定义监听
(针对如上定义的客户端,需要针对性的定义两个监听,注意此处注解的使用,监听的关键注解@StreamListener可以了解一下,通常此处会编写消息接收后的业务逻辑,因人而异,此处不做展开)
@Component
@EnableBinding(StreamClient.class)
public class StreamListen {
@Autowired
private QueueMsgMapper msgMapper;
@StreamListener(StreamClient.STREAM_FIRST)
public void firstStream(Object msg){
//boolean dealWith = false;
QueueMsg queueMsg = (QueueMsg)msg;
System.out.println("消息【"+ queueMsg.getMsg() +"】,消费中");
queueMsg.setStatus(QueueMsgStatus.CONSUMING.getCode());
msgMapper.updateByPrimaryKeySelective(queueMsg);
//todo 业务逻辑
//if dealWith = true
System.out.println("消息【"+ queueMsg.getMsg() +"】,业务处理成功");
queueMsg.setStatus(QueueMsgStatus.SUCCESS.getCode());
msgMapper.updateByPrimaryKeySelective(queueMsg);
//else
System.out.println("消息【"+ queueMsg.getMsg() +"】,业务处理失败");
queueMsg.setStatus(QueueMsgStatus.FAIL.getCode());
msgMapper.updateByPrimaryKeySelective(queueMsg);
//todo 重试机制
}
@StreamListener(StreamClient.STREAM_SECOND)
public void secondStream(Object msg){
//boolean dealWith = false;
QueueMsg queueMsg = (QueueMsg)msg;
System.out.println("消息【"+ queueMsg.getMsg() +"】,消费中");
queueMsg.setStatus(QueueMsgStatus.CONSUMING.getCode());
msgMapper.updateByPrimaryKeySelective(queueMsg);
//todo 业务逻辑
//if dealWith = true
System.out.println("消息【"+ queueMsg.getMsg() +"】,业务处理成功");
queueMsg.setStatus(QueueMsgStatus.SUCCESS.getCode());
msgMapper.updateByPrimaryKeySelective(queueMsg);
//else
System.out.println("消息【"+ queueMsg.getMsg() +"】,业务处理失败");
queueMsg.setStatus(QueueMsgStatus.FAIL.getCode());
msgMapper.updateByPrimaryKeySelective(queueMsg);
//todo 重试机制
}
}
使用
在需要的地方注入客户端,调用Output()方法即可完成消息的发送,请配合rabbit进行相应的测试
效果展示略过。。。
四、小结
至此一个基础的cloud框架搭建已完成,但是如果要应用到生产中,任需对各组件进行二次配置,以适应不同的环境。
(概念性的知识请看官自行补充,官网文档比我专业多了)