流行的通讯库/消息中间件

2.流行的通讯库/消息中间件

网络上各种各样的通讯中间件/MQ多不胜数。具作者所知,比较有名的有ACE、ICE、Boost::ASIO、MSMQ、ActiveMQ、RabbitMQ、ZeroMQ等等。

其中ACE、ICE是经典,网上资料很丰富,不过入门门槛较高,说白了就是有点难学难精。属于高端大气上档次的货。

Boost::ASIO作为大名鼎鼎的Boost模块之一,感觉很不错,只需引用.hpp文件,不需要动态库,性能据说也不错,跨平台,值得推荐和学习。不过没有最简单只有更简单,当有更好的选择时,Boost::ASIO的语法就略显复杂了。(不过还是强力推荐)。

MSMQ 微软的东西,用起来还可以,不过一般不推荐,毕竟linux下没人会用它。

JSM、ActiveMQ、RabbitMQ、ZeroMQ基本上是一类东西。activemq,基于jms稳定可靠安全。rabbitmq,基于erlang,充分利用并发和分布式特性。zeromq,号称世上最快消息内核。

l ActiveMQ  pActiveMQ是Apache开发的开源消息中间件,纯Java实现,基于JMS1.1及J2EE 1.4规范。 l RabbitMQ  pRabbitMQ 是由 LShift 提供的一个 Advanced Message Queuing Protocol (AMQP) 的开源实现,由以高性能、健壮以及可伸缩性出名的 Erlang 写成,因此也是继承了这些优点。 l ZeroMQ  p是由iMatix公司使用C语言开发的高性能消息中间件,是对socket的封装,在发送端缓存消息。

ActiveMQ RabbitMQ ZeroMQ
遵循规范JMS1.1及J2EE1.4AMPQ---
架构模型消息代理架构Broker消息代理架构BrokerC/S架构
实现语言JavaErlang C/C++
支持消息协议StompAMPQ、Stomp等---
主要推动力量Apache、RedhatLshift、Vmware、SpringSourceiMatix 
支持编程语言C,Java,PythonC,Java,PythonC,Java,Python
编程复杂度复杂简单中等
持久化支持支持,不支持第三方数据库发送端缓存
性能NormalNormalHigh
内存使用率HighHighNormal
引用自邱志刚的Message oriented middleware analysis,抱歉未找到链接。

下面是一个网上对消息系统的总结,也可以参考以下。

常见开源消息系统


3.最快的消息中间件zeroMQ

ZeroMQ简介

参考1: ?MQ(ZeroMQ)简介

参考2:ZeroMQ研究与应用分析[推荐]

参考3:高性能的通讯库-zeroMQ的几个高性能特征 

参考4:ZeroMQ详细教程,从入门到深入,34篇

4.ZeroMQ的C版本nanomsg,更快

为啥又整出个ZeroMQ的C版本呢?

具本人所知,ZeroMQ作者在实现ZeroMQ后,有一天幡然醒悟“如果用C来实现ZeroMQ会不会更快呢?”所以他就用C语言重新实现了ZeroMQ,即nanomsg,目前是alpha2版本。官方网站:http://nanomsg.org/index.html

关于为什么要用C实现zeromq,其实上面是作者的杜撰。具体原因可以参照以下分析:)

为什么我希望用C而不是C++来实现ZeroMQ

为什么我希望用C而不是C++来实现ZeroMQ(第二篇)


从网上的资料来看,nanomsg确实比zeromq更快。

5.ZeorMQ优点,我为什么使用MQ?

1)使用简单,不需要部署服务器什么的,直接编译后作为一个动态库使用;

2) 编程开发简单

以下是zeromq的一个“helloword”示例:

Server

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//
// Hello World server in C++
// Binds REP socket to tcp://*:5555
// Expects "Hello" from client, replies with "World"
//
#include <zmq.hpp>
#include <string>
#include <iostream>
#ifndef _WIN32
#include <unistd.h>
# else
#include <windows.h>
#endif
 
int main () {
     // Prepare our context and socket
     zmq::context_t context ( 1 );
     zmq::socket_t socket (context, ZMQ_REP);
     socket.bind ( "tcp://*:5555" );
 
     while ( true ) {
         zmq::message_t request;
 
         // Wait for next request from client
         socket.recv (&request);
         std::cout << "Received Hello" << std::endl;
 
         // Do some 'work'
#ifndef _WIN32
             sleep( 1 );
# else
         Sleep ( 1 );
#endif
 
         // Send reply back to client
         zmq::message_t reply ( 5 );
         memcpy (( void *) reply.data (), "World" , 5 );
         socket.send (reply);
     }
     return 0 ;
}</unistd.h></iostream></string></zmq.hpp>

Client

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//
// Hello World client in C++
// Connects REQ socket to tcp://localhost:5555
// Sends "Hello" to server, expects "World" back
//
#include <zmq.hpp>
#include <string>
#include <iostream>
int main ()
{
     // Prepare our context and socket
     zmq::context_t context ( 1 );
     zmq::socket_t socket (context, ZMQ_REQ);
     std::cout << "Connecting to hello world server..." << std::endl;
     socket.connect ( "tcp://localhost:5555" );
     // Do 10 requests, waiting each time for a response
     for ( int request_nbr = 0 ; request_nbr != 10 ; request_nbr++) {
         zmq::message_t request ( 6 );
         memcpy (( void *) request.data (), "Hello" , 5 );
         std::cout << "Sending Hello " << request_nbr << "..." << std::endl;
         socket.send (request);
         // Get the reply.
         zmq::message_t reply;
         socket.recv (&reply);
         std::cout << "Received World " << request_nbr << std::endl;
     }
     return 0 ;
}</iostream></string></zmq.hpp>

很简单吧。对比其他MQ要么需要部署Server(ActiveMQ,RabbitMQ),要么复杂Boost::ASIO。

作为反面教材,Boost::ASIO中简单的echo-server例子如下:

Server

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
//
// blocking_tcp_echo_server.cpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
 
#include <cstdlib>
#include <iostream>
#include <boost bind.hpp= "" >
#include <boost smart_ptr.hpp= "" >
#include <boost asio.hpp= "" >
#include <boost thread= "" thread.hpp= "" >
 
using boost::asio::ip::tcp;
 
const int max_length = 1024 ;
 
typedef boost::shared_ptr<tcp::socket> socket_ptr;
 
void session(socket_ptr sock)
{
   try
   {
     for (;;)
     {
       char data[max_length];
 
       boost::system::error_code error;
       size_t length = sock->read_some(boost::asio::buffer(data), error);
       if (error == boost::asio::error::eof)
         break ; // Connection closed cleanly by peer.
       else if (error)
         throw boost::system::system_error(error); // Some other error.
 
       boost::asio::write(*sock, boost::asio::buffer(data, length));
     }
   }
   catch (std::exception& e)
   {
     std::cerr << "Exception in thread: " << e.what() << "\n" ;
   }
}
 
void server(boost::asio::io_service& io_service, unsigned short port)
{
   tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port));
   for (;;)
   {
     socket_ptr sock( new tcp::socket(io_service));
     a.accept(*sock);
     boost::thread t(boost::bind(session, sock));
   }
}
 
int main( int argc, char * argv[])
{
   try
   {
     if (argc != 2 )
     {
       std::cerr << "Usage: blocking_tcp_echo_server <port>\n" ;
       return 1 ;
     }
 
     boost::asio::io_service io_service;
 
     using namespace std; // For atoi.
     server(io_service, atoi(argv[ 1 ]));
   }
   catch (std::exception& e)
   {
     std::cerr << "Exception: " << e.what() << "\n" ;
   }
 
   return 0 ;
}</port></tcp::socket></boost></boost></boost></boost></iostream></cstdlib>
Client

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
//
// blocking_tcp_echo_client.cpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
 
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <boost asio.hpp= "" >
 
using boost::asio::ip::tcp;
 
enum { max_length = 1024 };
 
int main( int argc, char * argv[])
{
   try
   {
     if (argc != 3 )
     {
       std::cerr << "Usage: blocking_tcp_echo_client <host> <port>\n" ;
       return 1 ;
     }
 
     boost::asio::io_service io_service;
 
     tcp::resolver resolver(io_service);
     tcp::resolver::query query(tcp::v4(), argv[ 1 ], argv[ 2 ]);
     tcp::resolver::iterator iterator = resolver.resolve(query);
 
     tcp::socket s(io_service);
     boost::asio::connect(s, iterator);
 
     using namespace std; // For strlen.
     std::cout << "Enter message: " ;
     char request[max_length];
     std::cin.getline(request, max_length);
     size_t request_length = strlen(request);
     boost::asio::write(s, boost::asio::buffer(request, request_length));
 
     char reply[max_length];
     size_t reply_length = boost::asio::read(s,
         boost::asio::buffer(reply, request_length));
     std::cout << "Reply is: " ;
     std::cout.write(reply, reply_length);
     std::cout << "\n" ;
   }
   catch (std::exception& e)
   {
     std::cerr << "Exception: " << e.what() << "\n" ;
   }
 
   return 0 ;
}</port></host></boost></iostream></cstring></cstdlib>
其实Boost算是简单的了,只是有对比才有进步嘛,ZeroMQ的代码仅有一半(不过这似乎说明不了什么问题)。

3)效率高(其实这个不是最重要的,最重要的是1、2)

为了让大伙儿有一个感性的认识,俺特地找来了消息队列软件的性能测评。这是某老外写的一篇帖子(在"这里"),不懂洋文的同学可以看"这里"。连帖子都懒得看的同学,可以直接看下图。


从图中可以明显看出,ZMQ 相比其它几款MQ,简直是鹤立鸡群啊!性能根本不在一个档次嘛。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值