在做服务器集群时,集群中的服务器需要通信,比如Client1(简称C1)连接到Server1(简称S1),Client2连接到Server2,Client1需要向Client2发消息,S1并不知道C2已连接到S2。
想到了两种方案:
A方案:采用组播(或广播),S1在接收到C1消息后,发送广播包查询C2位于哪个Server上,这时S2向S1回复,S1再将消息发送到S2,S2转发给C2,但是udp是不可靠的,虽然Server都位于同一局域网内,如果消息丢了,那C2就接收不到C1的消息了。
B方案:增加一个路由服务器,所有Server都连接到路由服务器(tcp长连接),S1将消息转发给路由服务器,路由服务器再广播给所有Server,由各个Server自行判断,但这样程序复杂度就上升了,每个Server都会处理本来不属于自己处理的消息,而且路由服务器会成为瓶颈,消息数量大规模增加的话。
这不就是个消息队列嘛,简单的可以用zeromq做,稍微复杂一点可以用rabbitmq/activemq/qpid等等各种成熟方案。
rabbitmq
MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过 队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。其中较为成熟的MQ产品有IBM WEBSPHERE MQ等等。
ActiveMQ
1、ActiveMQ是消息队列技术,为解决高并发问题而生!
2、ActiveMQ生产者消费者模型(生产者和消费者可以跨平台、跨系统)
有中间平台3、ActiveMQ支持两种消息传输方式
1)Queue,队列模式,生产者生产了一个消息,只能由一个消费者进行消费
2)Topic,发布/订阅模式,生产者生产了一个消息,可以由多个消费者进行消费
Qpid
AMQP是一种用于业务消息的开放网络协议。他定义了一种允许双方进行可靠业务消息传递的二进制线级协议。该协议的目标是成为所有消息中间件之间进行互操作的标准协议。
消息队列是一种进程间通信线程或同一进程的不同线程间的通信方式。
Qpid则是由Apache开发的一种消息队列,实现了AMQP协议,并且支持多种语言与多种平台。
zeromq
这是个类似于Socket的一系列接口,他跟Socket的区别是:普通的socket是端到端的(1:1的关系),而ZMQ却是可以N:M 的关系,人们对BSD套接字的了解较多的是点对点的连接,点对点连接需要显式地建立连接、销毁连接、选择协议(TCP/UDP)和处理错误等,而ZMQ屏蔽了这些细节,让你的网络编程更为简单。ZMQ用于node与node间的通信,node可以是主机或者是进程。
引用官方的说法: “ZMQ(以下ZeroMQ简称ZMQ)是一个简单好用的传输层,像框架一样的一个socket library,他使得Socket编程更加简单、简洁和性能更高。是一个消息处理队列库,可在多个线程、内核和主机盒之间弹性伸缩。ZMQ的明确目标是“成为标准网络协议栈的一部分,之后进入Linux内核”。现在还未看到它们的成功。但是,它无疑是极具前景的、并且是人们更加需要的“传统”BSD套接字之上的一 层封装。ZMQ让编写高性能网络应用程序极为简单和有趣。”
这不就是个消息队列嘛,简单的可以用zeromq做,稍微复杂一点可以用rabbitmq/activemq/qpid等等各种成熟方案
我看了下zeromq资料,它是用的tcp,通过一个路由服务器来转发(发布-订阅,请求-应答等等)。我的问题这种转发服务器会是一个瓶颈额,比如设计目标并发量10万,即每秒10万条消息,要求所有消息1秒内处理完,他能即时处理?
消息队列很成熟了,你要想性能好,就加机器来解决。
看消息大小,0mq官网有测试数据,8字节的消息每秒可以吞吐280万条(10G网络)或者400万条(infiniband),100字节的消息每秒都在100万条以上,每秒10万并不是一个特别巨大的量。想要性能可以堆机器,分布式消息队列很成熟了。
吞吐能力是接收和发送的总和?还是单单是接收?其实我想知道它的分发能力,比如说有10个服务器向它订阅了消息,那1秒它能同时分发给这10台服务器的消息量有多大?
官网有很具体的报告可以参考,建议自己搭环境实际测试,在普通PC和千兆网卡的环境里,是不可能有官方测出来的那个成绩的
我的程序中用的就是“广播”,主动或被动发送状态。
请问你是如何解决udp广播中丢消息的问题呢?建立应答与重发机制
在分布式调度系统中,如果要实现调度服务器与多台计算节点服务器之间通信,采用socket来实现是一种实现方式,当然我们也可以通过数据存储任务,子节点来完成任务,但是往往使用数据作为任务存储都需要定制开发,要维护数据库中任务记录状态等等。开发的东西还是有点多,而且还不够灵活。因此,我个人是比较偏向于使用socket来实现任务的调度工作。原因:使用socket实现调度比较灵活,而且扩展性都比较好。
实现思路:调度服务器要实现调度工作,它必须与所有计算节点之间建立连接。而且他需要知道每台计算节点的任务状况,因此服务器节点必须存储与所有计算节点的socket连接对象。
在客户端唯一需要知道的就是它归属的调度服务器的通信IP和端口,因此client是发送连接的主动方,由调度服务器监听是否有client请求建立连接,当建立连接成功后,把该连接信息存储到一个节点中以便监控client的存活状态及通信使用。