[架构] ZeroMQ 深度探索(一)

最初认识 ZeroMQ 是被它的名号所吸引,最近在一个高性能中间件的项目中用到了 ZeroMQ,对这个号称“史上最快的消息队列”有了更深层次的了解。如果我们仅仅把 ZeroMQ 看作是一个消息队列,那就完全搞错了,ZeroMQ 是一套智能传输层协议,它不仅为开发者提供了强大的开发包,还包含了一套很棒的通信协议的实现,更值得一提是,它对分布式系统开发有着相当独到的见解,绝对值得我们好好学习。ZeroMQ 的最终目标是加入 Linux 内核,目前 ZeroMQ 已经出现在 YUM 中,相信 ZeroMQ 的未来会越来越美好!

ZeroMQ 特点介绍

1、支持高并发的异步 Socket 框架
2、协议比 TCP 更快、适用于大型集群和分布式计算
3、提供多种消息传递机制,如 inproc/IPC/TCP/multicast 等
4、内置丰富的组合模式,可用于简化大型分步式计算架构
5、提供异步 I/O 模式,适用于可扩展的多核应用开发
6、拥有活跃的开发者社区提供技术支持,发展相当迅速
7、支持超过 30 种的编程语言,如 C/C++/Java/.NET/Python/PHP 等
8、良好的跨平台性,支持多种 OS,如 Linux/Windows/OS X 等
9、拥有 iMatix 公司的商业级别支持,却是完全免费的

ZeroMQ 设计哲学

综合来说,ZeroMQ 的设计哲学在于“权衡”两字,其实 ZeroMQ 的名字就体现了这一点。“Zero”表示从零开始,也就是从无到有;ZeroMQ 不提供现成的安装套件(比如broker),这也意味着使用者必须自己来构建需要的套件,这种做法各有利弊;“利”在于使用者可以自由的构造属于自己的分布式系统,而“弊”则在于门槛比较高,对于不熟悉编程的使用者来说就麻烦大了。不过,相比与通过功能迭代来实现复杂需求的方案来说,ZeroMQ 更倾向于从根本上解决问题,这也正体现了 ZeroMQ 创始人 Pieter Hintjens 的设计哲学。

ZeroMQ 面向用户

ZeroMQ 是为那些对大型分布式系统感兴趣的开发者们而生的!假如你熟悉 C 语言,那么使用 ZeroMQ 将是件非常享受的事情,因为 ZeroMQ 开发包中已经包含了非常丰富的 C 语言的使用范例,有经验的开发者可以快速入手。使用 ZeroMQ 可以为我们节省下大量的编码时间,当然在此之前,我们需要把 ZeroMQ 的基础知识和用法理解透彻,否则误用或者错用的话,后果将是“很严重”的!接下来,我们开始学习 ZeroMQ 的基础知识。

ZeroMQ 学前必读

ZeroMQ 究竟是什么?也许我们应该先“大肆吹嘘”一番,但这显然是毫无意义的,也不是我们技术人员的本色。简单来说,ZeroMQ 是一个更小、更快、更简单的智能传输层协议,它可以帮助我们简化原本非常复杂的事情,实际上,这也就是当初设计 ZeroMQ 时的初衷。

今天,我们的世界变得越来越复杂,我们使用的软件也在随着人类社会的变化而演变。可以预见到的是,未来的软件系统将会变得越来越庞大,就像人类的大脑一样,错综复杂;这个时候,我们必须得把问题分解开来,逐个击破,否则,软件最终只能变成可怕的巨兽,把一切都搞砸。分而治之,讲的就是这个道理,这也就是我们需要分布式系统的原因。

在分布式系统中,代码之间需要通信,此时我们就必须使用网络、协议、线程这些工具来实现;然而,现实情况是,即使我们已经拥有了这些工具,但实现起来仍然非常费功夫。目前业界可用的网络协议比较有限,比如 TCP/UDP/HTTP/Websocket 等;这些协议要么太复杂,要么太笨重,也许我们会抱怨道,难道没有其他的选择了吗?ZeroMQ 是否会是我们期待的答案?下面,让我们回到两个最基本的问题上,一是如何实现代码之间需要通信,二是如何让通信变得更简单高效。

ZeroMQ HelloWorld

接下来,我们先从一个最简单的例子,即 HelloWorld 项目讲起。这就是网络请求中最基本的“请求-响应”模式(Request-Reply),客户端往服务端发送“Hello”,服务端回应“World”,如图1-1。

以下是 HelloWorld 项目的服务端代码(hwserver.c),熟悉 Socket 编程的同学应该很容易理解其中的语法,即使用 TCP 协议,监听 5555 端口,然后不停地接受、打印并返回信息,每次处理后停止 1 秒。

[cpp] view plaincopy

  1. // Hello World server
  2. #include <zmq.h>
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6. #include <assert.h>
  7. int main (void)
  8. {
  9. // Socket to talk to clients
  10. void *context = zmq_ctx_new ();
  11. void *responder = zmq_socket (context, ZMQ_REP);
  12. int rc = zmq_bind (responder, "tcp://*:5555");
  13. assert (rc == 0);
  14. while (1) {
  15. char buffer [10];
  16. zmq_recv (responder, buffer, 10, 0);
  17. printf ("Received Hello\n");
  18. zmq_send (responder, "World", 5, 0);
  19. sleep (1); // Do some ‘work‘
  20. }
  21. return 0;
  22. }

以下是 HelloWorld 项目的客户端代码(hwclient.c),逻辑也很简单,向服务端连续发送 10 条消息,接受并打印返回信息。

[cpp] view plaincopy

  1. // Hello World client
  2. #include <zmq.h>
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include <unistd.h>
  6. int main (void)
  7. {
  8. printf ("Connecting to hello world server…\n");
  9. void *context = zmq_ctx_new ();
  10. void *requester = zmq_socket (context, ZMQ_REQ);
  11. zmq_connect (requester, "tcp://localhost:5555");
  12. int request_nbr;
  13. for (request_nbr = 0; request_nbr != 10; request_nbr++) {
  14. char buffer [10];
  15. printf ("Sending Hello %d…\n", request_nbr);
  16. zmq_send (requester, "Hello", 5, 0);
  17. zmq_recv (requester, buffer, 10, 0);
  18. printf ("Received World %d\n", request_nbr);
  19. }
  20. zmq_close (requester);
  21. zmq_ctx_destroy (context);
  22. return 0;
  23. }

服务端代码的运行结果如图1-2。

客户端代码的运行结果如图1-3。

运行结果很容易理解,这就是一个标准的“请求-响应”模式的例子。从中我们可以看到使用 ZeroMQ 的类库实现起来还是很简单的,和基础 Socket 库的用法差不多,实现的功能也差不了多少,但是事实是否如此呢?在下一篇《ZeroMQ 深度探索(二)》中我们将深入讨论这个问题,未完待续...

TIP:建议大家使用 3.2 以上的版本进行开发。以后所有的的例子都是基于 C 语言的。所有的示例代码可以通过“git clone --depth=1 git://github.com/imatix/zguide.git”获取。

时间: 2024-10-12 08:12:23

[架构] ZeroMQ 深度探索(一)的相关文章

Android深度探索总结

Android深度探索前四章总结 通过这几章的学习真实体会到“移植”的概念:为特定设备定制Android的过程,但是移植的过程中开发最多的就是支持各种硬件设备的Linux驱动程序,本章对Android和Linux做了总体介绍.接着介绍了Android的四层架构:Linux内核:C/C++代码库:Android SDK API;应用程序.又引入Android移植,Android移植包括两部分:应用移植,系统移植.而且为硬件平台添加新的模块,必须为此模块添加一个新的驱动程序,或者修改原来的程序. 学

《Android深度探索卷一》第一章Android系统移植与驱动开发概述。

<Android深度探索>第一章讲的是Android系统移植与驱动开发概述.这一章节将对Android以及Linux驱动做一个总体的介绍. Android是一个非常优秀的的嵌入式操作系统.经过几年的发展和演进,Android已经形成了非常完善的系统架构.Android的系统架构分为四层,如下图 Android移植可分为两部分:应用移植和系统移植. Android系统移植是指让Android操作系统在某一个特定硬件平台上运行.使一个操作系统在特定硬件平台上运行的一个首要条件就是该操作系统支持硬件

android深度探索第一章

Android深度探索HAL与驱动开发的第一章学习了android系统移植与系统开发详述. 正如书上的导言所说,,android已经成为当前智能手机操作系统的老大.所以其重要性可想而知,其学习的意义非比寻常.其发展的迅速,很大程度上取决于任何人都可以利用android的源代码定制完全属于自己的嵌入式系统,而不需要向Google交钱.而由于android原生的代码支持的设备不多,因此,要想在自己的设备(包括手机.智能电视.平板等)上完美运行android,就需要另外一些开发程序,使得android

Android深度探索(卷1)HAL与驱动开发 第一章&#160;Android系统移植与驱动开发概述 读书笔记

Android深度探索(卷1)HAL与驱动开发 第一章 Android系统移植与驱动开发概述 读书笔记 本章是 Android系统移植与驱动开发概述性的具体讲解.首先,Android被分为了四层架构.在最底层的是Linux内核 .然后分别是C/C++代码库.Android SDK A和应用程序.而Android的移植又分为系统移植和应用移植.系统移植要实现Android操作系统在其他硬件平台上运行起来,其中的关键是Linux的内核.内核必须要完成对平台上运行的各个硬件的识别.所以这就需要Linu

Android深度探索(卷1)HAL与驱动开发 第二章 搭建Android开发环境 读书笔记

Android深度探索(卷1)HAL与驱动开发 第二章 搭建Android开发环境 读书笔记   本章主要讲解在Ubuntu Linux 下搭建Android开发环境. 1.JDK:从官网下载压缩包,并将其解压缩. Gedit etc/profile 并设置PATH环境变量,记得PATH. 2.搭建Android应用程序开发环境. 安装Android SDK 安装Eclipse 安装ADT 配置ADT 建立AVD 这个步骤是安装Android SDK,步骤与操作与在Windows操作系统下的安装

Android深度探索第一章总结

Android深度探索第一章主要是Android系统移植与驱动开发概述.要想进行系统移植就必须先了解Android的系统架构,Android的系统架构主要是:第一层,Linux内核,主要包括驱动程序以及管理内存.进程.电源等资源的程序:第二层,C/C++代码库,主要包括Linux的.so文件以及嵌入到APK程序中的NDK代码:第三层,Android SDK API,直接面向应用程序的Java APK:第四层,应用程序,直接面向最终用户的Java应用程序(APK程序).接下来是Android移植的

Android深度探索(卷1)HAL与驱动开发 第四章 源代码的下载和编译 读书笔记

Android深度探索(卷1)HAL与驱动开发 第四章 源代码的下载和编译 读书笔记     本章学习了使用git下载两套源代码并搭建两个开发环境.分别为Android源代码和Linux内核源代码.Android源代码中包含了HAL(即硬件抽象层) 的代码,并学习了如何搭建这两种开发环境. Android 的移植的本质就是Linux内核的移植,Linux内核的移植主要是Linux驱动的移植.而开发和测试Linux驱动就需要安装以上两个开发环境. 搭建两套环境的具体步骤如下: 一.下载编译和测试A

《Android深度探索》第一章心得体会

<Android深度探索>第一章讲的是Android系统移植与驱动开发概述.Android的系统架构分为四层:Linux内核.C/C++代码库.Android SDK API.应用程序.Android移植的主要工作:移植Linux驱动和移植HAL.学习Linux驱动要准备一个自己熟悉的Linux操作系统,用于开发和测试Linux驱动:准备一块开发板:学习GNU C:学习相关的硬件知识:不断地实践.Linux将存储器和外设分为3大类:字符设备.块设备.网络设备. 通过对第一章的学习,我了解到由于

Android深度探索(卷一)HAL与驱动开发 第九章

通过学习Android深度探索(卷一)HAL与驱动开发的第九章让我知道了HAL硬件抽象层,为什么要在Android中加入HAL和Android HAL架构. HAL是建立在Linux驱动之上的一套程序库.这套程序库并不属于Linux内核,而是属于Linux内核层之上的应用层,其主要目的除了尽量避免应用程序直接访问Linux驱动外,还有一个重要原因,那就是保护“私人财产”. 在传统的Linux系统中Linux驱动一般有两种类型的代码:访问硬件寄存器代码和业务逻辑代码.所以加入HAL的主要原因就是: