作者回复: A1:这个参数是控制客户端在生产消费的时候会访问同一个主题的队列数量,假设一个主题有100个队列,对于每一个客户端来说,它没必要100个队列都访问,只需要使用其中的几个队列就行了。
A2:writeQueueNums和readQueueNums是在服务端来控制每个客户端在生产和消费的时候,分别访问多少个队列。这两个参数是服务端参数,优先级是高于客户端控制的参数defaultTopicQueueNums的。perm是设置Topic读写等权限的参数,具体如何设置你需要去看一下文档。
A3:如果局限于:“APP/浏览器 --[http协议]-->web 服务”这样的场景,受限于http协议,前端和web服务的交互一定是单向和同步的。一定要等待结果然后返回响应,但是,这种情况仍然可以使用异步的方法,这个我在“08答疑”中解释秒杀的时候其实已经给出了答案。很多同学不理解的原因是思维被web框架给限制住了。像spring web这种框架,它把处理web请求都给你封装好了,你只要写一个handler就行了,很方便。但是,这个handler只能是一个同步方法,它必须在返回值中给出响应结果,所以导致很多同学的思维转不过来这个弯儿。
你可以结合我们讲的异步网络IO内容想一下,http协议发一个请求到服务端,就是发了一些数据过来,服务端回响应也就是在这个连接上给它返回一些数据回去就可以了。至于什么时候往回发响应数据,哪个线程来发,有要求吗?并没有。只要在超时之前发响应就可以了。我们讲得如何来实现异步网络IO的方法处理的不就是这种情况吗?
这个过程不是说一定要做成和web框架一样的同步处理。
作者回复: 个人建议学习Java或者Go,这两种语言都有不错的生态系统,都可以用来构建大规模集群。
相对来说,Java的生态系统更强大,Go比较年轻,有很多Java不具备的语言特性。
Python本来只是一门脚本语言,特别适合开发机器学习程序而火起来了,如果你不是从事机器学习相关的研发,不太建议作为第一语言来学习。
作者回复: 异步发送仍然可以保证严格顺序,但需要注意几点:
1. 需要单线程异步发送;
2. 需要记录一个递增流水号,保证每个发出的消息都有一个流水号,如果某个流水号的消息发送出错,需要重发这个流水号之后的所有消息。比如,连续异步发送12345这5条消息,假如已经异步发送了12345,然后异步检查发送结果的时候发现3发送失败了,需要从3开始重发。也就是按顺序重发345。
3. 消费逻辑需要幂等,能接受2中的这种情况,也就是说,收到的消息有可能是:12(3丢了)45 345。
作者回复: 我理解主要的原因除了超时时间的计算不准确以外,更重要的原因是这个异步方法还有改进的空间,其实可以直接结合Netty做到不需要Executor。
作者回复: 这两个方法没有做到线程安全,但是这两个方法的实现内部,调用的方法都是线程安全的方法。
作者回复: 给认真思考完成作业的同学点赞👍!
作者回复: PullConsumer:业务代码在需要的时候调用consumer.pullxxxx方法从consumer拉消息;PushConsumer:当有消息的时候,consumer会自动调用messageListener(业务处理消息的代码)。
这两种方式主要是为了方便使用者进行线程控制,没有什么本质区别。
作者回复: 分别在哪两个地方执行的2次启动呢?
作者回复: 有一个问题你需要考虑,你是不是需要为每一个会话(比如,张三和李四之间开始聊天,成为一个会话)在MQ中凑创建一个Topic呢?这样会导致MQ集群中的Topic数量非常多。假设你的系统注册用户数是n,理论上最多会需要 n x n 个Topic,这还没有计算用户拉的群。
对于海量的Topic数量,RocketMQ和Kafka都不是太好的选择。
作者回复: 感谢!