【消息队列开发】 设计网络通信协议

🍃前言

本次开发任务

  • 设计网络通信协议

用于客户端和服务器之间的通信

🎍明确需求

我们先来看一下我们最初的客户端与服务器的交互模型
在这里插入图片描述

我们可以看到,生产者和消费者都是客户端,都需要通过网络和Broker Server 进行通信。

此处我们使用 TCP 协议,来作为通信的底层协议。同时在这个基础上自定义应用层协议,完成客户端对服务器这边功能的远程调用。

要调用的功能有:

  • 创建 channel
  • 关闭 channel
  • 创建 exchange
  • 删除 exchange
  • 创建 queue
  • 删除 queue
  • 创建 binding
  • 删除 binding
  • 发送 message
  • 订阅 message
  • 发送 ack
  • 返回 message (服务器 -> 客户端)

🍀设计应用层协议

我们这里使⽤⼆进制的方式设定协议

请求与相应报文格式如下:

  • 请求
    在这里插入图片描述
  • 响应
    在这里插入图片描述

其中 type 表⽰请求响应不同的功能,取值如下:

  • 0x1 创建 channel
  • 0x2 关闭 channel
  • 0x3 创建 exchange
  • 0x4 销毁 exchange
  • 0x5 创建 queue
  • 0x6 销毁 queue
  • 0x7 创建 binding
  • 0x8 销毁 binding
  • 0x9 发送 message
  • 0xa 订阅 message
  • 0xb 返回 ack
  • 0xc 服务器给客⼾端推送的消息。(被订阅的消息)响应独有的。

其中 payload 部分, 会根据不同的 type, 存在不同的格式。

对于请求来说, payload 表示这次方法调用的各种参数信息

对于响应来说, payload 表示这次方法调用的返回值

🎄定义 Request / Response

Request 类实现如下:

ublic class Request {
	private int type;
	private int length;
	private byte[] payload;
	// 省略 getter setter
}

Response 类实现如下:

public class Response {
	private int type;
	private int length;
	private byte[] payload;
	// 省略 getter setter
}

关于 payload里面的数据,我们另外用别的类进行表示。

🌴定义参数父类与返回值父类

构造⼀个类表示方法的参数,作为 Request 的 payload

不同的方法中,参数形态各异,但是有些信息是通用的,使用⼀个⽗类表示出来。具体每个⽅法的参数再通过继承的方式体现.

参数父类实现如下:

public class BaseArguments implements Serializable {
	// 表⽰⼀次请求/响应的唯⼀ id. ⽤来把响应和请求对上.
	protected String rid;
	protected String channelId;
	// 省略 getter setter
}

此处的 rid 和 channelId 都是基于 UUID 来生成的, rid 用来标识⼀个请求-响应。这⼀点在请求响应比较多的时候非常重要.

返回值父类和参数同理,也需要构造⼀个类表示返回值,作为Response 的 payload

代码实现如下:

public class BaseReturns implements Serializable {
	// 表⽰⼀次请求/响应的唯⼀ id. ⽤来把响应和请求对上.
	protected String rid;
	protected String channelId;
	protected boolean ok;
	// 省略 getter setter
}

🌲定义其他参数类

针对每个 VirtualHost 提供的⽅法, 都需要有⼀个类表示对应的参数

比如创建交换机代码如下:

public class ExchangeDeclareArguments extends BaseArguments implements Serializa
	private String exchangeName;
	private ExchangeType exchangeType;
	private boolean durable;
	private boolean autoDelete;
	private Map<String, Object> arguments;
}

⼀个创建交换机的请求,形如:

  • 可以把 ExchangeDeclareArguments 转成 byte[],就得到了下列图片的结构.
  • 按照 length 长度读取出 payload, 就可以把读到的⼆进制数据转换成ExchangeDeclareArguments 对象.

在这里插入图片描述
后续相关方法也是如此,这里就进行书写了

不一样的一个方法就是 订阅消息的方法,在这里面我们有一个参数为我们的回调函数。

这个回调函数, 是不能通过网络传输的。站在 broker server 这边, 针对消息的处理回调, 其实是统一的。(把消息返回给客户端)

客户端这边收到消息之后, 再在客户端自己这边执行一个用户自定义的回调就行了。此时, 客户端也就不需要把自身的回调告诉给服务器了.

因此这个类就不需要 consumer 成员了

🌳定义其他返回类

这个返回类是因为,我们需要执行回调函数将消息发送给客户端(订阅方)、

代码执行如下:

public class SubScribeReturns extends BasicReturns implements Serializable {
    private String consumerTag;
    private BasicProperties basicProperties;
    private byte[] body
    //省略get与set
}

⭕总结

关于《【消息队列开发】 设计网络通信协议》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下

  • 35
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

遇事问春风乄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值