原文地址

I’m a minimalist, and I don’t like to complicate software too early and unnecessarily. And adding components to a software system is one of the things that adds a significant amount of complexity. So let’s talk about message queues.

Message Queues are systems that let you have fault-tolerant, distributed, decoupled, etc, etc. architecture. That sounds good on paper.

Message queues may fit in several use-cases in your application. You can check this nice article about the benefits of MQs of what some use-cases might be. But don’t be hasty in picking an MQ because “decoupling is good”, for example. Let’s use an example – you want your email sending to be decoupled from your order processing. So you post a message to a message queue, then the email processing system picks it up and sends the emails. How would you do that in a monolithic, single classpath application? Just make your order processing service depend on an email service, and call sendEmail(..) rather than sendToMQ(emailMessage). If you use MQ, you define a message format to be recognized by the two systems; if you don’t use an MQ you define a method signature. What is the practical difference? Not much, if any.

But then you probably want to be able to add another consumer that does additional thing with a given message? And that might happen indeed, it’s just not for the regular project out there. And even if it is, it’s not worth it, compared to adding just another method call. Coupled – yes. But not inconveniently coupled.

What if you want to handle spikes? Message queues give you the ability to put requests in a persistent queue and process all of them. And that is a very useful feature, but again it’s limited based on several factors – are your requests processed in the UI background, or require immediate response? The servlet container thread pool can be used as sort-of queue – response will be served eventually, but the user will have to wait (if the thread acquisition timeout is too small, requests will be dropped, though). Or you can use an in-memory queue for the heavier requests (that are handled in the UI background). And note that by default your MQ might not be highly-availably. E.g. if an MQ node dies, you lose messages. So that’s not a benefit over an in-memory queue in your application node.

Which leads us to asynchronous processing – this is indeed a useful feature. You don’t want to do some heavy computation while the user is waiting. But you can use an in-memory queue, or simply start a new thread (a-la spring’s @Async annotation). Here comes another aspect – does it matter if a message is lost? If you application node, processing the request, dies, can you recover? You’ll be surprised how often it doesn’t actually matter, and you can function properly without guaranteeing all messages are processed. So, just asynchronously handling heavier invocations might work well.

Even if you can’t afford to lose messages, the use-case when a message is put into a queue in order for another component to process it, there’s still a simple solution – the database. You put a row with a processed=false flag in the database. A scheduled job runs, picks all unprocessed ones and processes them asynchronously. Then, when processing is finished, set the flag to true. I’ve used this approach a number of times, including large production systems, and it works pretty well.

And you can still scale your application nodes endlessly, as long as you don’t have any persistent state in them. Regardless of whether you are using an MQ or not. (Temporary in-memory processing queues are not persistent state).

Why I’m trying to give alternatives to common usages of message queues? Because if chosen for the wrong reason, an MQ can be a burden. They are not as easy to use as it sounds. First, there’s a learning curve. Generally, the more separate integrated components you have, the more problems may arise. Then there’s setup and configuration. E.g. when the MQ has to run in a cluster, in multiple data centers (for HA), that becomes complex. High availability itself is not trivial – it’s not normally turned on by default. And how does your application node connect to the MQ? Via a refreshing connection pool, using a short-lived DNS record, via a load balancer? Then your queues have tons of configurations – what’s their size, what’s their behaviour (should consumers explicitly acknowledge receipt, should they explicitly acknowledge failure to process messages, should multiple consumers get the same message or not, should messages have TTL, etc.). Then there’s the network and message transfer overhead – especially given that people often choose JSON or XML for transferring messages. If you overuse your MQ, then it adds latency to your system. And last, but not least – it’s harder to track the program flow when analyzing problems. You can’t just see the “call hierarchy” in your IDE, because once you send a message to the MQ, you need to go and find where it is handled. And that’s not always as trivial as it sounds. You see, it adds a lot of complexity and things to take care of.

Certainly MQs are very useful in some contexts. I’ve been using them in projects where they were really a good fit – e.g. we couldn’t afford to lose messages and we needed fast processing (so pinging the database wasn’t an option). I’ve also seen it being used in non-trivial scenarios, where we are using to for consuming messages on a single application node, regardless which node posts the message (pub/sub). And you can also check this stackoverflow question. And maybe you really need to have multiple languages communicate (but don’t want an ESB), or maybe your flow is getting so complex, that adding a new method call instead of a new message consumer is an overkill.

So all I’m trying to say here is the trite truism “you should use the right tool for the job”. Don’t pick a message queue if you haven’t identified a real use for it that can’t be easily handled in a different, easier to setup and maintain manner. And don’t start with an MQ “just in case” – add it whenever you realize the actual need for it. Because probably, in the regular project out there, a message queue is not needed.

You Probably Don’t Need a Message Queue的更多相关文章

  1. 初识Message Queue之--基础篇

    之前我在项目中要用到消息队列相关的技术时,一直让Redis兼职消息队列功能,一个偶然的机会接触到了MSMQ消息队列.秉着技术还是专业的好为原则,对MSMQ进行了学习,以下是我个人的学习笔记. 一.什么 ...

  2. MSMQ(Microsoft Message Queue)

    http://www.cnblogs.com/sk-net/archive/2011/11/25/2232341.html 利用 MSMQ(Microsoft Message Queue),应用程序开 ...

  3. Message Queue vs. Web Services?

    From stackoverflow.com When you use a web service you have a client and a server: If the server fail ...

  4. hdu 1509 Windows Message Queue

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1509 Windows Message Queue Description Message queue ...

  5. 为什么要用Message Queue

    摘录自博客:http://dataunion.org/9307.html?utm_source=tuicool&utm_medium=referral 为什么要用Message Queue 解 ...

  6. 单线程模型中Message、Handler、Message Queue、Looper之间的关系

    1. Android进程 在了解Android线程之前得先了解一下Android的进程.当一个程序第一次启动的时候,Android会启动一个LINUX进程和一个主线程.默认的情况下,所有该程序的组件都 ...

  7. Top 10 Uses of a Message Queue

    Top 10 Uses of a Message QueueAsynchronicity, Work Dispatch, Load Buffering, Database Offloading, an ...

  8. hdoj 1509 Windows Message Queue【优先队列】

    Windows Message Queue Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Ot ...

  9. 详解boost库中的Message Queue .

    Message Queue(后文简写成MQ或消息队列)是boost库中用来封装进程间通信的一种实现,同一台机器上的进程或线程可以通过消息队列来进行通迅.消息队列中的消息由优先级.消息长度.消息数据三部 ...

  10. Windows Message Queue(优先队列)

    欢迎参加——BestCoder周年纪念赛(高质量题目+多重奖励) Windows Message Queue Time Limit: 2000/1000 MS (Java/Others)    Mem ...

随机推荐

  1. 系统中 CPU 时间片是多久

    Windows 系统中线程轮转时间也就是时间片大约是20ms,如果某个线程所需要的时间小于20ms,那么不到20ms就会切换到其他线程:如果一个线程所需的时间超过20ms,系统也最多只给20ms,除非 ...

  2. win10 MongoDB安装

    1.下载地址https://www.mongodb.com/download-center#community 2.安装步骤 点击next同意安装,下面这一步选择Custom 自定义目录 注意:在这一 ...

  3. 一些html5

    ---匿名函数(funcation(){}())---- 一.拖拽 draggable=ture-----A拖动元素上事件 1. 拖拽开始:ondragstart2. 拖拽中:ondrag3. 拖拽结 ...

  4. leetcode小题解析

    描述Given an array of integers, return indices of the two numbers such that they add up to a specific ...

  5. mybatis中根据日期模糊查询

    首先设置起始日期startDate和结束日期endDate,数据库中日期字段为achive_time,表名为dos_dossier<select id="getDossiers&quo ...

  6. PL/SQL基本语法

    *2.PL/SQL基本语法   1)匿名块   一段不能在数据库存储的PL/SQL. 基本结构如下:   DECLARE     //变量的声明定义区域(可省略)   BEGIN     //业务处理 ...

  7. ubuntu 14.04服务器上使用nginx搭建wordpress博客详解

    过程详解 1.更新apt-get sudo apt-get update 2.安装nginx sudo apt-get install nginx 3.启动nginx sudo service ngi ...

  8. MVC传递数据-传递对象或对象集合

    前言 本文主要介绍从View(或者js)文件向Controller提交对象或者对象集合.比方.将表格中的一行数据作为一个对象提交.或将多行数据作为一个集合提交到Controller. 回想 从View ...

  9. Android高级控件(一)——ListView绑定CheckBox实现全选,添加和删除等功能

    Android高级控件(一)--ListView绑定CheckBox实现全选,添加和删除等功能 这个控件还是挺复杂的.也是项目中应该算是比較经常使用的了,所以写了一个小Demo来讲讲,主要是自己定义a ...

  10. C++11新特性应用--实现延时求值(std::function和std::bind)

    说是延时求值,注意还是想搞一搞std::function和std::bind. 之前博客<C++11新特性之std::function>注意是std::function怎样实现回调函数. ...