原文地址

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. D. Destruction of a Tree_dfs序_性质分析_思维题

    题意: 给定一棵树,每次可以拆掉一个树上度数为偶数的点,拆掉该点后,与该点所连的所有边都会被删掉.问,是否有一种删点顺序可以删掉所有的点.如果有,则输出任意一组解. 数据范围:线性做法 O(n)O(n ...

  2. 2019-03-15 使用Request POST获取CNABS网站上JSON格式的表格数据,并解析出来用xlwt写到Excel中

    import requests import xlwt url = 'https://v1.cn-abs.com/ajax/ChartMarketHandler.ashx' headers={ 'Us ...

  3. StringUtils 的填充方法

    注意:两个参数的用空格填充,三个参数的用后面的参数填充 第一个参数要填充的字符串,第二个是需要的长度,第三个是以什么填充. 左侧填充: leftPad(): StringUtils.leftPad(S ...

  4. 在join中,on和where的区别

    两个表在,join时,首先做一个笛卡尔积,on后面的条件是对这个笛卡尔积做一个过滤形成一张临时表,如果没有where就直接返回结果,如果有where就对上一步的临时表再进行过滤. 在使用left  j ...

  5. elasticsearch的安装和使用

    准备环境: 环境: win7 64位  jdk1.8.0  elasticsearch2.3.3 elasticsearch2.3.3:https://www.elastic.co/thank-you ...

  6. 【【henuacm2016级暑期训练】动态规划专题 I】Gargari and Permutations

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 注意这k个序列每个都是排列. 如果在每个序列中都满足y出现在x之后的话. 那么我们从x连一条有向边至y (有一个序列不满足就不连 ( ...

  7. Spring IoC简介及使用

    Spring根本任务 Spring的根本任务就是简化Java开发. 目前许多框架如果要使用他们,就必须要继承或实现这些框架的各种类.这使得框架与我们的程序耦合度过高.由于在我们的程序中加入了过多的框架 ...

  8. C#-WebService基础02

    WebService WSDL是web service的交换格式 跨平台数据交互 什么是web服务 SOA 面向服务的体系结构  service-Oriented Architecture Servi ...

  9. Sublime Text 3 添加到右键菜单

    Sublime Text 3 添加到右键菜单 学习了:http://jingyan.baidu.com/article/cdddd41c99d07653ca00e147.html Windows Re ...

  10. AWS使用心得:当初我曾错过的那些宝贵经验

    在今天的文章中,我整理出了大量当初以前错过.而至今仍将我追悔莫及的Amazon Web Services(简称AWS)使用心得. 在几年来的实践其中,我通过在AWS之上新手构建及部署各类应用程序而积累 ...