{"id":15212,"date":"2016-11-11T12:15:10","date_gmt":"2016-11-11T10:15:10","guid":{"rendered":"https:\/\/www.webcodegeeks.com\/?p=15212"},"modified":"2016-11-10T16:03:54","modified_gmt":"2016-11-10T14:03:54","slug":"microservice-communication-queues","status":"publish","type":"post","link":"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/","title":{"rendered":"Microservice Communication with Queues"},"content":{"rendered":"<p>Microservices are small programs that handle one task. A microservice that is never used is useless though \u2014 it\u2019s the system on the whole that provides value to the user. Microservices work together by communicating messages back and forth so that they can accomplish the larger task.<\/p>\n<p>Communication is key, but there are a variety of ways this can be accomplished. A pretty standard way is through a RESTful API, passing JSON back and forth over HTTP. In one sense, this is great; it\u2019s a form of communication that\u2019s well understood. However, this method isn\u2019t without flaws because it adds other factors, such as HTTP status codes and receiving\/parsing requests and responses.<\/p>\n<p>What other ways might microservices communicate back and forth? In this article, we\u2019re going to explore the use of a queue, more specifically <a href=\"https:\/\/www.rabbitmq.com\/\">RabbitMQ<\/a>.<\/p>\n<h2>What Does RabbitMQ Do?<\/h2>\n<p>RabbitMQ provides a language-agnostic way for programs to send messages to each other. In simple terms, it allows a \u201cPublisher\/Producer\u201d to send a message and allows for a \u201cConsumer\u201d to listen for those messages.<\/p>\n<p>In one of its simpler models, it resembles what many Rails developers are used to with Sidekiq: the ability to distribute asynchronous tasks among one or more workers. Sidekiq is one of the first things I install on all my Rails projects. I don\u2019t think RabbitMQ would necessarily take its place, especially for things that work more easily within a Rails environment: sending emails, interacting with Rails models, etc.<\/p>\n<p>It doesn\u2019t stop there though. RabbitMQ can also handle Pub\/Sub functionality, where a single \u201cevent\u201d can be published and one or more consumers can subscribe to that event. You can take this further where consumers can subscribe only to specific events and\/or events that match the pattern they\u2019re watching for.<\/p>\n<p>Finally, RabbitMQ can allow for RPCs (Remote Procedure Calls), where you\u2019re looking for an answer right away from another program\u2026 basically calling a function that exists in another program.<\/p>\n<p>In this article, we\u2019ll be taking a look at both the \u201cTopic\u201d or pattern-based Pub\/Sub approach, as well as how an RPC can be accomplished.<\/p>\n<h2>Event-based and asynchronous<\/h2>\n<p>The first example we\u2019ll be working with today is a sports news provider who receives incoming data about scores, goals, players, teams, etc. It has to parse the data, store it, and perform various tasks depending on the incoming data.<\/p>\n<p>To make things a little clearer, let\u2019s imagine that, in one of the incoming data streams, we\u2019ll be notified about soccer goals.<\/p>\n<p>When we discover that a goal has happened, there are a number of things that we need to do:<\/p>\n<ul>\n<li>Parse and normalize the information<\/li>\n<li>Store the details locally<\/li>\n<li>Update the \u201cbox-score\u201d for the game that the goal took place in<\/li>\n<li>Update the league leaderboard showing who the top goal scorer is<\/li>\n<li>Notify all subscribers (push notification) of a particular league, team, or player<\/li>\n<li>And any number of other tasks or analysis that we need to do<\/li>\n<\/ul>\n<p>Do we need to do all of those tasks in order? Should the program in charge of processing incoming data need to know about all of these tasks and how to accomplish them? I suggest that other than parsing\/normalizing the incoming data and maybe even saving it locally, the rest of the tasks can be done asynchronously and that the program shouldn\u2019t really know or care about all of these other tasks.<\/p>\n<p>What we can do is have the parser program emit an event (<code>soccer.mls.goal<\/code> for example), along with its accompanying information:<\/p>\n<pre class=\"brush:php\">{\r\n  league: 'MLS',\r\n  team: 'Toronto FC',\r\n  player: 'Sebastian Giovinco',\r\n  opponent: 'New York City FC',\r\n  time: '14:21'\r\n}<\/pre>\n<p>The parser can then forget about it! It\u2019s done its work of emitting the event. The rest of the work will be done by any number of consumers who have subscribed to this specific event.<\/p>\n<h3>Producing in Ruby<\/h3>\n<p>To produce or emit events in Ruby, the first thing we need to do is install the <a href=\"http:\/\/rubybunny.info\/\">bunny<\/a> client, which allows Ruby to communicate with RabbitMQ. For an example, here is some fake incoming data that needs to trigger the <code>goal<\/code> event for soccer.<\/p>\n<pre class=\"brush:php\"># Imagine the parsing happens here :)\r\nsoccer = Soccer.new\r\nsoccer.emit_goal(\r\n  league: 'MLS',\r\n  team: 'Toronto FC',\r\n  player: 'Sebastian Giovinco',\r\n  opponent: 'New York City FC',\r\n  time: '14:21'\r\n)<\/pre>\n<p>Let\u2019s next take a look at the <code>emit_goal<\/code> function inside of the <code>Soccer<\/code> class, which builds the event slug and packages the data together to be included in the event being emitted:<\/p>\n<pre class=\"brush:php\">class Soccer\r\n  include EventEmitter\r\n\r\n  def emit_goal(raw_details)\r\n    slug = \"soccer.#{raw_details[:league]}.goal\".downcase # \"soccer.mls.goal\"\r\n    payload = raw_details.slice(:league, :team, :player, :opponent, :time)\r\n    emit('live_events', slug, payload)\r\n  end\r\nend<\/pre>\n<p>The <code>'live_events'<\/code> string has to do with which Exchange to publish the event to. An Exchange is basically like a router that decides which Queue(s) the event should be placed into. The <code>emit<\/code> method is inside of a <code>Module<\/code> I created to simplify emitting events:<\/p>\n<pre class=\"brush:php\">module EventEmitter\r\n  def emit(topic, slug, payload)\r\n    conn = Bunny.new\r\n    conn.start\r\n\r\n    ch = conn.create_channel\r\n    x = ch.topic(topic)\r\n\r\n    x.publish(payload.to_json, routing_key: slug)\r\n    puts \" [OUT] #{slug}:#{payload}\"\r\n\r\n    conn.close\r\n  end\r\nend<\/pre>\n<p>It receives the <code>topic<\/code>, event <code>slug<\/code>, and event <code>payload<\/code> and sends that information to RabbitMQ.<\/p>\n<h3>Consuming in Ruby<\/h3>\n<p>So far we have produced an event, but without a consumer to consume it, the event will be lost. Let\u2019s create a Ruby consumer that is listening for all soccer goal events.<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/11\/Screen-Shot-2016-11-07-at-1.29.34-PM.png\"><img decoding=\"async\" class=\"aligncenter wp-image-15214\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/11\/Screen-Shot-2016-11-07-at-1.29.34-PM.png\" alt=\"screen-shot-2016-11-07-at-1-29-34-pm\" width=\"860\" height=\"477\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/11\/Screen-Shot-2016-11-07-at-1.29.34-PM.png 1434w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/11\/Screen-Shot-2016-11-07-at-1.29.34-PM-300x167.png 300w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/11\/Screen-Shot-2016-11-07-at-1.29.34-PM-768x426.png 768w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/11\/Screen-Shot-2016-11-07-at-1.29.34-PM-1024x568.png 1024w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/p>\n<p>You may have noticed that what I was calling the event <code>slug<\/code> (or the <code>routing_key<\/code>) looked like <code>\"soccer.mls.goal\"<\/code>. Picking a pattern to follow is important, because consumers can choose which events to listen for based on a pattern such as <code>\"soccer.*.goal\"<\/code>: all soccer goals regardless of the league.<\/p>\n<p>The consumer in this case will be some code which updates the leaderboard for the top goal scorers in the league. It is kicked off by running a Ruby file with this line:<\/p>\n<pre class=\"brush:php\">SoccerLeaderboard.new.live_updates<\/pre>\n<p>The <code>SoccerLeaderboard<\/code> class has a method called <code>live_updates<\/code> which will call a <code>receive<\/code> method provided be an included <code>Module<\/code>. It will provide the topic, the pattern of event slug\/routing_key to listen for, and a block of code to be called any time there is a new event to process.<\/p>\n<pre class=\"brush:php\">class SoccerLeaderboard\r\n  include EventReceiver\r\n\r\n  def live_updates\r\n    receive('live_events', 'soccer.*.goal') do |payload|\r\n      puts \"#{payload['player']} has scored a new goal.\"\r\n    end\r\n  end\r\nend<\/pre>\n<p>The <code>EventReceiver<\/code> Module is a little larger, but for the most part it\u2019s just setting up a connection to RabbitMQ and telling it what it wants to listen for.<\/p>\n<pre class=\"brush:php\">module EventReceiver\r\n  def receive(topic, pattern, \u2588)\r\n    conn = Bunny.new\r\n    conn.start\r\n\r\n    ch = conn.create_channel\r\n    x = ch.topic(topic)\r\n    q = ch.queue(\"\", exclusive: true)\r\n    q.bind(x, routing_key: pattern)\r\n\r\n    puts \" [INFO] Waiting for events. To exit press CTRL+C\"\r\n\r\n    begin\r\n      q.subscribe(:block =&gt; true) do |delivery_info, properties, body|\r\n        puts \" [IN] #{delivery_info.routing_key}:#{body}\"\r\n        block.call(JSON.parse(body))\r\n      end\r\n    rescue Interrupt =&gt; _\r\n      ch.close\r\n      conn.close\r\n    end\r\n  end\r\nend<\/pre>\n<h3>Consuming in Elixir<\/h3>\n<p>I mentioned that RabbitMQ is language agnostic. What I mean by this is that we can not only have a consumer in Ruby listening for events, but we can have a consumer in Elixir listening for events at the same time.<\/p>\n<p>In Elixir, the package I used to connect to RabbitMQ was <a href=\"https:\/\/hex.pm\/packages\/amqp\">amqp<\/a>. One gotcha was that it relies on <a href=\"https:\/\/hex.pm\/packages\/amqp_client\">amqp_client<\/a> which was giving me problems with Erlang 19. To solve that, I had to link directly to the GitHub repository because it doesn\u2019t appear that the fix has been published to Hex yet.<\/p>\n<pre class=\"brush:php\">defp deps do\r\n  [\r\n    {:amqp_client, git: \"https:\/\/github.com\/dsrosario\/amqp_client.git\", branch: \"erlang_otp_19\", override: true},\r\n    {:amqp, \"~&gt; 0.1.5\"}\r\n  ]\r\nend<\/pre>\n<p>The code to listen for events in Elixir looks like the following code below. Most of the code inside of the <code>start_listening<\/code> method is just creating a connection to RabbitMQ and telling it what to subscribe to. The <code>wait_for_messages<\/code> is where the event processing takes place.<\/p>\n<pre class=\"brush:php\">defmodule GoalNotifications do\r\n  def start_listening do\r\n    {:ok, connection} = AMQP.Connection.open\r\n    {:ok, channel} = AMQP.Channel.open(connection)\r\n    AMQP.Exchange.declare(channel, \"live_events\", :topic)\r\n    {:ok, %{queue: queue_name}} = AMQP.Queue.declare(channel, \"\", exclusive: true)\r\n    AMQP.Queue.bind(channel, queue_name, \"live_events\", routing_key: \"*.*.goal\")\r\n    AMQP.Basic.consume(channel, queue_name, nil, no_ack: true)\r\n    IO.puts \" [INFO] Waiting for messages. To exit press CTRL+C, CTRL+C\"\r\n    wait_for_messages(channel)\r\n  end\r\n\r\n  def wait_for_messages(channel) do\r\n    receive do\r\n      {:basic_deliver, payload, meta} -&gt;\r\n      IO.puts \" [x] Received [#{meta.routing_key}] #{payload}\"\r\n\r\n      wait_for_messages(channel)\r\n    end\r\n  end\r\nend\r\n\r\n\r\nGoalNotifications.start_listening<\/pre>\n<h2>RPC\u2026 when you need an answer right away<\/h2>\n<p>Remote Procedure Calls can be accomplished with RabbitMQ, but I\u2019ll be honest: It\u2019s more involved than the examples above for more of a typical Pub\/Sub approach. To me, it felt like each side (producer\/consumer) has to act as both a producer and a consumer.<\/p>\n<p>The flow is a little like this:<\/p>\n<ul>\n<li>Program A asks Program B for some information, providing a unique ID for the request<\/li>\n<li>Program A listens for responses that match the same unique ID<\/li>\n<li>Program B receives request, does the work and provides a response with the same unique ID<\/li>\n<li>Program A runs callback once matching unique ID is found in response from Program B<\/li>\n<\/ul>\n<p>In this example, we\u2019ll be talking about a product\u2019s inventory\u2026 an answer we need to know right away to be sure that there is stock available for a customer to purchase.<\/p>\n<pre class=\"brush:php\">inventory = ProductInventory.new('abc123').inventory\r\nputs \"Product has inventory of #{inventory}\"<\/pre>\n<p>The <code>ProductInventory<\/code> class is quite simple, mostly because I\u2019ve hidden the complexity of the RPC call inside of a class called <code>RemoteCall<\/code>.<\/p>\n<pre class=\"brush:php\">class ProductInventory\r\n  attr_accessor :product_sku\r\n\r\n  def initialize(product_sku)\r\n    @product_sku = product_sku\r\n  end\r\n\r\n  def inventory\r\n    RemoteCall.new('inventory').response(product_sku)\r\n  end\r\nend<\/pre>\n<p>Now let\u2019s take a look at how <code>RemoteCall<\/code> is handling it:<\/p>\n<pre class=\"brush:php\">require 'bunny'\r\nrequire 'securerandom'\r\n\r\nclass RemoteCall\r\n  attr_reader :lock, :condition\r\n  attr_accessor :conn, :channel, :exchange, :reply_queue,\r\n    :remote_response, :call_id, :queue_name\r\n\r\n  def initialize(queue_name)\r\n    @queue_name = queue_name\r\n    @conn = Bunny.new\r\n    @conn.start\r\n    @channel = conn.create_channel\r\n    @exchange = channel.default_exchange\r\n    @reply_queue = channel.queue('', exclusive: true)\r\n  end\r\n\r\n  def response(payload)\r\n    @lock = Mutex.new\r\n    @condition = ConditionVariable.new\r\n    response_callback(reply_queue)\r\n\r\n    self.call_id = SecureRandom.uuid\r\n    puts \"Awaiting call with correlation ID #{call_id}\"\r\n    exchange.publish(payload,\r\n      routing_key: queue_name,\r\n      correlation_id: call_id,\r\n      reply_to: reply_queue.name\r\n    )\r\n    lock.synchronize { condition.wait(lock) }\r\n\r\n    remote_response\r\n  end\r\n\r\n  private\r\n\r\n  def response_callback(reply_queue)\r\n    that = self\r\n    reply_queue.subscribe do |delivery_info, properties, payload|\r\n      if properties[:correlation_id] == that.call_id\r\n        that.remote_response = payload\r\n        that.lock.synchronize { that.condition.signal }\r\n      end\r\n    end\r\n  end\r\nend<\/pre>\n<p>So if all that code was for the Producer, what does the Consumer look like? It\u2019s kicked off with:<\/p>\n<pre class=\"brush:php\">server = InventoryServer.new\r\nserver.start<\/pre>\n<p>And the <code>InventoryServer<\/code> looks like:<\/p>\n<pre class=\"brush:php\">require 'bunny'\r\n\r\nclass InventoryServer\r\n  QUEUE_NAME = 'inventory'.freeze\r\n  attr_reader :conn\r\n\r\n  def initialize\r\n    @conn = Bunny.new\r\n  end\r\n\r\n  def start\r\n    conn.start\r\n    channel = conn.create_channel\r\n    queue = channel.queue(QUEUE_NAME)\r\n    exchange = channel.default_exchange\r\n    subscribe(queue, exchange)\r\n  rescue Interrupt =&gt; _\r\n    channel.close\r\n    conn.close\r\n  end\r\n\r\n  def subscribe(queue, exchange)\r\n    puts \"Listening for inventory calls\"\r\n\r\n    queue.subscribe(block: true) do |delivery_info, properties, payload|\r\n      puts \"Received call with correlation ID #{properties.correlation_id}\"\r\n      product_sku = payload\r\n      response = self.class.inventory(product_sku)\r\n      exchange.publish(response.to_s,\r\n        routing_key: properties.reply_to,\r\n        correlation_id: properties.correlation_id\r\n      )\r\n    end\r\n  end\r\n\r\n  def self.inventory(product_sku)\r\n    42\r\n  end\r\nend<\/pre>\n<p>Wow\u2026 that\u2019s a lot of work to make an RPC! RabbitMQ has a <a href=\"https:\/\/www.rabbitmq.com\/tutorials\/tutorial-six-ruby.html\">great guide explaining<\/a> how this works in a variety of different languages.<\/p>\n<h2>Conclusion<\/h2>\n<p>Microservices don\u2019t always need to communicate synchronously, and they don\u2019t always need to communicate over HTTP\/JSON either. They can, but next time you\u2019re thinking about how they should speak to each other, why not consider doing it asynchronously using RabbitM? It comes with a great interface for monitoring the activity of the queue and has fantastic client support in a variety of popular languages. It\u2019s fast, reliable, and scalable.<\/p>\n<p>Microservices aren\u2019t free though\u2026 I think it\u2019s worthwhile considering whether the extra complexity involved in setting up separate services and providing them a way to communicate couldn\u2019t be better handled using something like Sidekiq and writing clean, modular code.<\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td><span class=\"reference\">Reference: <\/span><\/td>\n<td><a href=\"https:\/\/blog.codeship.com\/microservice-communication-queues\/\">Microservice Communication with Queues<\/a> from our <a href=\"http:\/\/www.webcodegeeks.com\/join-us\/wcg\/\">WCG partner<\/a>\u00a0Leigh Halliday at the <a href=\"http:\/\/blog.codeship.com\/\">Codeship Blog<\/a> blog.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Microservices are small programs that handle one task. A microservice that is never used is useless though \u2014 it\u2019s the system on the whole that provides value to the user. Microservices work together by communicating messages back and forth so that they can accomplish the larger task. Communication is key, but there are a variety &hellip;<\/p>\n","protected":false},"author":113,"featured_media":4128,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[21],"tags":[228,341],"class_list":["post-15212","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ruby","tag-microservices","tag-rabbitmq"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Microservice Communication with Queues - Web Code Geeks - 2026<\/title>\n<meta name=\"description\" content=\"Microservices are small programs that handle one task. A microservice that is never used is useless though \u2014 it\u2019s the system on the whole that provides\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Microservice Communication with Queues - Web Code Geeks - 2026\" \/>\n<meta property=\"og:description\" content=\"Microservices are small programs that handle one task. A microservice that is never used is useless though \u2014 it\u2019s the system on the whole that provides\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/\" \/>\n<meta property=\"og:site_name\" content=\"Web Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/webcodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2016-11-11T10:15:10+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/04\/ruby-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Leigh Halliday\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@leighchalliday\" \/>\n<meta name=\"twitter:site\" content=\"@webcodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Leigh Halliday\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/\"},\"author\":{\"name\":\"Leigh Halliday\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/e496b17f78cdca27723b8e225dc6ab6b\"},\"headline\":\"Microservice Communication with Queues\",\"datePublished\":\"2016-11-11T10:15:10+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/\"},\"wordCount\":1469,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/04\/ruby-logo.jpg\",\"keywords\":[\"Microservices\",\"RabbitMQ\"],\"articleSection\":[\"Ruby\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/\",\"name\":\"Microservice Communication with Queues - Web Code Geeks - 2026\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/04\/ruby-logo.jpg\",\"datePublished\":\"2016-11-11T10:15:10+00:00\",\"description\":\"Microservices are small programs that handle one task. A microservice that is never used is useless though \u2014 it\u2019s the system on the whole that provides\",\"breadcrumb\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/#primaryimage\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/04\/ruby-logo.jpg\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/04\/ruby-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.webcodegeeks.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Ruby\",\"item\":\"https:\/\/www.webcodegeeks.com\/category\/ruby\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Microservice Communication with Queues\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"name\":\"Web Code Geeks\",\"description\":\"Web Developers Resource Center\",\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.webcodegeeks.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/webcodegeeks\",\"https:\/\/x.com\/webcodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/e496b17f78cdca27723b8e225dc6ab6b\",\"name\":\"Leigh Halliday\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/bd40251a1acc424c292c35a3485264a801efa20efa7063c3e320a0a354ddafac?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/bd40251a1acc424c292c35a3485264a801efa20efa7063c3e320a0a354ddafac?s=96&d=mm&r=g\",\"caption\":\"Leigh Halliday\"},\"description\":\"Leigh is a developer at theScore. He writes about Ruby, Rails, and software development on his personal site.\",\"sameAs\":[\"http:\/\/www.leighhalliday.com\/\",\"https:\/\/x.com\/leighchalliday\"],\"url\":\"https:\/\/www.webcodegeeks.com\/author\/leigh-halliday\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Microservice Communication with Queues - Web Code Geeks - 2026","description":"Microservices are small programs that handle one task. A microservice that is never used is useless though \u2014 it\u2019s the system on the whole that provides","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/","og_locale":"en_US","og_type":"article","og_title":"Microservice Communication with Queues - Web Code Geeks - 2026","og_description":"Microservices are small programs that handle one task. A microservice that is never used is useless though \u2014 it\u2019s the system on the whole that provides","og_url":"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/","og_site_name":"Web Code Geeks","article_publisher":"https:\/\/www.facebook.com\/webcodegeeks","article_published_time":"2016-11-11T10:15:10+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/04\/ruby-logo.jpg","type":"image\/jpeg"}],"author":"Leigh Halliday","twitter_card":"summary_large_image","twitter_creator":"@leighchalliday","twitter_site":"@webcodegeeks","twitter_misc":{"Written by":"Leigh Halliday","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/#article","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/"},"author":{"name":"Leigh Halliday","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/e496b17f78cdca27723b8e225dc6ab6b"},"headline":"Microservice Communication with Queues","datePublished":"2016-11-11T10:15:10+00:00","mainEntityOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/"},"wordCount":1469,"commentCount":0,"publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/04\/ruby-logo.jpg","keywords":["Microservices","RabbitMQ"],"articleSection":["Ruby"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/","url":"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/","name":"Microservice Communication with Queues - Web Code Geeks - 2026","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/#primaryimage"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/04\/ruby-logo.jpg","datePublished":"2016-11-11T10:15:10+00:00","description":"Microservices are small programs that handle one task. A microservice that is never used is useless though \u2014 it\u2019s the system on the whole that provides","breadcrumb":{"@id":"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/#primaryimage","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/04\/ruby-logo.jpg","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/04\/ruby-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.webcodegeeks.com\/ruby\/microservice-communication-queues\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.webcodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Ruby","item":"https:\/\/www.webcodegeeks.com\/category\/ruby\/"},{"@type":"ListItem","position":3,"name":"Microservice Communication with Queues"}]},{"@type":"WebSite","@id":"https:\/\/www.webcodegeeks.com\/#website","url":"https:\/\/www.webcodegeeks.com\/","name":"Web Code Geeks","description":"Web Developers Resource Center","publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.webcodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.webcodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.webcodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/webcodegeeks","https:\/\/x.com\/webcodegeeks"]},{"@type":"Person","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/e496b17f78cdca27723b8e225dc6ab6b","name":"Leigh Halliday","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/bd40251a1acc424c292c35a3485264a801efa20efa7063c3e320a0a354ddafac?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/bd40251a1acc424c292c35a3485264a801efa20efa7063c3e320a0a354ddafac?s=96&d=mm&r=g","caption":"Leigh Halliday"},"description":"Leigh is a developer at theScore. He writes about Ruby, Rails, and software development on his personal site.","sameAs":["http:\/\/www.leighhalliday.com\/","https:\/\/x.com\/leighchalliday"],"url":"https:\/\/www.webcodegeeks.com\/author\/leigh-halliday\/"}]}},"_links":{"self":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/15212","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/users\/113"}],"replies":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/comments?post=15212"}],"version-history":[{"count":0,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/15212\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media\/4128"}],"wp:attachment":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media?parent=15212"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/categories?post=15212"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/tags?post=15212"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}