kong網關基于header分流灰度發布

kong網關基于header分流灰度發布

在現代微服務架構中,灰度發布(Canary Release)已經成為一種常用且安全的上線策略。它允許我們將新版本的功能僅暴露給一小部分用戶,從而在保證系統穩定性的同時收集反饋、驗證效果、規避風險。而作為一款輕量高性能的 API 網關,Kong 提供了靈活的路由規則,使得我們可以通過配置請求頭、Cookie、路徑等條件,實現基于規則的流量分流。

本文將聚焦于一種實用的灰度發布方案:基于請求頭(Header)進行流量分發。我們將以 X-App-Version 等請求頭為判斷依據,將部分請求引導至灰度環境(如 backend-v2),其余流量仍然指向正式環境(backend-v1)。通過 Kong 的聲明式配置方式,可以輕松實現無數據庫、無插件依賴的灰度發布策略,特別適合前后端聯調、測試環境驗證以及輕量化場景。

在這里插入圖片描述

本篇文章將從實際業務需求出發,介紹如何使用 Kong 網關進行權重分流的灰度發布,包括:

  • Kong 中實現header分流的配置;

  • 如何基于 Docker Compose 部署一個 DB-less 模式的灰度發布環境;

  • 配置示例講解:如何將v2流量導向新版本服務 backend-v2,v1保持在舊版本 backend-v1;

前置條件

節點規劃如下:

主機名節點IP監聽端口操作系統
frontend192.168.73.118080Ubuntu 24.04
backend-v1192.168.73.113001Ubuntu 24.04
backend-v2192.168.73.113002Ubuntu 24.04
kong-gateway192.168.73.118000Ubuntu 24.04

已安裝 Docker 和 docker-compose工具。

無DB模式部署kong網關

創建kong.yml聲明式配置文件:

root@ubuntu:/data/apps/kong# cat kong.yml 
_format_version: "3.0"services:- name: backend-serviceurl: http://backend-v1:3000- name: backend-service-grayurl: http://backend-v2:3000routes:- name: backend-route-grayservice: backend-service-graypaths:- /adminheaders:X-App-Version:- v2strip_path: false- name: backend-routeservice: backend-servicepaths:- /adminstrip_path: falseplugins:- name: corsconfig:origins:- "*"methods:- GET- POST- PUT- DELETE- OPTIONSheaders:- Accept- Authorization- Content-Type- X-Requested-With- X-App-Versionexposed_headers:- X-Custom-Headercredentials: truemax_age: 3600

配置參數說明:

好的,以下是你提供的這份 Kong 聲明式配置(kong.yml)的逐項參數詳解,特別聚焦于灰度發布與 CORS 支持相關部分:


_format_version: "3.0"

  • 說明:聲明配置文件的格式版本,Kong 3.x 需要為 "3.0"
  • 作用:Kong 用來解析聲明式配置,必須寫。

services

定義了兩個后端服務(一個正式,一個灰度):

  1. backend-service
- name: backend-serviceurl: http://backend-v1:3000
  • name:服務名稱,用于 route 映射。
  • url:實際后端地址,這里是正式環境 backend-v1 的 3000 端口。
  • 備注:省略了 host/port/protocol 的寫法,直接用 url 更簡潔。
  1. backend-service-gray
- name: backend-service-grayurl: http://backend-v2:3000
  • 同上,只不過這是灰度環境的服務地址(backend-v2)。

routes

定義了兩條路由規則,基于路徑和請求頭進行分流:

  1. backend-route-gray
- name: backend-route-grayservice: backend-service-graypaths:- /adminheaders:X-App-Version:- v2strip_path: false
  • name:路由名稱。
  • service:綁定到灰度服務 backend-service-gray
  • paths:匹配 /admin 路徑的請求。
  • headers:匹配請求頭 X-App-Version: v2 的請求。
  • strip_path:為 false 表示保留 /admin 前綴,不會從請求 URL 中剝離。
  1. backend-route
- name: backend-routeservice: backend-servicepaths:- /adminstrip_path: false
  • 匹配 /admin 的默認路由,綁定到正式服務 backend-service
  • 沒有 header 限制,所有不匹配前面 route 的請求都會走這個。

?? 匹配順序重要backend-route-gray 必須在前面,Kong 按順序匹配 route,先匹配成功的就執行,后面的不再判斷。


plugins

配置了全局的 CORS(跨域資源共享)插件:

- name: corsconfig:origins:- "*"methods:- GET- POST- PUT- DELETE- OPTIONSheaders:- Accept- Authorization- Content-Type- X-Requested-With- X-App-Versionexposed_headers:- X-Custom-Headercredentials: truemax_age: 3600

參數說明:

參數說明
origins允許哪些源(Origin)跨域訪問。* 表示全部允許
methods允許的 HTTP 方法
headers允許客戶端請求時攜帶的請求頭(包括自定義的如 X-App-Version
exposed_headers響應中暴露給前端的響應頭
credentials是否允許攜帶 Cookie、認證信息等
max_age預檢請求(OPTIONS)結果緩存時間(秒)

最終請求 http://kong網關/admin

  • 如果帶 X-App-Version: v2 請求頭 → 進入 灰度服務
  • 如果不帶或值不為 v2 → 進入 正式服務
  • 啟用了全局的 CORS 支持,適合 Web 前端跨域請求調用 API

創建docker外部網絡,打通kong網關與前后端服務網絡

docker network create app_network

創建部署kong網關的docker-compose.yaml

root@ubuntu:/data/apps/kong# cat docker-compose.yaml
name: 'kong-gateway'services:kong:image: kong:3.9.1container_name: kong-gatewayrestart: alwaysenvironment:KONG_DATABASE: "off"KONG_DECLARATIVE_CONFIG: /usr/local/kong/declarative/kong.yml# kong proxyKONG_PROXY_LISTEN: 0.0.0.0:8000KONG_PROXY_LISTEN_SSL: 0.0.0.0:8443# kong adminKONG_ADMIN_LISTEN: 0.0.0.0:8001, 0.0.0.0:8444 ssl# kong managerKONG_ADMIN_GUI_LISTEN: 0.0.0.0:8002, 0.0.0.0:8445 ssl# kong logsKONG_PROXY_ACCESS_LOG: /dev/stdoutKONG_PROXY_ERROR_LOG: /dev/stderrKONG_ADMIN_ACCESS_LOG: /dev/stdoutKONG_ADMIN_ERROR_LOG: /dev/stderrports:- "8000:8000" # Proxy- "8443:8443" # Proxy SSL- "8001:8001" # Admin API- "8444:8444" # Admin API SSL- "8002:8002" # Kong Manager- "8445:8445" # Kong Manager SSLvolumes:- .kong.yml:/usr/local/kong/declarative/kong.ymlnetworks:- app-nethealthcheck:test: ["CMD-SHELL", "kong health"]interval: 15stimeout: 10sretries: 3networks:app-net:external: truename: app_network

啟動kong網關

docker compose up -d

查看服務運行狀態

root@ubuntu:/data/apps/kong# docker compose ps
NAME           IMAGE        COMMAND                  SERVICE   CREATED          STATUS                    PORTS
kong-gateway   kong:3.9.1   "/docker-entrypoint.…"   kong      31 seconds ago   Up 31 seconds (healthy)   0.0.0.0:8000-8002->8000-8002/tcp, [::]:8000-8002->8000-8002/tcp, 0.0.0.0:8443-8445->8443-8445/tcp, [::]:8443-8445->8443-8445/tcp
root@ubuntu:/data/apps/kong# 

訪問kong manager查看創建的轉發規則
Gateway Services
在這里插入圖片描述

Routes
在這里插入圖片描述

Plugins
在這里插入圖片描述

部署前后端服務

示例 Canaryheader 是一個基于Kong網關和docker-compose的Web端灰度發布演示項目,支持基于百分比的流量灰度策略。

架構如下:
在這里插入圖片描述

主要特性

  • 前端:html/js,展示后端返回的版本信息
  • 后端:Node.js (Express),分別為v1和v2版本
  • Kong網關:流量分流、服務注冊、路由配置,支持基于header灰度
  • 容器化:所有服務均為Docker容器
  • 一鍵部署:docker-compose編排

目錄結構

canaryheader/
├── docker-compose.yml
├── backend-v1/
│   ├── Dockerfile
│   └── index.js           # v1后端代碼
├── backend-v2/
│   ├── Dockerfile
│   └── index.js           # v2后端代碼
├── frontend/
│   ├── Dockerfile
│   └── index.html

backend-v1/index.js

root@ubuntu:/data/git/canary-header-app# cat backend-v1/index.js 
const express = require('express');
const app = express();
app.get('/admin', (req, res) => {res.json({ version: 'v1', message: 'Hello from backend v1!' });
});
app.listen(3000, () => console.log('Backend v1 running on 3000'));

backend-v1/Dockerfile

root@ubuntu:/data/git/canary-header-app# cat backend-v1/Dockerfile 
FROM node:24-alpine
WORKDIR /app
COPY index.js ./
RUN npm config set registry https://registry.npmmirror.com && \npm init -y && \npm install express
EXPOSE 3000
CMD ["node", "index.js"] 

backend-v2/index.js

root@ubuntu:/data/git/canary-header-app# cat backend-v2/index.js 
const express = require('express');
const app = express();
app.get('/admin', (req, res) => {res.json({ version: 'v2', message: 'Hello from backend v2!' });
});
app.listen(3000, () => console.log('Backend v2 running on 3000'));

backend-v2/Dockerfile

root@ubuntu:/data/git/canary-header-app# cat backend-v2/Dockerfile 
FROM node:24-alpine
WORKDIR /app
COPY index.js ./
RUN npm config set registry https://registry.npmmirror.com && \npm init -y && \npm install express
EXPOSE 3000
CMD ["node", "index.js"] 

frontend/index.html

root@ubuntu:/data/git/canary-header-app# cat frontend/index.html 
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8" /><title>Canary Flow</title><style>body {font-family: Arial, sans-serif;max-width: 600px;margin: 0 auto;padding: 20px;}.test-section {margin: 20px 0;padding: 15px;border: 1px solid #ddd;border-radius: 5px;}button {margin: 5px;padding: 10px 15px;background-color: #007bff;color: white;border: none;border-radius: 3px;cursor: pointer;}button:hover {background-color: #0056b3;}pre {background-color: #f8f9fa;padding: 10px;border-radius: 3px;white-space: pre-wrap;}.version-v1 { color: #28a745; font-weight: bold; }.version-v2 { color: #dc3545; font-weight: bold; }</style>
</head>
<body><h1>Canary Flow 灰度發布演示</h1><div class="test-section"><h3>灰度規則測試</h3><p>基于請求頭 <code>X-App-Version</code> 的簡單灰度規則:</p><ul><li><strong>X-App-Version: v2</strong> → 路由到 Backend v2</li><li><strong>無請求頭或其他值</strong> → 路由到 Backend v1</li></ul></div><div class="test-section"><h3>測試按鈕</h3><button onclick="fetchData()">默認請求 (v1)</button><button onclick="fetchDataWithVersion('v2')">使用 v2 版本</button><button onclick="fetchDataWithVersion('v1')">強制使用 v1</button></div><pre id="output">點擊按鈕開始測試...</pre><script>async function fetchData() {try {const res = await fetch("http://192.168.73.11:8000/admin");const data = await res.json();displayResult(data, "默認請求(無請求頭)");} catch (error) {document.getElementById("output").innerText = "錯誤: " + error.message;}}async function fetchDataWithVersion(version) {try {const res = await fetch("http://192.168.73.11:8000/admin", {headers: {'X-App-Version': version}});const data = await res.json();displayResult(data, `X-App-Version: ${version}`);} catch (error) {document.getElementById("output").innerText = "錯誤: " + error.message;}}function displayResult(data, requestInfo = "") {const output = document.getElementById("output");const versionClass = data.version === 'v1' ? 'version-v1' : 'version-v2';const timestamp = new Date().toLocaleTimeString();output.innerHTML = `
請求信息: ${requestInfo}
時間: ${timestamp}
版本: <span class="${versionClass}">${data.version}</span>
消息: ${data.message}`;}</script>
</body>
</html>

說明:前端直接通過kong網關接口http://192.168.73.11:8000/admin調用后端服務。

frontend/Dockerfile

root@ubuntu:/data/git/canary-header-app# cat frontend/Dockerfile 
FROM nginx:alpine
RUN rm -rf /usr/share/nginx/html/*
COPY index.html /usr/share/nginx/html/

docker-compose.yaml

root@ubuntu:/data/git/canary-header-app# cat docker-compose.yml 
name: 'canary-flow-app'services:frontend:build: ./frontendimage: registry.cn-shenzhen.aliyuncs.com/cnmirror/canary-header-frontend:v1.0container_name: canary-frontendports:- "8080:80"networks:- app-netbackend-v1:build: ./backend-v1image: registry.cn-shenzhen.aliyuncs.com/cnmirror/canary-header-backend-v1:v1.0container_name: canary-backend-v1ports:- "3001:3000"networks:- app-netbackend-v2:build: ./backend-v2image: registry.cn-shenzhen.aliyuncs.com/cnmirror/canary-header-backend-v2:v1.0container_name: canary-backend-v2ports:- "3002:3000"networks:- app-netnetworks:app-net:external: truename: app_network

啟動前后端服務

構建鏡像

docker compose build

啟動服務

docker compose up -d

查看服務運行狀態

root@ubuntu:/data/git/canary-header-app# docker compose ps
NAME                IMAGE                                                                    COMMAND                  SERVICE      CREATED          STATUS          PORTS
canary-backend-v1   registry.cn-shenzhen.aliyuncs.com/cnmirror/canary-flow-backend-v1:v1.0   "docker-entrypoint.s…"   backend-v1   10 minutes ago   Up 10 minutes   0.0.0.0:3001->3000/tcp, [::]:3001->3000/tcp
canary-backend-v2   registry.cn-shenzhen.aliyuncs.com/cnmirror/canary-header-backend-v2:v1.0   "docker-entrypoint.s…"   backend-v2   10 minutes ago   Up 10 minutes   0.0.0.0:3002->3000/tcp, [::]:3002->3000/tcp
canary-frontend     registry.cn-shenzhen.aliyuncs.com/cnmirror/canary-header-frontend:v1.0     "/docker-entrypoint.…"   frontend     10 minutes ago   Up 10 minutes   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp
root@ubuntu:/data/git/canary-flow-app# 

灰度流量分流

Kong通過routes--headers將流量按header分配到v1和v2后端,實現灰度發布。通過kong網關多次請求接口進行驗證:

root@ubuntu:/data/apps/kong# curl -s -H "X-App-Version: v1" http://192.168.73.11:8000/admin | jq
{"version": "v1","message": "Hello from backend v1!"
}
root@ubuntu:/data/apps/kong# 
root@ubuntu:/data/apps/kong# curl -s -H "X-App-Version: v2" http://192.168.73.11:8000/admin | jq
{"version": "v2","message": "Hello from backend v2!"
}
root@ubuntu:/data/apps/kong# curl -s http://192.168.73.11:8000/admin | jq
{"version": "v1","message": "Hello from backend v1!"
}
root@ubuntu:/data/apps/kong# 

瀏覽器訪問frontend驗證:
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/88204.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/88204.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/88204.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Go語言gin框架原理

在gin框架中&#xff0c;最關鍵的就是前綴樹&#xff0c;是很重要的。gin框架本質上是在http包的基礎之上&#xff0c;對其的一個二次封裝。這里借鑒一下小徐先生的圖&#xff0c;可能當前版本的gin可能內容有所改變&#xff0c;但大致思想還是這樣。gin框架所做的就是提供一個…

4、Sending Messages

本節介紹如何發送消息。Using KafkaTemplate本節介紹如何使用KafkaTemplate發送消息。OverviewKafkaTemplate封裝了一個生產者&#xff0c;并提供了向Kafka主題發送數據的便利方法。以下列表顯示了KafkaTemplate的相關方法&#xff1a;CompletableFuture<SendResult<K, V…

CSS長度單位問題

在 CSS 中&#xff0c;100px 的邏輯長度在不同分辨率的手機屏幕上是否表現一致&#xff0c;取決于 設備的像素密度&#xff08;devicePixelRatio&#xff09; 和 視口&#xff08;viewport&#xff09;的縮放設置。以下是詳細分析&#xff1a;1. 核心概念 CSS 像素&#xff08;…

基于Java+SpringBoot的圖書管理系統

源碼編號&#xff1a;S606源碼名稱&#xff1a;基于SpringBoot的圖書管理系統用戶類型&#xff1a;雙角色&#xff0c;用戶、管理員數據庫表數量&#xff1a;12 張表主要技術&#xff1a;Java、Vue、ElementUl 、SpringBoot、Maven運行環境&#xff1a;Windows/Mac、JDK1.8及以…

XTOM工業級藍光三維掃描儀用于筆記本電腦背板模具全尺寸檢測

鎂合金具有密度小、強度高、耐腐蝕性好等優點&#xff0c;成為筆記本電腦外殼主流材料。沖壓模具作為批量生產筆記本電腦鎂合金背板的核心工具&#xff0c;其精度直接決定了產品的尺寸一致性、結構可靠性與外觀品質。微米級模具誤差可能在沖壓過程中被放大至毫米級&#xff08;…

運維打鐵: MongoDB 數據庫集群搭建與管理

文章目錄思維導圖一、集群基礎概念1. 分片集群2. 副本集二、集群搭建1. 環境準備2. 配置副本集步驟 1&#xff1a;修改配置文件步驟 2&#xff1a;啟動 MongoDB 服務步驟 3&#xff1a;初始化副本集3. 配置分片集群步驟 1&#xff1a;配置配置服務器副本集步驟 2&#xff1a;啟…

HCIP-Datacom Core Technology V1.0_5 OSPF特殊區域及其他特性

在前面的章節中&#xff0c;OSPF可以劃分區域&#xff0c;減輕單區域里面LSDB的規模&#xff0c;從而減輕路由器的負荷&#xff0c;雖然OSPF能夠劃分區域&#xff0c;但是依舊需要維護域間路由和外部路由&#xff0c;這樣隨著網絡規模的不斷擴大&#xff0c;路由器所維護的LSDB…

實時開發IDE部署指南

&#x1f525;&#x1f525; AllData大數據產品是可定義數據中臺&#xff0c;以數據平臺為底座&#xff0c;以數據中臺為橋梁&#xff0c;以機器學習平臺為中層框架&#xff0c;以大模型應用為上游產品&#xff0c;提供全鏈路數字化解決方案。 ?杭州奧零數據科技官網&#xff…

深入解析 RAGFlow:文件上傳到知識庫的完整流程

在 RAGFlow 這樣的檢索增強生成&#xff08;RAG&#xff09;系統中&#xff0c;知識庫是其核心。用戶上傳的文檔如何高效、可靠地轉化為可檢索的知識&#xff0c;是系統穩定運行的關鍵。今天&#xff0c;我們就來深入探討 RAGFlow 中文件上傳到知識庫的完整流程&#xff0c;揭秘…

cad_recognition 筆記

Hubch/cad_recognition | DeepWiki https://github.com/Hubch/cad_recognition winget install python.python.3.10 python -m venv venv micromamba activate ./venv pip install paddleocr2.9.0 pip install poetry pip install moviepy1.0.3 下次要用conda建環境 或者…

基于odoo17的設計模式詳解---構建模式

大家好&#xff0c;我是你的Odoo技術伙伴。在Odoo開發中&#xff0c;創建一個簡單的記錄可能只需要一行 self.env[res.partner].create({name: New Partner})。但如果我們要創建一個復雜的對象&#xff0c;比如一個包含了特定上下文、具有多個可選配置、并且需要執行一系列關聯…

暑假算法日記第四天

目標?&#xff1a;刷完靈神專題訓練算法題單 階段目標&#x1f4cc;&#xff1a;【算法題單】滑動窗口與雙指針 LeetCode題目:2953. 統計完全子字符串1016. 子串能表示從 1 到 N 數字的二進制串其他: 今日總結 往期打卡 2953. 統計完全子字符串 跳轉: 2953. 統計完全子字符串…

Linux 常用命令大全(2025簡明版)

&#x1f9ed; 一、文件和目錄操作命令說明ls列出目錄內容ls -l以列表形式顯示&#xff08;含權限&#xff09;cd /path切換目錄pwd顯示當前路徑mkdir dir創建目錄mkdir -p dir/subdir遞歸創建目錄rm file刪除文件rm -r dir刪除目錄&#xff08;遞歸&#xff09;rm -rf dir強制…

React Ref 指南:原理、實現與實踐

前言 React Ref&#xff08;引用&#xff09;是React中一個強大而重要的概念&#xff0c;它為我們提供了直接訪問DOM元素或組件實例的能力。雖然React推崇聲明式編程和數據驅動的理念&#xff0c;但在某些場景下&#xff0c;我們仍需要直接操作DOM或訪問組件實例。本文將深入探…

4.權重衰減(weight decay)

4.1 手動實現權重衰減 import torch from torch import nn from torch.utils.data import TensorDataset,DataLoader import matplotlib.pyplot as plt def synthetic_data(w,b,num_inputs):Xtorch.normal(0,1,size(num_inputs,w.shape[0]))yXwbytorch.normal(0,0.1,sizey.shap…

OpenCV開發-初始概念

第一章 OpenCV核心架構解析1.1 計算機視覺的基石OpenCV&#xff08;Open Source Computer Vision Library&#xff09;作為跨平臺計算機視覺庫&#xff0c;自1999年由Intel發起&#xff0c;已成為圖像處理領域的標準工具。其核心價值體現在&#xff1a;跨平臺性&#xff1a;支持…

LeetCode 930.和相同的二元子數組

給你一個二元數組 nums &#xff0c;和一個整數 goal &#xff0c;請你統計并返回有多少個和為 goal 的 非空 子數組。 子數組 是數組的一段連續部分。 示例 1&#xff1a; 輸入&#xff1a;nums [1,0,1,0,1], goal 2 輸出&#xff1a;4 解釋&#xff1a; 有 4 個滿足題目要求…

【論文解讀】Referring Camouflaged Object Detection

論文信息 論文題目&#xff1a;Referring Camouflaged Object Detection 論文鏈接&#xff1a;https://arxiv.org/pdf/2306.07532 代碼鏈接&#xff1a;https://github.com/zhangxuying1004/RefCOD 錄用期刊&#xff1a;TPAMI 2025 論文單位&#xff1a;南開大學 ps&#xff1a…

Spring中過濾器和攔截器的區別及具體實現

在 Spring 框架中&#xff0c;過濾器&#xff08;Filter&#xff09; 和 攔截器&#xff08;Interceptor&#xff09; 都是用于處理 HTTP 請求的中間件&#xff0c;但它們在作用范圍、實現方式和生命周期上有顯著區別。以下是詳細對比和實現方式&#xff1a;核心區別特性過濾器…

CANFD 數據記錄儀在新能源汽車售后維修中的應用

一、前言隨著新能源汽車市場如火如荼和新能源汽車電子系統的日益復雜&#xff0c;傳統維修手段在面對復雜和偶發故障時往往捉襟見肘&#xff0c;CANFD 數據記錄儀則憑借其獨特優勢&#xff0c;為售后維修帶來新的解決方案。二、 詳細介紹在新能源汽車領域&#xff0c;CANFD 數據…