0
0
MicroservicesHow-ToBeginner ยท 4 min read

How Microservices Communicate: Methods and Examples

Microservices communicate using synchronous methods like HTTP/REST or gRPC, and asynchronous methods like message queues or event streams. These methods help services exchange data reliably and independently.
๐Ÿ“

Syntax

Microservices communicate mainly in two ways:

  • Synchronous communication: One service sends a request and waits for a response. Common protocols are HTTP/REST and gRPC.
  • Asynchronous communication: Services send messages without waiting for immediate replies. Common tools are message queues like RabbitMQ or Kafka.

Example syntax for HTTP request:

GET /api/resource HTTP/1.1
Host: service.example.com

Example syntax for sending a message to a queue:

queue.send({ event: 'order_created', data: {...} })
python
import requests

# Synchronous HTTP call
response = requests.get('http://service.example.com/api/resource')
print(response.status_code, response.json())
Output
200 {'id': 123, 'name': 'example resource'}
๐Ÿ’ป

Example

This example shows two microservices communicating synchronously via HTTP and asynchronously via a message queue.

python
from flask import Flask, request, jsonify
import threading
import queue

# Simple message queue simulation
message_queue = queue.Queue()

# Service A: Sends HTTP request and publishes event
app_a = Flask('service_a')

@app_a.route('/start', methods=['POST'])
def start():
    # Synchronous call to Service B
    import requests
    resp = requests.get('http://localhost:5001/data')
    data = resp.json()

    # Asynchronous event publish
    message_queue.put({'event': 'data_processed', 'payload': data})
    return jsonify({'status': 'started', 'service_b_data': data})

# Service B: Responds to HTTP request
app_b = Flask('service_b')

@app_b.route('/data')
def data():
    return jsonify({'value': 42})

# Consumer for async messages
def consume_messages():
    while True:
        msg = message_queue.get()
        print(f"Consumed event: {msg['event']} with payload: {msg['payload']}")

if __name__ == '__main__':
    threading.Thread(target=consume_messages, daemon=True).start()
    threading.Thread(target=lambda: app_b.run(port=5001), daemon=True).start()
    app_a.run(port=5000)
Output
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) * Running on http://127.0.0.1:5001/ (Press CTRL+C to quit) Consumed event: data_processed with payload: {'value': 42}
โš ๏ธ

Common Pitfalls

Common mistakes when microservices communicate include:

  • Tight coupling: Services depend too much on each other's availability, causing failures.
  • Ignoring retries and timeouts: Not handling failed requests leads to errors and poor user experience.
  • Not using idempotency: Repeated messages or requests cause duplicate processing.
  • Overusing synchronous calls: Can cause slowdowns and cascading failures.

Correct approach is to use asynchronous messaging for loose coupling and implement retries with backoff.

python
import requests

# Wrong: No timeout, no error handling
response = requests.get('http://service-b/api')
print(response.json())

# Right: With timeout and error handling
try:
    response = requests.get('http://service-b/api', timeout=2)
    response.raise_for_status()
    print(response.json())
except requests.exceptions.RequestException as e:
    print(f'Error communicating with service B: {e}')
Output
Error communicating with service B: HTTPConnectionPool(host='service-b', port=80): Max retries exceeded with url: /api (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f8c8c>: Failed to establish a new connection'))
๐Ÿ“Š

Quick Reference

Communication TypeDescriptionCommon Tools/ProtocolsUse Case
SynchronousRequest and wait for responseHTTP/REST, gRPCSimple queries, immediate response needed
AsynchronousSend message, no immediate waitRabbitMQ, Kafka, AWS SNS/SQSEvent-driven, decoupled processing
Event-drivenPublish/subscribe to eventsKafka, MQTTBroadcast changes to multiple services
Message QueueQueue messages for processingRabbitMQ, ActiveMQReliable task processing, load leveling
โœ…

Key Takeaways

Microservices communicate synchronously via HTTP/REST or gRPC and asynchronously via message queues or event streams.
Use asynchronous communication to reduce tight coupling and improve system resilience.
Always implement retries, timeouts, and idempotency to handle failures gracefully.
Avoid overusing synchronous calls to prevent cascading failures and slowdowns.
Choose communication method based on use case: immediate response or decoupled event processing.