客户端多线程使用同一条 connection 并行写数据,一定需要加锁吗?

ponponon
  • 1.6k

我看到 rabbitmq 有一个 Channel 的东西,具体参考了:Connection和Channel

想往 rabbitmq server 中 publish 一些 message 的时候(假设要写 10000 条吧),我应该采用哪种方案:

  • 方案一:开多线程,假设 10 个线程(每个线程写 1000 个 message 吧),每个线程使用自己独立的 connection,每一个 connection 有自己的 Channel。(就是开10个线程、建立10个连接、建立10个Channel)
  • 方案二:开多线程,假设 10 个线程(每个线程写 1000 个 message 吧),每个线程共享同一个 connection,在每个 connection 下面开 1 个 Channel

我应该使用哪种方案?

方案一还是方案二?


如果采用方案二的话,并且不加锁的话,我有一个问题,到目前为止,人类有什么技术可以区分堆在 tcp 缓存区中的数据是来自哪个 message ?

因为对于 rabbitmq server 的 tcp 可读缓冲区中的 n kb 数据的:
0-13 可能来自 message001 ;
13-15 可能来自 message002;
15-199 可能来自 message001;
199-249 可能来自 message003;

这谁还分的清?人类有什么技术可以分清吗?


如果要加锁的话,我就有另一个问题了,我在使用一个叫做 nameko 的 amqp 框架,这个框架使用的是 python 的第三方协程 eventlet 去做的(打了猴子补丁)

我是用 nameko 来做任务投递(把 message 发到 rabbitmq server 中去)

nameko 的特点就是,一个进程一个 rabbitmq 连接,然后协程并发,共用这一条连接。

nameko 工作的很好。

协程的特点是碰到网络 IO 就让出 CPU 给其他协程

协程没有锁(就我简陋的知识水平来说)

那么,问题来了,一碰到 publish 就让出 CPU,还没有锁,那么就会出现上面的问题!

rabbitmq server 的 tcp 可读缓冲区中的 n kb 数据的:
0-13 可能来自 message001 ;
13-15 可能来自 message002;
15-199 可能来自 message001;
199-249 可能来自 message003;

但是 nameko 工作的很好呀?

所以这个问题是怎么解决的?(不一定要局限于 nameko,可以是地球上任意东西)

给协程加锁?但那还有什么意义,慢死了!

还是说有什么神秘技术可以解决上面的问题


参考了:
socket套接字在多线程发送数据时要加锁吗?
对于socket发送数据时是否要加锁及write read的阻塞非阻塞

但是问题还是没有解决

不仅 rabbitmq 有 Channel,thrift 貌似也有 Channel?

HTTP2 好像也有类似的概念

回复
阅读 729
1 个回答
依云
  • 24.9k

rabbitmq 给你封装了一层驱动。你每次发送数据,这层驱动都把整个消息完整地保存下来,放到队列里等待发送。可以发送数据的话,再依次往 TCP 缓冲区里发数据。(相当于驱动帮你加了锁;虽然协程的话没加锁的必要,因为存消息那里没有协程切换点。)

协程的特点是用户态调度,程序里可以看到切换点(比如 await 语句;可能发生调度的地方)。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏