การสื่อสารระหว่างบริการ
นำรูปแบบการสื่อสารระหว่างไมโครเซอร์วิสที่มีประสิทธิภาพมาใช้ รวมถึงกลไกที่อิงเหตุการณ์และแบบคำขอ-การตอบกลับ
การสื่อสารระหว่างบริการ เป็นบทเรียน NestJS Enterprise Backend APIs ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 3 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน NestJS Enterprise Backend APIs และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส NestJS Enterprise Backend APIs มีบทเรียนทั้งหมด 3 บทเรียน
บางส่วนของบทเรียนนี้ยังไม่ได้รับการแปล และแสดงเป็นภาษาอังกฤษ
Microservices Need to Talk
Microservices are designed to be independent, but they often need to collaborate to complete complex tasks. This means they must communicate with each other!
In this lesson, we'll explore the main patterns for how your NestJS microservices can send messages and share data effectively.
Sync vs. Async Communication
Understanding the difference between synchronous and asynchronous communication is crucial for microservices:
- Synchronous: The sender waits for an immediate reply. It's like a direct phone call where you expect an answer right away.
- Asynchronous: The sender doesn't wait for a reply. It's like sending an email – you send it and continue with other tasks, expecting a reply later (or not at all).
Both patterns have distinct use cases in a distributed system.
Request-Response Pattern
The Request-Response pattern is a synchronous communication method. One service (the client) sends a request to another service (the server) and pauses its own execution, waiting for a direct response.
- Ideal for operations needing an immediate result.
- Similar to how a typical web client interacts with a REST API.
- Often implemented using HTTP, RPC, or message brokers configured for synchronous replies.
NestJS: Receiving Requests
In NestJS, a microservice listens for incoming requests using the @MessagePattern() decorator. This pattern must match the one sent by the client.
The decorated handler function receives the payload and returns a response. Try running this Product Service microservice:
import { NestFactory } from '@nestjs/core';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { Module, Controller, MessagePattern } from '@nestjs/common';
@Controller()
class ProductController {
@MessagePattern('get_product_details')
getProductDetails(id: string): any {
console.log(`Product Service: Request for ID: ${id}`);
const products = {
'1': { id: '1', name: 'Laptop', price: 1200 },
'2': { id: '2', name: 'Mouse', price: 25 },
};
return products[id] || { id, name: 'Product Not Found', price: 0 };
}
}
@Module({
controllers: [ProductController],
})
class AppModule {}
async function bootstrap() {
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
AppModule,
{
transport: Transport.TCP,
options: { host: '127.0.0.1', port: 8877 },
},
);
await app.listen();
console.log('Product Microservice is listening on port 8877');
}
bootstrap();NestJS: Sending Requests
To send a request to the 'Product Service' (from the previous scene), another microservice or an API Gateway uses a ClientProxy.
The client.send() method dispatches a message with a specific pattern and payload, returning an RxJS Observable that resolves with the response.
This snippet shows how a client service would initiate the request:
// product-client.service.ts in 'Order Service' microservice
import { Injectable, Inject } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
import { lastValueFrom } from 'rxjs'; // For awaiting observable
@Injectable()
export class ProductClientService {
constructor(@Inject('PRODUCT_SERVICE') private client: ClientProxy) {}
async fetchProduct(productId: string): Promise<any> {
console.log(`Order Service: Fetching product ID: ${productId}`);
// 'get_product_details' must match the pattern in Product Service
const product = await lastValueFrom(
this.client.send('get_product_details', productId),
);
console.log('Received product:', product);
return product;
}
}
// To make this work, 'PRODUCT_SERVICE' needs to be registered
// in an AppModule using ClientsModule.register():
// imports: [
// ClientsModule.register([
// {
// name: 'PRODUCT_SERVICE',
// transport: Transport.TCP,
// options: { host: '127.0.0.1', port: 8877 },
// },
// ]),
// ],When to Use Request-Response
The Request-Response pattern is best when:
- You need an immediate answer from the target service.
- The operation is critical and requires direct feedback (e.g., payment processing, user authentication).
- You are fetching specific data from another service.
- The interaction is a clear client-server relationship.
Be aware that this pattern introduces direct coupling between services.
Event-Based Communication
Event-based communication is an asynchronous pattern that uses a 'publish-subscribe' model. Services don't directly call each other; instead, they publish events to a message broker (like RabbitMQ) when something notable happens.
- A service publishes an event (e.g., 'OrderCreated').
- Other services subscribe to events they are interested in.
- This pattern greatly decouples services, making them more independent.
NestJS: Publishing Events
To publish an event in NestJS, you use the client.emit() method of a ClientProxy. Unlike send(), emit() sends the event and immediately returns, not waiting for a response.
This 'fire-and-forget' approach is ideal for notifying other services about state changes. Run this Order Service that emits an event:
import { NestFactory } from '@nestjs/core';
import { Module, Controller, Post, Body, Inject } from '@nestjs/common';
import { ClientProxy, ClientsModule, Transport } from '@nestjs/microservices';
interface OrderCreatedEvent {
orderId: string;
userId: string;
totalAmount: number;
}
@Controller('orders')
class OrderController {
constructor(@Inject('NOTIFICATION_SERVICE') private client: ClientProxy) {}
@Post()
async createOrder(@Body() orderData: any) {
const orderId = `ORD-${Date.now()}`;
const event: OrderCreatedEvent = {
orderId,
userId: orderData.userId || 'user-123',
totalAmount: orderData.amount || 100,
};
this.client.emit('order_created', event);
console.log(`Order ${orderId} created, 'order_created' event emitted.`);
return { message: 'Order created and event sent', orderId };
}
}
@Module({
imports: [
ClientsModule.register([
{
name: 'NOTIFICATION_SERVICE',
transport: Transport.TCP,
options: { host: '127.0.0.1', port: 8878 },
},
]),
],
controllers: [OrderController],
})
class AppModule {}
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
console.log('Order Service (HTTP) is listening on port 3000');
}
bootstrap();NestJS: Listening to Events
Other microservices can subscribe to events using the @EventPattern() decorator. When an event with a matching pattern is emitted, the decorated method is automatically triggered.
This allows multiple services to react to the same event independently. Run this Notification Service to receive the event:
import { NestFactory } from '@nestjs/core';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { Module, Controller, EventPattern } from '@nestjs/common';
interface OrderCreatedEvent {
orderId: string;
userId: string;
totalAmount: number;
}
@Controller()
class NotificationController {
@EventPattern('order_created')
handleOrderCreated(data: OrderCreatedEvent) {
console.log('Notification Service received OrderCreated event:', data);
console.log(`Sending notification for Order ${data.orderId} to User ${data.userId}`);
}
}
@Module({
controllers: [NotificationController],
})
class AppModule {}
async function bootstrap() {
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
AppModule,
{
transport: Transport.TCP,
options: { host: '127.0.0.1', port: 8878 },
},
);
await app.listen();
console.log('Notification Microservice is listening on port 8878');
}
bootstrap();When to Use Event-Driven
Event-based communication is highly beneficial for:
- Decoupling: Services don't need to know about each other, reducing dependencies.
- Broadcasting: Notifying multiple consumers about a single event (e.g., 'UserRegistered' event).
- Long-running processes: Initiating tasks that don't require an immediate response.
- Resilience: Services can process events when they are available, improving fault tolerance.
It adds complexity but offers great flexibility and scalability.
Communication Patterns Quiz
Consider a scenario where an 'Order Service' needs to inform a 'Shipping Service' that an order is ready to be shipped, but the 'Order Service' doesn't need to wait for the shipping confirmation immediately. Which communication pattern is best suited for this?
Recap: Talking Services
Congratulations! You've learned about the fundamental patterns for inter-service communication in NestJS microservices.
- Request-Response (using
client.send()and@MessagePattern()) is for immediate, direct interactions where a reply is expected. - Event-Based (using
client.emit()and@EventPattern()) is for asynchronous, decoupled communication via events, ideal for notifications and broadcasting.
Choosing the right pattern depends on your specific needs for coupling, responsiveness, and scalability in your distributed system.
เรียนรู้ TypeScript ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 20
- บทเรียน
- 76
คำถามที่พบบ่อย
บทเรียน “การสื่อสารระหว่างบริการ” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การสื่อสารระหว่างบริการ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส NestJS Enterprise Backend APIs ให้อัปเกรดเป็น CoddyKit PRO คอร์ส NestJS Enterprise Backend APIs มีบทเรียนทั้งหมด 3 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การสื่อสารระหว่างบริการ”
นำรูปแบบการสื่อสารระหว่างไมโครเซอร์วิสที่มีประสิทธิภาพมาใช้ รวมถึงกลไกที่อิงเหตุการณ์และแบบคำขอ-การตอบกลับ คุณปฏิบัติ NestJS Enterprise Backend APIs ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน NestJS Enterprise Backend APIs หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน NestJS Enterprise Backend APIs บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 3 บทเรียน
บทเรียน “การสื่อสารระหว่างบริการ” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน NestJS Enterprise Backend APIs นี้ได้ไหม
ได้ บทเรียน NestJS Enterprise Backend APIs ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ภาพรวมไมโครเซอร์วิสของ NestJS
- การผสานรวม RabbitMQ
- การสื่อสารระหว่างบริการ