CodeGym /Các khóa học /ChatGPT Apps /MCP Gateway: tại sao cần nó giữa ChatGPT và các dịch vụ c...

MCP Gateway: tại sao cần nó giữa ChatGPT và các dịch vụ của bạn

ChatGPT Apps
Mức độ , Bài học
Có sẵn

1. Vì sao lại cần thêm một lớp nữa?

Hầu như ai cũng bắt đầu giống nhau: có một MCP server, nó mô tả vài công cụ, ChatGPT gọi thẳng tới qua HTTPS, và tưởng như mọi thứ đều ổn. Kiến trúc giả định như sau:

ChatGPT  →  máy chủ MCP của bạn  →  cơ sở dữ liệu / API bên ngoài

Ở giai đoạn “pet project”, đây thực sự là một lựa chọn ổn. Nhưng ngay khi ứng dụng bắt đầu mở rộng chức năng và team phát triển lớn dần, vấn đề sẽ xuất hiện rất nhanh.

Thứ nhất, MCP server biến thành “God object”. Trong đó cùng lúc tồn tại công cụ gợi ý quà tặng, checkout, analytics, và thêm cả kiểu “hay là nhét luôn báo cáo vào đây”. Các phần code khác nhau có SLA khác nhau và yêu cầu bảo mật khác nhau, nhưng lại bị dán vào cùng một tiến trình.

Thứ hai, ChatGPT và các client khác buộc phải biết topology dịch vụ của bạn. Nếu sau nửa năm bạn có thêm một MCP server cho commerce, bạn sẽ phải kết nối lại client, đổi config và mô tả. Thay vì “một điểm vào”, bạn sẽ có cả một rừng URL.

Thứ ba, trở nên không rõ nên triển khai những thứ dùng chung cho mọi dịch vụ ở đâu: xác thực, ghi log, metric, rate limiting, kiểm tra token, bản địa hóa và định tuyến theo vùng. Nếu rải những thứ này vào tất cả dịch vụ MCP/Agent, bạn sẽ nhận nhiều phần trùng lặp và hành vi khác nhau ở mỗi dịch vụ.

Để tách rời sự phụ thuộc này và đồng thời ẩn sự phức tạp bên trong khỏi ChatGPT, MCP Gateway xuất hiện — một cổng mạng (gateway) và điểm vào thống nhất cho toàn bộ lưu lượng MCP.

2. MCP Gateway là gì trong ngữ cảnh ChatGPT App

Về mặt hình thức, MCP Gateway là lớp proxy và điểm vào thống nhất giữa các MCP client (ChatGPT, MCP Jam, công cụ nội bộ của bạn) và tập các backend service — thường là REST/HTTP API, microservice, dịch vụ Agents, commerce backend, v.v.

Gateway tự triển khai giao thức MCP ra bên ngoài (đối với ChatGPT, nó trông như một MCP server duy nhất), còn bên trong chỉ gọi tới các REST endpoint thông thường qua HTTP/gRPC.

Với yêu cầu tools/list, gateway không proxy lời gọi đi tiếp, mà trả về danh sách công cụ của riêng nó: hoặc được mô tả cố định trong code, hoặc được tổng hợp từ cấu hình. Mỗi tool được gắn với một REST endpoint và schema dữ liệu cụ thể. Với yêu cầu tools/call, gateway lấy tên công cụ, tìm route REST tương ứng và gọi nó qua fetch/HTTP client.

Mô tả sơ đồ có thể như sau:

flowchart LR
    ChatGPT["ChatGPT / mô hình"] --> |MCP JSON-RPC| Gateway["MCP Gateway<br/>(máy chủ MCP duy nhất)"]
    Gateway --> GiftAPI["Gift REST API<br/>/ microservice quà tặng"]
    Gateway --> CommerceAPI["Commerce REST API<br/>/ ACP / thanh toán"]
    Gateway --> AnalyticsAPI["Analytics Service<br/>/ sự kiện và số liệu"]

Đối với ChatGPT đây là một máy chủ: một URL, một tập công cụ, một luồng sự kiện. Còn với bạn — một điểm định tuyến linh hoạt để chuyển lưu lượng tới các dịch vụ “nóng/lạnh” khác nhau.

3. MCP Gateway trong kiến trúc GiftGenius

Để bớt nói trừu tượng và cho thấy gateway “trong hệ thống sống”, hãy tiếp tục ví dụ GiftGenius — ứng dụng gợi ý quà tặng và có thể tạo đơn hàng qua ACP/Instant Checkout.

Ở phiên bản đơn giản, ta có một MCP server biết cả suggest_giftscheckout_start. Giờ khi ứng dụng đã lớn, ta tách trách nhiệm:

  • Gift REST API — tìm kiếm và gợi ý quà, làm việc với catalog và feed (dịch vụ HTTP/REST thông thường).
  • Commerce REST API — ACP, phiên checkout, trạng thái đơn hàng, kết nối với nhà cung cấp thanh toán.
  • Analytics Service / REST API — thu thập sự kiện và số liệu (mở gợi ý nào, mua gì).
  • Dịch vụ Agents riêng (nếu cần) — kịch bản nhiều bước phức tạp. Nó cũng truy cập qua HTTP/REST, không qua MCP.

MCP Gateway trở thành điểm vào thống nhất cho tất cả các thành phần này. Nó:

  • với yêu cầu tools/list trả về danh sách tools thống nhất do chính nó mô tả: mỗi tool gắn với một REST endpoint của một dịch vụ;
  • với yêu cầu tools/call nhìn vào tên công cụ (params.name), dựa trên bảng định tuyến để quyết định nên tới REST service nào và gọi HTTP method tương ứng (qua fetch, axios, v.v.).

Nếu đến tools/call với tên suggest_gifts, gateway gọi REST endpoint tương ứng ở Gift REST API. Nếu là checkout_start, yêu cầu sẽ đi sang Commerce REST API.

Đoạn pseudocode TypeScript kiểu Express có thể như sau:

// Trình xử lý MCP rất đơn giản (rút gọn)
app.post("/mcp", async (req, res) => {
  const mcpReq = req.body as { method: string; params?: any };
  const ctx = buildContextFromHeaders(req); // auth, locale, v.v.

  const toolName = mcpReq.params?.name;
  const backendRes = await callBackend(toolName, mcpReq, ctx);

  res.json(backendRes);
});

Bên trong pickBackend bạn có thể dựa vào tên method, tên công cụ, locale của người dùng và thậm chí phiên bản dịch vụ (để phục vụ canary và phát hành blue/green, sẽ nói kỹ hơn sau trong module).

4. Trách nhiệm của MCP Gateway: nó chắc chắn làm gì

Chúng ta đã xem gateway nằm ở đâu trong kiến trúc GiftGenius. Giờ hãy ghi rõ những trách nhiệm của nó như một lớp riêng, bất kể ứng dụng cụ thể. Quan trọng là nhìn gateway như một lớp mạng và liên dịch vụ. Nhiệm vụ của nó — không nghĩ về logic quà tặng, mà giải quyết các bài toán hạ tầng xung quanh.

Định tuyến yêu cầu

Vai trò đầu tiên — bộ định tuyến. Gateway nhận yêu cầu MCP và, dựa trên nội dung, ngữ cảnh người dùng và cấu hình của chính nó, chọn dịch vụ đích.

Ví dụ, trong GiftGenius có thể có một bảng định tuyến đơn giản:

const TOOL_ROUTES: Record<string, "gift" | "commerce" | "analytics"> = {
  suggest_gifts: "gift",
  get_similar_gifts: "gift",
  checkout_start: "commerce",
  get_order_status: "commerce",
  log_event: "analytics",
};

Và sau đó dùng nó:

function pickBackend(req: McpRequest, ctx: GatewayContext): Backend {
  if (req.method === "tools/list") return "aggregator";
  if (req.method === "tools/call") {
    const toolName = req.params?.name;
    const group = TOOL_ROUTES[toolName] ?? "gift";
    return group === "commerce" ? commerceBackend : giftBackend;
  }
  return giftBackend;
}

Trong trường hợp của chúng ta, giftBackend, commerceBackend, analyticsBackend — là các REST service thông thường: mỗi service có một base URL ("https://gift-api.internal", "https://commerce-api.internal", …). Gateway không đẩy MCP vào bên trong, nó chuyển lời gọi MCP thành yêu cầu HTTP tới đúng REST endpoint.

Xác thực và phân quyền ở rìa (perimeter)

Chức năng quan trọng thứ hai — bảo vệ perimeter. Gateway là nơi thuận tiện để kiểm tra token, xác định người dùng là ai, đến từ tổ chức nào và có quyền gì.

Nó có thể, ví dụ, nhận OAuth token từ ChatGPT hoặc từ MCP Auth server của bạn, xác thực (tốt nhất dùng thư viện tin cậy thay vì tự làm crypto) và chuyển thành một đối tượng context gọn gàng:

type GatewayContext = {
  userId: string | null;
  tenantId: string | null;
  locale: string;
};

function buildContextFromHeaders(req: Request): GatewayContext {
  const token = req.headers["authorization"]; // "Bearer ..."
  const claims = token ? verifyJwt(token) : null;

  return {
    userId: claims?.sub ?? null,
    tenantId: claims?.tenant ?? null,
    locale: (req.headers["x-openai-locale"] as string) || "en-US",
  };
}

Khi đó các backend/REST service bên trong không cần bận tâm parse header HTTP thô và token nữa, mà nhận sẵn context đã chuẩn hoá với userId, tenantIdlocale. Khuyến nghị từ tài liệu MCP nói rõ: đừng tự xây xác thực token từ đầu, hãy dùng thư viện đã kiểm chứng và token sống ngắn.

Ghi log, tracing và metrics

Vai trò thứ ba — quan sát (observability). Gateway nhìn thấy mọi yêu cầu MCP vào và mọi phản hồi, vì vậy đây là nơi lý tưởng để gắn correlation id, ghi log tham số công cụ (không gồm dữ liệu nhạy cảm), lưu thời gian phản hồi và status.

Ý tưởng tối giản:

app.use((req, res, next) => {
  const requestId = crypto.randomUUID();
  (req as any).requestId = requestId;

  const start = Date.now();
  res.on("finish", () => {
    const ms = Date.now() - start;
    console.log(
      `[${requestId}] ${req.method} ${req.url} -> ${res.statusCode} in ${ms}ms`
    );
  });

  next();
});

Sau này trong module về observability, bạn sẽ gửi dữ liệu này không chỉ vào console.log mà vào kho dữ liệu có cấu trúc và dựng dashboard từ đó.

Kiểm soát tải cơ bản

Nhiệm vụ thứ tư nhưng cũng quan trọng — kiểm soát tải sơ bộ. Ở gateway tiện đặt bộ đếm lời gọi theo người dùng, tổ chức, công cụ và endpoint để không cho một client “điên cuồng” đốt cháy cluster và ngân sách mô hình của bạn.

Trong module này ta mới chỉ chốt ý tưởng: rate limiting và hàng đợi sống ở tầng gateway, còn chi tiết triển khai (Redis, token bucket, leaky bucket) sẽ bàn trong bài tiếp theo về bảo vệ perimeter.

Làm giàu yêu cầu bằng ngữ cảnh

Cuối cùng, gateway là nơi tốt để biến ngữ cảnh thô của MCP client thành các tham số gọn gàng cho công cụ nội bộ.

Ví dụ, ChatGPT có thể truyền locale người dùng qua openai/locale_meta["openai/userLocation"]. Gateway có thể:

  • chọn dịch vụ theo khu vực phù hợp (máy chủ ru, máy chủ en, v.v.);
  • thêm locale vào tham số lời gọi tool, ngay cả khi bản thân công cụ không yêu cầu tường minh trong JSON Schema (ví dụ, như một trường không bắt buộc).

Ví dụ đơn giản:

function enrichToolArgs(args: any, ctx: GatewayContext) {
  return {
    ...args,
    locale: args.locale ?? ctx.locale,
    tenantId: ctx.tenantId,
  };
}

Kết quả là Gift API nhận ngay “ngữ cảnh giàu” và có thể, chẳng hạn, lấy mô tả quà tặng tiếng Nga cho "ru-RU" và tiếng Anh cho "en-US".

5. MCP Gateway KHÔNG nên làm gì

Khi dev có một “chỗ ma thuật mà mọi thứ đều đi qua”, rất dễ nảy ra ý định nhét vào đó tất cả những gì vốn thuộc các dịch vụ riêng. Như vậy gateway có nguy cơ biến thành quái vật.

Có một vài thứ nhìn chung không nên sống ở lớp này.

Thứ nhất, logic nghiệp vụ phức tạp. Gợi ý quà tặng, quy tắc giảm giá, tính phí giao hàng, logic ACP — tất cả nên nằm trong các dịch vụ backend/commerce chuyên biệt. Gateway tối đa chỉ nên làm kiểm tra nhẹ (ví dụ đảm bảo giá không âm), chứ không chọn SKU hay tính thuế theo vùng.

Thứ hai, trạng thái người dùng sống lâu. Gateway là dịch vụ stateless điển hình. Nó cần scale ngang dễ dàng, không phụ thuộc bộ nhớ cục bộ và có thể khởi động lại không để lại hậu quả. Nếu bạn bắt đầu lưu trong nó, ví dụ trạng thái wizard checkout hay nội dung giỏ hàng tạm, bạn sẽ nhanh chóng đau đầu với đồng bộ giữa các instance.

Thứ ba, các chức năng đặc thù hợp lý hơn khi đặt trong chính backend service (Gift API, Commerce API). Ví dụ, nếu Gift backend muốn cache kết quả tìm quà, hãy để chính nó làm (có thể dùng Redis). Gateway không cần biết tối ưu nội bộ đó. Chúng ta sẽ nói riêng về bảo vệ perimeter, và ở đó nhấn mạnh: gateway là về chức năng mạng và liên dịch vụ, không phải quy tắc khuyến nghị nghiệp vụ.

Thứ tư, tính toán nặng. Nếu bên trong gateway bạn bắt đầu gọi mô hình LLM, làm biến đổi và tổng hợp phức tạp, nó sẽ không còn là “mặt trước nhẹ” mà trở thành một backend dày nữa — khó scale và khó debug.

6. Gateway, bản địa hóa và phiên bản dịch vụ

Chúng ta đã bàn các trách nhiệm cơ bản của gateway và những thứ không nên nhét vào nó. Giờ nhìn vào hai bài toán “nâng cao” phổ biến, phù hợp giải ở lớp này: bản địa hóa và versioning dịch vụ. Một vai trò thú vị khác của gateway — định tuyến thông minh theo locale và phiên bản dịch vụ.

Khi ChatGPT gọi App của bạn, nó đã có thông tin về ngôn ngữ người dùng (openai/locale) và, thường là, vị trí địa lý (_meta["openai/userLocation"]). Gateway có thể dùng thông tin này để gửi yêu cầu tới backend phù hợp.

Ví dụ, có thể xây kiến trúc “một gateway — nhiều backend đơn ngôn ngữ”:

  • ru-Gift API — chỉ catalog và nội dung tiếng Nga.
  • en-Gift API — chỉ tiếng Anh.
  • jp-Gift API — tiếng Nhật (khi bạn sẵn sàng chinh phục thế giới).

Trong trường hợp này, gateway đóng vai MCP server cho ChatGPT và dựa vào localeuserLocation để chọn dịch vụ nội bộ phù hợp.

Ví dụ đơn giản:

function pickGiftBackendByLocale(ctx: GatewayContext): Backend {
  if (ctx.locale.startsWith("ru")) return giftRuBackend;
  if (ctx.locale.startsWith("ja")) return giftJpBackend;
  return giftEnBackend;
}

Cũng tại đây tiện triển khai định tuyến canary đơn giản. Trong module về kiến trúc production, chúng tôi đề xuất dùng gateway để gửi một phần lưu lượng sang cluster dịch vụ mới, phần còn lại vẫn ở cluster cũ.

Ví dụ canary rất thô:

function pickGiftBackendCanary(ctx: GatewayContext): Backend {
  const hash = hashUser(ctx.userId ?? "anonymous");
  const bucket = hash % 100;
  return bucket < 5 ? giftBackendV2 : giftBackendV1; // 5% lưu lượng đi tới v2
}

Như vậy có thể triển khai an toàn phiên bản mới của Gift API, theo dõi metric và lỗi, mà không làm vỡ toàn bộ production ngay lập tức.

7. Kiến trúc điển hình: từ “tất cả trong một” đến Gateway

Trước đó trong khóa học, bạn đã thấy vài biến thể kiến trúc production cho ChatGPT App. Trong module này, chúng tôi tách ra ba topology cơ bản, đủ dùng cho 90% trường hợp.

Thứ nhất — “tất cả trong một”. Widget App (Next.js), MCP server, logic Agents và commerce backend đơn giản cùng sống trong một dịch vụ, thường một repository và thậm chí một ứng dụng Vercel. Ưu điểm — gần như không cần DevOps, deploy đơn giản, độ trễ tối thiểu. Nhược điểm — khó scale từng phần, một tính năng “nóng” có thể làm sập cả ứng dụng, và ranh giới giữa các thành phần mờ nhạt.

Thứ hai — App + MCP Gateway + nhiều backend service. Ở đây widget Next.js sống riêng (ví dụ trên Vercel), và toàn bộ lưu lượng MCP đi qua Gateway, nơi định tuyến tới Gift REST API, Commerce REST API, dịch vụ Agents, ACP backend và các thành phần khác. Đây chính là sơ đồ chúng ta đang phân tích cho GiftGenius và phù hợp với 90% case production thực tế.

Thứ ba — tương tự, nhưng ở nhiều vùng (multi-region), với bộ cân bằng toàn cầu phía trước gateway. Khi đó người dùng ở châu Âu vào cụm eu, ở Mỹ vào cụm us, và mỗi vùng được xây theo sơ đồ “Gateway + nhiều backend service”. Đây là câu chuyện cho các dự án lớn với người dùng toàn cầu.

Điều quan trọng với chúng ta lúc này không phải ghi nhớ mọi biến thể, mà là quen tư duy gateway như một thành phần kiến trúc riêng, ngay cả khi giai đoạn đầu vai trò đó do một MCP monolith hoặc backend của App đảm nhiệm.

8. MCP Gateway chạy ở đâu (thực tế)

Tin vui: MCP Gateway không nhất thiết phải là một dịch vụ khổng lồ riêng chạy trên Kubernetes. Thường nó sẽ trải qua vài giai đoạn trưởng thành.

Ở quy mô nhỏ nhất, MCP server có thể tự đảm nhiệm vai trò gateway. Khi đó bạn chỉ cần cấu trúc code cẩn thận: tách định tuyến, xác thực và ghi log vào một module, còn logic công cụ vào các module khác. Trong module này chúng tôi ghi rõ rằng trong hệ thống nhỏ, chức năng gateway có thể ở trong MCP server hoặc phần backend của App (ví dụ, trong Next.js API route).

Bước tiếp theo — một dịch vụ Node/TypeScript riêng. Đó có thể là ứng dụng Express/Fastify lắng nghe "/mcp" và gọi vào bên trong tới vài HTTP service. Với nhiều team, đây là lựa chọn thoải mái: phù hợp với công cụ DevOps quen thuộc.

Bộ khung tối giản của dịch vụ như vậy:

const app = express();
app.use(express.json());

app.post("/mcp", handleMcpRequest); // toàn bộ “phép màu” gateway ở đây

app.listen(4000, () => {
  console.log("MCP Gateway listening on :4000");
});

Ở giai đoạn trưởng thành hơn nữa, gateway có thể triển khai trên các giải pháp managed: AWS API Gateway, Cloudflare Workers/Routes, NGINX/Envoy với cấu hình routing và script Lua/JS. Quan trọng là hiểu đây là thay đổi về cách triển khai, không phải khái niệm. Về mặt kiến trúc, ChatGPT vẫn gọi vào một điểm duy nhất, và mọi chi tiết do gateway xử lý.

9. Ví dụ mini: MCP Gateway đơn giản cho GiftGenius

Chúng ta đã lần lượt xem xét định tuyến, ngữ cảnh và xử lý tools/list. Giờ ghép tất cả lại thành một ví dụ nhỏ, rõ ràng. Giả sử ta có hai REST service nội bộ:

  • GIFT_API_BASE = "https://gift-api.internal";
  • COMMERCE_API_BASE = "https://commerce-api.internal".

Và một gateway, nơi ChatGPT sẽ gọi tới địa chỉ "https://gateway.giftgenius.com/mcp".

Trước tiên định nghĩa vài kiểu:

type Backend = "gift" | "commerce";

type ToolRoute = {
  backend: Backend;
  method: "GET" | "POST";
  path: string;
};

const TOOL_ROUTES: Record<string, ToolRoute> = {
  suggest_gifts: {
    backend: "gift",
    method: "POST",
    path: "/api/gifts/suggest",
  },
  checkout_start: {
    backend: "commerce",
    method: "POST",
    path: "/api/checkout/start",
  },
  get_order_status: {
    backend: "commerce",
    method: "GET",
    path: "/api/orders/status",
  },
};

Tiếp theo triển khai chọn backend và gọi:

async function callBackend(toolName: string, mcpReq: McpRequest, ctx: GatewayContext) {
  const route = TOOL_ROUTES[toolName];
  if (!route) {
    throw new Error(`Unknown tool: ${toolName}`);
  }

  const base =
    route.backend === "gift" ? GIFT_API_BASE : COMMERCE_API_BASE;

  const url = base + route.path;

  // args đến trong lời gọi MCP tools/call
  const args = {
    ...(mcpReq.params?.arguments ?? {}),
    locale: ctx.locale,
  };

  const res = await fetch(url, {
    method: route.method,
    headers: { "content-type": "application/json" },
    body: route.method === "POST" ? JSON.stringify(args) : undefined,
  });

  const data = await res.json();

  // Bọc phản hồi REST service thành phản hồi MCP
  return {
    result: data,
  } satisfies McpResponse;
}

Và cuối cùng, trình xử lý chính, nơi:

  1. Xây context từ header (auth, locale).
  2. Chọn backend.
  3. Hoặc tổng hợp tools/list, hoặc proxy tools/call.
app.post("/mcp", async (req, res) => {
  const mcpReq = req.body as McpRequest;
  const ctx = buildContextFromHeaders(req);

  if (mcpReq.method === "tools/list") {
    // Gateway tự khai báo các công cụ và schema của chúng
    const tools = [
      {
        name: "suggest_gifts",
        description: "Gợi ý quà tặng theo ngân sách và sở thích.",
        inputSchema: { /* ... JSON Schema ... */ },
      },
      {
        name: "checkout_start",
        description: "Tạo bản nháp đơn hàng và khởi động checkout.",
        inputSchema: { /* ... */ },
      },
      // ...
    ];

    return res.json({ result: { tools } });
  }

  if (mcpReq.method === "tools/call") {
    const toolName = mcpReq.params?.name;
    const backendRes = await callBackend(toolName, mcpReq, ctx);
    return res.json(backendRes);
  }

  res.status(400).json({ error: { message: "Unsupported MCP method" } });
});

Dĩ nhiên đây là sơ đồ giản lược, nhưng nó đã thể hiện các ý chính:

  • gateway không biết Gift API gợi ý quà tặng như thế nào;
  • nó chỉ định tuyến gọn gàng, làm giàu tham số và, nếu muốn, ghi log và áp hạn mức lời gọi.

10. Tất cả điều này liên quan gì tới các chủ đề tiếp theo của module

MCP Gateway là phần nền tảng cho mọi thứ chúng ta sẽ bàn trong các bài còn lại của module:

  • Ở chủ đề kế tiếp, ta sẽ nói về bảo vệ perimeter: rate limiting, hàng đợi và backpressure. Tất cả chủ yếu sống ở tầng gateway, vì chính nó nhìn thấy toàn bộ lưu lượng vào và có thể “cắt bớt phần thừa” trước khi yêu cầu làm ngập backend.
  • Tiếp đó là khả năng chịu lỗi: timeouts, circuit breaker, bulkhead. Gateway là điểm tiện để đặt timeout tập trung cho các lời gọi ra ngoài và bật/tắt những dịch vụ có vấn đề (ví dụ, tạm “ngắt” Commerce API nếu nó đang lỗi nhiều).
  • Cuối cùng, khi nói về scale và deploy, chúng ta sẽ xem gateway như một cụm riêng có thể cân bằng tải, triển khai theo mô hình blue/green và canary, và rollback độc lập với các MCP service bên trong.

Thực chất, nếu trước đây bạn nghĩ “mình có App và MCP server”, thì giờ sơ đồ mở rộng thành “mình có App, MCP Gateway, vài cụm backend/Agents và commerce backend”. Và chính gateway cho phép không làm phức tạp cấu hình cho ChatGPT — nó vẫn chỉ thấy một điểm MCP duy nhất.

11. Lỗi thường gặp khi làm việc với MCP Gateway

Lỗi số 1: biến gateway thành “quái vật nghiệp vụ”.
Cái bẫy phổ biến: vì mọi thứ đi qua gateway, sao không thêm tính toán giảm giá, chọn SKU, quy tắc danh mục phức tạp hay xác thực mã khuyến mại. Kết quả là một dịch vụ “béo” khó scale và khó thay đổi, đồng thời mất ý nghĩa tách Gift API, Commerce API và các thành phần chuyên biệt khác. Hãy giữ gateway là lớp mạng mỏng, còn mọi thứ đặc thù miền nên ở các service chuyên trách.

Lỗi số 2: lưu trạng thái người dùng sống lâu trong gateway.
Ý tưởng “hãy lưu giỏ hàng của người dùng ngay trong bộ nhớ gateway” nghe hấp dẫn khi bạn chỉ có một instance. Nhưng khi có instance thứ hai, nỗi đau bắt đầu: giỏ hàng thật ở A hay B? Sau khi khởi động lại thì sao? Gateway nên stateless: tối đa có cache nhỏ cho handshake hoặc config, còn mọi trạng thái phiên và đơn hàng lưu trong DB hoặc dịch vụ chuyên biệt.

Lỗi số 3: làm ChatGPT biết topology nội bộ của dịch vụ.
Nếu bạn bắt đầu đưa thẳng nhiều API server vào ChatGPT (Gift API riêng, Commerce API riêng), còn gateway chỉ dùng “chỗ này chỗ kia”, bạn mất lợi thế chính: điểm vào thống nhất và kiểm soát tập trung. Khi đổi topology, sẽ phải sửa cấu hình ở nhiều nơi. Dễ hơn nhiều nếu cấu hình MCP Gateway làm endpoint chính thức cho App và ẩn mọi thay đổi nội bộ phía sau nó.

Lỗi số 4: nhân bản logic liên dịch vụ ở mọi backend.
Đôi khi các team cố triển khai xác thực, rate limiting, ghi log và bản địa hóa trong từng REST service riêng lẻ. Kết quả là chính sách quyền và hạn mức ở Gift API một kiểu, ở Commerce API kiểu khác, và hành vi App trở nên khó đoán. Gateway sinh ra để tập trung các việc này: kiểm tra token, xác định tenant và locale, ghi log lời gọi, áp hạn mức, rồi mới đi tới dịch vụ cụ thể.

Lỗi số 5: chất lên gateway các tính toán nặng và lời gọi LLM.
Về mặt kỹ thuật chẳng ai ngăn bạn gọi thêm một mô hình LLM từ gateway, làm tổng hợp phức tạp hay các batch job dài. Nhưng điều đó sẽ nhanh chóng biến nó thành một backend dày khác, không thể scale và cô lập tốt. Gateway nên nhẹ và dự đoán được: tối đa là biến đổi nhẹ và định tuyến. Mọi thứ nặng — đưa vào REST service hoặc hàng đợi/worker (sẽ bàn thêm sau trong module).

Lỗi số 6: phức tạp hóa hạ tầng quá sớm.
Cực đoan ngược lại — ngay lập tức dựng cluster Kubernetes riêng, stack NGINX, Cloudflare Workers và một đống cấu hình phức tạp cho một App học tập nhỏ. Điều này vô nghĩa khi bạn chưa có tải thực và yêu cầu cao về sẵn sàng. Hoàn toàn ổn khi bắt đầu với một MCP monolith hoặc một Node gateway đơn giản, rồi sau đó, khi tăng trưởng, mới tách dần thành các cụm và dịch vụ managed.

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION