Microservices — HTTP orqali ma'lumot almashish

~20 daq · NestJS · Ilg'or mavzular

Muammodan boshlaylik

Oldingi darsda RabbitMQ bilan servislar orasida xabar almashishni ko'rdik. Lekin har doim message broker kerak emas.

Ba'zida eng oddiy yondashuv yaxshi: Orders Service inventarni tekshirish uchun Inventory Service ga oddiy HTTP so'rov yuboradi.


Qachon HTTP, qachon RabbitMQ?

HTTP:                          RabbitMQ:
──────────────────             ──────────────────
Javob darhol kerak             Fon vazifalar
Oddiy so'rov-javob             Reliability muhim
Kichik loyiha                  Ko'p servis, yuqori yuk

Kichik loyihalarda HTTP yetarli va sodda. Yirik tizimda message queue kerak.


O'rnatish

npm install @nestjs/axios axios

Fayl tuzilmasi

src/
  orders/
    orders.module.ts   ← HttpModule import qilinadi
    orders.service.ts  ← HTTP so'rov shu yerdan yuboriladi

HttpModule ulash

// orders/orders.module.ts
import { Module } from '@nestjs/common';
import { HttpModule } from '@nestjs/axios';
import { OrdersService } from './orders.service';

@Module({
  imports: [HttpModule], // ← shu yerga qo'shildi
  providers: [OrdersService],
})
export class OrdersModule {}

Boshqa servisce so'rov yuborish

// orders/orders.service.ts
import { Injectable, BadRequestException } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { firstValueFrom } from 'rxjs';

@Injectable()
export class OrdersService {
  constructor(private httpService: HttpService) {}

  async createOrder(dto: { productId: number; quantity: number; email: string }) {
    // Inventory Service dan stok tekshirish
    const response = await firstValueFrom(
      this.httpService.get(`http://inventory-service:3001/stock/${dto.productId}`)
    );

    if (response.data.quantity < dto.quantity) {
      throw new BadRequestException('Mahsulot yetarli emas');
    }

    return { id: Date.now(), ...dto };
  }
}

Nima uchun firstValueFrom()?

HttpService ichida Axios ishlatadi, lekin javobni RxJS Observable sifatida qaytaradi. firstValueFrom() uni oddiy Promise ga aylantiradi — await bilan ishlash uchun.

// Observable → Promise
const response = await firstValueFrom(this.httpService.get(url));

// response.data — asosiy ma'lumot
console.log(response.data);

URL larni .env da saqlash

URL ni kod ichiga qattiq yozmaslik kerak — servis manzili o'zgarishi mumkin:

# .env
INVENTORY_SERVICE_URL=http://inventory-service:3001
// orders/orders.service.ts
import { ConfigService } from '@nestjs/config';

@Injectable()
export class OrdersService {
  constructor(
    private httpService: HttpService,
    private config: ConfigService,
  ) {}

  async getStock(productId: number) {
    const baseUrl = this.config.get('INVENTORY_SERVICE_URL');

    const response = await firstValueFrom(
      this.httpService.get(`${baseUrl}/stock/${productId}`)
    );

    return response.data;
  }
}

Xatolarni boshqarish

Boshqa servis mavjud bo'lmasa yoki xato qaytarsa:

async getStock(productId: number) {
  try {
    const response = await firstValueFrom(
      this.httpService.get(`${this.baseUrl}/stock/${productId}`)
    );
    return response.data;
  } catch (error) {
    if (error.response?.status === 404) {
      throw new NotFoundException('Mahsulot topilmadi');
    }
    throw new ServiceUnavailableException('Inventory service ishlamayapti');
  }
}

Docker Compose da servis nomi

Docker Compose da servislar bir-birini nomi bilan topadi — IP manzil kerak emas:

# docker-compose.yml
services:
  orders-service:
    build: ./orders
    environment:
      INVENTORY_SERVICE_URL: http://inventory-service:3001

  inventory-service:
    build: ./inventory
    ports:
      - "3001:3001"

inventory-service nomi Docker ichki DNS orqali avtomatik IP manzilga aylanadi.


Tez-tez uchraydigan xatolar

1. ECONNREFUSED

connect ECONNREFUSED inventory-service:3001

Sababi: Servis ishlamayapti yoki nomi noto'g'ri. Yechim: docker compose logs inventory-service bilan xatoni ko'ring.


2. Timeout Sababi: Servis javob bermayapti yoki juda sekin. Yechim: HttpModule.register({ timeout: 5000 }) bilan vaqt chegarasi qo'ying.


Xulosa

  • HttpService — boshqa servisce HTTP so'rov yuborish uchun
  • firstValueFrom() — Observable ni Promise ga aylantiradi
  • URL larni .env da saqlang, kod ichiga yozmang
  • Docker Compose da servislar nomi orqali bir-birini topadi
  • Xatolarni try/catch bilan boshqaring

**Keyingi dars: 42-dars: Bull Queue — task queue, background jobs**