今天看书的时候,书中写到了到了RocketMQ的消息发送的流程解析,特此做个笔记
先说说RocketMQ 的消息发送方式
书上写着RocketMQ 一共有三种消息发送方式 :同步(sync )异步(async)、单向( oneway)。
同步 :发送者向 MQ 执行 送消息 API 时,同步等待,直到消息服务器返回发送结果。
异步 :发送者向 MQ 执行发送消息 API 时,指定消息发送成功后的回调函数,然后调用消息发送 API 后,立即返回,消息发送者线程不阻塞 ,直到运行结束,消息发送成功或失败的回调任务在 个新的线程中执行。如果消息发送失败会进行重试,可以通过调整参数来控制消息重试次数。
单向::消息发送者向 MQ 执行发送消息 时,直接返回,不等待消息服务器的结果,
也不注册回调函数,简单地说,就是只管发,不在乎消息是否成功存储在消息服务器上。
举个例子吧
比如A约B吃饭
同步发送就是,A一定要等到B一个答复,B说了去或者不去,A才继续做其他事情。
异步发送就是,A给B发消息了,A不会等着B给结果会先去做别的事,B看到了消息会给A一个答复。
单向发送就是,A给B发消息了,不管B去不去,A接着做自己的事,B去不去和A没关系。
消息发送的基本流程
消息发送流程主要的步骤有:验证消息、查找路由、 消息发送
1.消息长度验证
消息在发送之前,首先要确保生产者处于运行状态,然后验证消息是否符合相应的规范,具体的规范要求是主题名称、消息体不能为、 消息长度不能等于0且不能超过允许发送消息的最大长度 4M (maxMessageSize=1024 * 1024 *4)
2.查找主题路由信息
消息发送之前,首先需要获取Topic的路由信息,只有获取了这些信息我们才知道消息要发送的Broker节点的信息。
负责查找主题的路由信息的是一个名为tryToFindTopicPublishlnfo的方法,如果生产者中缓存了 Topic的路由信息,如果该路由信息中包含了消息队列,则直接返回该路由信息,如果没有缓存或没有包含消息队列, 则向 NameServer 查询该Topic的路由信息。如果最终未找到路由信息,则抛出无法找到主题相关路由信息的异常(其实默认情况下,topic不用手动创建,当producer进行消息发送时,会从NameServer 拉取topic的路由信息,如果topic的路由信息不存在,那么会默认拉取broker启动时默认创建好Topic,自动创建的开关配置在BrokerConfig中,通过autoCreateTopicEnable字段进行控制,但是生产中不建议开启)。
Tip:不建议的原因是使用自动创建的主题的话,那么后面有可能该主题的消息都发到一个Broker中,破坏了原有的负载均衡,并且Borker是每隔30秒向集群中所有的NameServer 发送心跳链接的,然后NameServer 收到心跳包后会更新缓存中的记录,然后每十秒进行一次扫描,如果120s没有收到心跳就会移除Broker,根据上述机制中可以得出最坏情况下NameServer 要30秒才能感知到这个新的Topic ,如果这个新主题消息很多,那存有该Topic的 Broker 负载就会非常的高。而且并且也会降低可用性,假如消息数量非常大,这台broker一旦挂掉,容易出现单点故障,所以不建议线上开启允许自动创建主题。
3.消息发送
除了上面写的三种发送方式以外,还有批量发送,批量发送是将同一主题的多条消息一起打包发送到消息服务端,减少网络调用次数,提高网络传输效率。不过,并不是在同一批次中发送的消息数量越多性能就越好,其判断依据是单条消息的长度,如果单条消息内容比较长, 则打包多条消息发送会影线程发送消息的响应时间 ,并且单次消息发送总长度不能超过4M。