全部产品
Search
文档中心

API 网关:后端路由

更新时间:Apr 09, 2024

Routing插件具备根据请求的参数取值与系统参数取值,变更后端地址、路径、参数或类型的能力。可以用于租户路由,蓝绿发布,不同环境的区分等场合。

1. 概述

Routing插件具备根据请求的参数取值与系统参数取值,变更后端地址、路径、参数或类型的能力。可以用于租户路由,蓝绿发布,不同环境的区分等场合。

1. 配置方式

1.1 配置模板

可以选择JSON或者YAML格式的来配置您的插件,两种格式的schema相同,可以搜索yaml to json转换工具来进行配置格式的转换,yaml格式的模板见下表。

---
routes:
# 当调用方的AppId为"123456"时, 路由至独立的地址, 例子中指定了VPC授权名为"slbAddressForVip"的地址
- name: Vip
  condition: "$CaAppId = 123456"
  backend:
    type: "HTTP-VPC"
    vpcAccessName: "slbAccessForVip"
# 针对太老的客户端, 返回不再支持的应答, ClientVersion是API中的自定义参数
- name: MockForOldClient
  condition: "$ClientVersion < '2.0.5'"
  backend: 
    type: "MOCK"
    statusCode: 400
    body: "This version is not supported!!!"

配置模板的根对象为routes,包含多个route对象,每个route对象用于指定一条路由,每条路由由以下几个部分组成:

  • name: 表示这个路由的名称,大小写英文字母和数字,在每个插件中保持唯一,如果命中了这条路由,后端收到的请求会包含一个名为X-Ca-Routing-Name的HTTP头,指示本次命中的路由名称

  • condition:路由的条件表达式,条件表达式的规范见本文2.2节中的描述,如果当前的请求符合条件表达式,则本条路由命中,Routing插件会按照插件的配置顺序从上到下进行判断,并将请求路由给命中的第一条记录,并忽略后面的记录,如果您配置了多条路由记录,请仔细检查配置的顺序与您期望的逻辑一致。

  • backend: 后端描述,与API网关的Swagger标准保持一致,后端在原有API的后端上覆盖backend配置后处理,如果覆盖后的backend不完整,会提示客户端X-Ca-Error-Code: I504RB,当看到这个错误时,请检查自己的backend配置是否完整,关于Backend描述,请参照2.3节,Routing插件中的Backend覆盖规则

  • constant-parameters: 可以自行设置路由的常量参数,常量参数会附加在命中路由的后端请求上,用于后端的业务逻辑处理,location支持headerquery

1.2. Condition条件表达式

1.2.1 基本语法

  • Condition表达式与SQL表达式类似,基础表达形式为$A = 'A' and '$B = 'B'

  • 参数以$开头,可以引用在API中定义的参数(API为映射与透传方式均可),如果您在API中定义了名为query1的参数,则$query1可以表示当前请求中的query1参数s

  • 支持以下常量类型:

    • STRING: 字符串类型,支持单引号或双引号,如: "Hello"

    • INTEGER: 整数类型,如:1001,-1

    • NUMBER: 浮点数类型,如: 0.1, 100.0

    • BOOLEAN: 布尔类型,如:true、false

  • 可以使用andor来连接不同的表达式

  • 可以用小括号()来指定条件判断的优先级

  • 可以使用 $CaAppId 形式来引用当前请求的系统参数,系统参数不需要API中被定义即可引用,但如果您在API中定义了重名的参数,取到的值会被自定义参数覆盖,可用于路由插件的系统参数列表如下:

    • CaStage: 当前API请求的环境,RELEASE,PRE,TEST

    • CaDomain: 当前请求的域名

    • CaRequestHandleTime:请求处理的UTC时间

    • CaAppId:请求参数的AppId

    • CaAppKey:请求参数的AppKey

    • CaClientIp:客户端IP

    • CaApiName:创建时候的API名字

    • CaHttpScheme:请求的协议HTTP,HTTPS

    • CaClientUa: 客户端上传的UserAgent字段

  • 如果表达式中使用了不存在的参数,如$UnknonwParameter = 1,则表达式的判断会返回false

1.2.2 条件表达式样例

  • 当前API请求的是测试环境

    $CaStage = 'TEST'

  • 自定义参数中的UserName是Admin且来源IP是47.47.XX.XX

    $UserName = 'Admin' and $CaClientIp = '47.47.XX.XX'

  • 当前请求的用户ID是1001,1098,2011中的一个,且使用HTTPS协议请求

    $CaHttpScheme = 'HTTPS' and ($CaAppId = 1001 or $CaAppId = 1098 or $CaAppId = 2011)

1.3. Backend的定义与覆盖规则

Backend的结构与API网关导入Swagger时的结构一致,详细请参考文档导入API网关的扩展Swagger定义,目前支持的后端类型及配置样例如下,如果插件中不需要变更后端类型,只需要变更部分设置,则不需要填写完整的字段,仅填写需要变更的即可。

重要
  • HTTP

---
backend:
  type: HTTP
  address: "http://10.10.100.2:8000"
  httpTargetHostName: "a.b.com"  # 指定API网关请求后端的域名头(Host),优先级最高
  path: "/users/{userId}"
  method: GET
  timeout: 7000
  • HTTP-VPC

---
backend:
  type: HTTP-VPC
  vpcAccessName: vpcAccess1
  vpcTargetHostName: "a.b.com"  # 指定API网关请求后端的域名头(Host),优先级最高
  vpcScheme: "https"
  path: "/users/{userId}"
  method: GET
  timeout: 10000
  • FC

---
backend:
  type: FC
  fcRegion: cn-shanghai
  fcType: FCEvent
  serviceName: fcService
  functionName: fcFunction
  roleArn: "acs:ram::111111111:role/aliyunapigatewayaccessingfcrole"
backend:
  type: FC
  fcRegion: cn-shenzhen
  method: GET
  fcType: HttpTrigger
  fcUrl: https://1833848375796824.cn-shenzhen.fc.aliyuncs.com/2016-08-15/proxy/servicetest/fctest3/fctest3
  roleArn: acs:ram::1833848375796824:role/aliyunapigatewayaccessingfcrole
  • OSS

---
backend:
  type: OSS
  ossRegionId: cn-hangzhou
  bucketName: bucketName
  key: /objectName
  timeout: 10000
  action: putObject
  • MOCK

---
backend:
  type: MOCK
  mockResult: "mock resul sample"
  mockStatusCode: 200
  mockHeaders:
    - name: server
      value: mock
    - name: proxy
      value: GW

1.4. 权重与分发

将API的请求按权重分发到两个不同的后端服务,权重越高的后端服务将被分发更多的请求。配置示例如下:

---
routes:
# 配置两个后端服务,根据后端服务承载能力不同,分别配置不同的权重,权重越高分发的请求将越多
- name: Backend01
  condition: "1 = 1"  # 1 = 1是条件命中,1 = 0是条件未命中
  weight: 100       # 用来配置后端服务流量分发权重
  backend:
    type: "HTTP"
    address: "https://test01.com"
    path: "/web/cloudapi"
- name: Backend02
  condition: "1 = 1"
  weight: 80
  backend:
    type: "HTTP"
    address: "https://test02.com"
    path: "/web/cloudapi"

重要
  • 命中一个条件,所有流量都会指向命中的后端服务

  • 命中多个条件,按权重分发流量

  • 无命中条件,所有流量都会指向API定义的后端服务

1.5. 限制

  • 插件的文本大小限制为16384字节,超过后会报错InvalidPluginData.TooLarge

  • 单个Routing插件的条数限制为160条,超过后会报错InvalidPluginData.TooManyRoutes 当这个插件绑定至共享实例API时只有前16条生效,绑定至专享实例API时全部生效

  • 单条Condition语句的大小限制为512字节,超过后会报错InvalidPluginData.ConditionTooLong

  • 插件更新会实时生效至所有已绑定该插件的API,插件的更新频率被限制为45秒一次,超出时会报错,InvalidPluginData.UpdateTooBusy

2. 典型应用场景

2.1. 配置租户路由(根据AppId分配不同的后端地址)

AppId为10098,10099的用户是VIP用户,来自这两个用户的请求路由到独立的服务器集群去。配置示例如下:

---
routes:
# 当调用方的AppId为10098或10099时, 路由至独立的地址,
# 例子中指定了VPC授权名为"slbAddressForVip"的地址
- name: Vip
  condition: "$CaAppId = 10098 or $CaAppId = 10099"
  backend:
    type: "HTTP-VPC"
    vpcAccessName: "slbAccessForVip"

2.2. Stage路由(测试/预发/生产环境变更)

正式环境在阿里云的VPC中,但希望将所有访问测试环境的API指向公网测试服务器。配置示例如下:

---
routes:
# 当访问测试环境时, 将路由转向公网服务器
- name: Vip
  condition: "$CaStage = 'TEST'"
  backend:
    type: "HTTP"
    address: "https://test-env.foo.com"

2.3. 蓝绿发布

将5%的流量指向一组beta服务器地址,95%的流量指向VPC类型后端服务。配置示例如下:

---
routes:
# 蓝绿发布场景:将5%的请求路由给蓝绿发布后端,95%的请求路由指向vpc类型后端服务。
- name: BlueGreenPercent05
  condition: "1 = 1"
  weight: 5
  backend:
    type: "HTTP"
    address: "https://beta-version.api.foo.com"
    path: "/web/cloudapi"
  constant-parameters:
  - name: x-route-blue-green
    location: header
    value: "route-blue-green"
- name: BlueGreenPercent95
  condition: "1 = 1"
  weight: 95
  backend:
    type: HTTP-VPC
    path: "/web/cloudapi"
    vpcAccessName: testvpc
说明
  • condition:1 = 1是条件命中,1 = 0是条件未命中。

  • weight:用来配置后端服务流量分发权重。

2.4 一致性哈希算法路由

一致性哈希算法根据不同的哈希因子将访问请求均匀地分配到后端服务。相同哈希因子计算结果的请求,将会调度到相同的后端服务。

后端路由插件支持如下哈希因子:

  • 源IP哈希:根据请求的源IP地址进行哈希计算。相同源IP的请求会分发到同一台后端服务器。

  • 参数哈希:根据请求的参数进行哈希计算。相同参数的请求会分发到同一台后端服务器。

源IP哈希的示例如下:

---
parameters:
  clientIp: "System:CaClientIp"  
routeByHash: clientIp   #指定哈希因子
routes:
- name: route1
  condition: "1 = 1"  # 1 = 1是条件命中,1 = 0是条件未命中
  backend:
    type: "MOCK"
    statusCode: 200
    mockResult: "Hello World!!!"
- name: route2
  condition: "1 = 1"
  backend:
    type: "MOCK"
    statusCode: 400
    mockResult: "mock resul sample"
- name: route3
  condition: "1 = 0"
  backend:
    type: "HTTP"
    address: "https://test.com"
  constant-parameters:
  - name: x-route-by-hash
    location: header
    value: "route-by-hash"