This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

中间件组件规格

可注入 Dapr 处理管道的所有受支持的中间件组件列表。

下表列出了 Dapr 支持的中间件组件。了解如何自定义处理管道和设置中间件组件。

Table headers to note:

HeaderDescriptionExample
StatusComponent certification statusAlpha
Beta
Stable
Component versionThe version of the componentv1
Since runtime versionThe version of the Dapr runtime when the component status was set or updated1.11

HTTP

ComponentDescriptionStatusComponent version
OAuth2 Authorization Grant flowEnables the OAuth2 Authorization Grant flow on a Web APIAlphav1
OAuth2 Client Credentials Grant flowEnables the OAuth2 Client Credentials Grant flow on a Web APIAlphav1
OpenID ConnectVerifies a Bearer Token using OpenID Connect on a Web APIStablev1
Rate limitRestricts the maximum number of allowed HTTP requests per secondStablev1
Rego/OPA PoliciesApplies Rego/OPA Policies to incoming Dapr HTTP requestsAlphav1
Router AliasUse Router Alias to map arbitrary HTTP routes to valid Dapr API endpointsAlphav1
RouterCheckerUse RouterChecker middleware to block invalid http request routingAlphav1
SentinelUse Sentinel middleware to guarantee the reliability and resiliency of your applicationAlphav1
UppercaseConverts the body of the request to uppercase letters (demo)Stablev1
WasmUse Wasm middleware in your HTTP pipelineAlphav1

1 - Bearer

使用 bearer 中间件通过验证 bearer 令牌来保护 HTTP 端点

bearer HTTP 中间件 在 Web API 上使用 OpenID Connect 验证 Bearer 令牌,而无需修改应用程序。此设计将身份验证/授权关注点与应用程序分离,使应用程序操作员能够采用和配置身份验证/授权提供程序,而不会影响应用程序代码。

组件格式

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: bearer-token
spec:
  type: middleware.http.bearer
  version: v1
  metadata:
    - name: audience
      value: "<your token audience; i.e. the application's client ID>"
    - name: issuer
      value: "<your token issuer, e.g. 'https://accounts.google.com'>"

    # Optional values
    - name: jwksURL
      value: "<JWKS URL, e.g. 'https://accounts.google.com/.well-known/openid-configuration'>"

规格元数据字段

字段必填详情示例
audienceY令牌中期望的受众。通常,这对应于在 OpenID Connect 平台托管的凭据下创建的应用程序的客户端 ID。
issuerY颁发者机构,即令牌中颁发者声明的期望值。"https://accounts.google.com"
jwksURLNJWKS(包含用于验证令牌的公钥的 JWK 集)的地址。如果为空,将尝试从 OpenID 配置文档 <issuer>/.well-known/openid-configuration 中获取 URL。"https://accounts.google.com/.well-known/openid-configuration"

issuer 的常见值包括:

  • Auth0:https://{domain},其中 {domain} 是您的 Auth0 应用程序的域
  • Microsoft Entra ID:https://login.microsoftonline.com/{tenant}/v2.0,其中 {tenant} 应替换为您应用程序的租户 ID,格式为 UUID
  • Google:https://accounts.google.com
  • Salesforce (Force.com):https://login.salesforce.com

Dapr 配置

要应用中间件,必须在 配置 中引用该中间件。请参阅中间件管道

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  httpPipeline:
    handlers:
    - name: bearer-token
      type: middleware.http.bearer

相关链接

2 - OAuth2

使用 OAuth2 中间件来保护 HTTP 端点

OAuth2 HTTP 中间件 可在无需修改应用程序的情况下,为 Web API 启用 OAuth2 授权码流程。这种设计将身份验证/授权的关注点与应用程序分离,使应用程序运维人员可以采用和配置身份验证/授权提供程序,而不会影响应用程序代码。

组件格式

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: oauth2
spec:
  type: middleware.http.oauth2
  version: v1
  metadata:
  - name: clientId
    value: "<your client ID>"
  - name: clientSecret
    value: "<your client secret>"
  - name: scopes
    value: "https://www.googleapis.com/auth/userinfo.email"
  - name: authURL
    value: "https://accounts.google.com/o/oauth2/v2/auth"
  - name: tokenURL
    value: "https://accounts.google.com/o/oauth2/token"
  - name: redirectURL
    value: "http://dummy.com"
  - name: authHeaderName
    value: "authorization"
  - name: forceHTTPS
    value: "false"
  - name: pathFilter
    value: ".*/users/.*"

规范元数据字段

字段详细信息示例
clientId您的应用程序的客户端 ID,它是作为由支持 OAuth 的平台托管的凭据的一部分创建的
clientSecret您的应用程序的客户端密钥,它是作为由支持 OAuth 的平台托管的凭据的一部分创建的
scopes以空格分隔、区分大小写的 scope 字符串列表,通常用于应用程序中的授权"https://www.googleapis.com/auth/userinfo.email"
authURLOAuth2 授权服务器的端点"https://accounts.google.com/o/oauth2/v2/auth"
tokenURL客户端用于通过出示其授权授权或刷新令牌来获取访问令牌的端点"https://accounts.google.com/o/oauth2/token"
redirectURL授权服务器应在用户完成身份验证后重定向到的 Web 应用程序 URL"https://myapp.com"
authHeaderName要转发到您的应用程序的授权标头名称"authorization"
forceHTTPS如果为 true,则强制使用 TLS/SSL"true","false"
pathFilter仅将中间件应用于与给定路径模式匹配的请求".*/users/.*"

Dapr 配置

要应用中间件,必须在配置中引用它。请参阅中间件管道

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  httpPipeline:
    handlers:
    - name: oauth2
      type: middleware.http.oauth2

请求路径过滤

pathFilter 字段允许您使用正则表达式模式根据 HTTP 请求路径有选择地应用 OAuth2 身份验证。这支持以下场景:例如为不同的 API 端点配置具有不同 scope 的多个 OAuth2 中间件,通过确保用户仅获得其预期操作所需的最小权限,来实现最小权限原则。

示例:分离只读和管理员用户访问

在以下配置中:

  • /api/users/* 端点的请求获得具有只读用户 scope 的令牌
  • /api/admin/* 端点的请求获得具有完整管理员 scope 的令牌

这通过防止不必要的权限访问并限制受损令牌的影响范围来降低安全风险。

# 具有只读访问权限的用户
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: oauth2-users
spec:
  type: middleware.http.oauth2
  version: v1
  metadata:
  - name: clientId
    value: "<your client ID>"
  - name: clientSecret
    value: "<your client secret>"
  - name: scopes
    value: "user:read profile:read"
  - name: authURL
    value: "https://accounts.google.com/o/oauth2/v2/auth"
  - name: tokenURL
    value: "https://accounts.google.com/o/oauth2/token"
  - name: redirectURL
    value: "http://myapp.com/callback"
  - name: pathFilter
    value: "^/api/users/.*"
---
# 具有完整管理员访问权限的用户
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: oauth2-admin
spec:
  type: middleware.http.oauth2
  version: v1
  metadata:
  - name: clientId
    value: "<your client ID>"
  - name: clientSecret
    value: "<your client secret>"
  - name: scopes
    value: "admin:read admin:write user:read user:write"
  - name: authURL
    value: "https://accounts.google.com/o/oauth2/v2/auth"
  - name: tokenURL
    value: "https://accounts.google.com/o/oauth2/token"
  - name: redirectURL
    value: "http://myapp.com/callback"
  - name: pathFilter
    value: "^/api/admin/.*"

相关链接

3 - OAuth2 客户端凭据

使用 OAuth2 客户端凭据中间件保护 HTTP 端点

OAuth2 客户端凭据 HTTP 中间件 可在无需修改应用程序的情况下,为 Web API 启用 OAuth2 客户端凭据流。这种设计将身份验证/授权的关注点与应用程序分离,使得应用程序运维人员可以采用和配置身份验证/授权提供方,而不会影响应用程序代码。

组件格式

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: oauth2clientcredentials
spec:
  type: middleware.http.oauth2clientcredentials
  version: v1
  metadata:
  - name: clientId
    value: "<your client ID>"
  - name: clientSecret
    value: "<your client secret>"
  - name: scopes
    value: "https://www.googleapis.com/auth/userinfo.email"
  - name: tokenURL
    value: "https://accounts.google.com/o/oauth2/token"
  - name: headerName
    value: "authorization"
  - name: pathFilter
    value: ".*/users/.*"

规范元数据字段

字段详情示例
clientId在支持 OAuth 的平台上托管作为凭据的一部分而创建的应用程序客户端 ID
clientSecret在支持 OAuth 的平台上托管作为凭据的一部分而创建的应用程序客户端密钥
scopes以空格分隔的、区分大小写的范围字符串列表,通常用于应用程序中的授权"https://www.googleapis.com/auth/userinfo.email"
tokenURL客户端通过呈现其授权授予或刷新令牌来获取访问令牌的端点"https://accounts.google.com/o/oauth2/token"
headerName转发到应用程序的授权标头名称"authorization"
endpointParamsQuery指定对令牌端点的请求的附加参数true
authStyle可选地指定端点希望如何发送客户端 ID 和客户端密钥。请参阅下表中的可能值0
pathFilter仅将中间件应用于匹配给定路径模式的请求".*/users/.*"

authStyle 的可能值

含义
1在 POST 正文 中发送 “client_id” 和 “client_secret” 作为 application/x-www-form-urlencoded 参数。
2使用 HTTP 基本认证 发送 “client_id” 和 “client_secret”。这是 OAuth2 RFC 6749 第 2.3.1 节中描述的一种可选样式。
0表示通过尝试两种方式并缓存成功的方式来自动检测提供方想要的认证样式。

Dapr 配置

要应用中间件,必须在配置中引用该中间件。请参阅中间件管道

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  httpPipeline:
    handlers:
    - name: oauth2clientcredentials
      type: middleware.http.oauth2clientcredentials

请求路径过滤

pathFilter 字段允许您使用正则表达式模式,基于 HTTP 请求路径有选择地应用 OAuth2 身份验证。这支持诸如配置多个具有不同范围的 OAuth2 中间件用于不同 API 端点、通过确保用户仅获得其预期操作所需的最小权限来实现最小权限原则等场景。

示例:区分只读用户和管理员用户访问

在以下配置中:

  • /api/users/* 端点的请求接收带有只读用户范围的令牌
  • /api/admin/* 端点的请求接收带有完整管理员范围的令牌 这通过防止不必要的特权访问和限制受损令牌的影响范围来降低安全风险。
# 具有只读访问范围的用户
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: oauth2clientcredentials-users
spec:
  type: middleware.http.oauth2clientcredentials
  version: v1
  metadata:
  - name: clientId
    value: "<your client ID>"
  - name: clientSecret
    value: "<your client secret>"
  - name: scopes
    value: "user:read profile:read"
  - name: tokenURL
    value: "https://accounts.google.com/o/oauth2/token"
  - name: headerName
    value: "authorization"
  - name: pathFilter
    value: "^/api/users/.*"
---
# 具有完整管理员访问范围的用户
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: oauth2clientcredentials-admin
spec:
  type: middleware.http.oauth2clientcredentials
  version: v1
  metadata:
  - name: clientId
    value: "<your client ID>"
  - name: clientSecret
    value: "<your client secret>"
  - name: scopes
    value: "admin:read admin:write user:read user:write"
  - name: tokenURL
    value: "https://accounts.google.com/o/oauth2/token"
  - name: headerName
    value: "authorization"
  - name: pathFilter
    value: "^/api/admin/.*"

相关链接

4 - 应用 Open Policy Agent (OPA) 策略

使用中间件对传入请求应用 Open Policy Agent (OPA) 策略

Open Policy Agent (OPA) HTTP 中间件OPA 策略应用于传入的 Dapr HTTP 请求。这可用于对应用端点应用可重用的授权策略。

组件格式

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: my-policy
spec:
  type: middleware.http.opa
  version: v1
  metadata:
    # `includedHeaders` 是以逗号分隔的、不区分大小写的请求头集合,
    # 这些请求头将被包含在请求输入中。
    # 默认情况下,请求头不会传递给策略。若要在输入中接收传入请求头,
    # 请包含此配置
    - name: includedHeaders
      value: "x-my-custom-header, x-jwt-header"

    # `defaultStatus` 是拒绝响应时返回的状态码
    - name: defaultStatus
      value: 403

    # `readBody` 控制中间件是否在内存中读取完整的请求体,
    # 以便用于策略决策。
    - name: readBody
      value: "false"

    # `rego` 是要评估的 open policy agent 策略。必填
    # 策略包必须是 http,且策略必须设置 data.http.allow
    - name: rego
      value: |
        package http

        default allow = true

        # Allow 也可以是一个对象,并包含其他属性

        # 例如,如果你想在策略失败时重定向,可以设置状态码为 301,
        # 并在响应上设置 location 请求头:
        allow = {
            "status_code": 301,
            "additional_headers": {
                "location": "https://my.site/authorize"
            }
        } {
            not jwt.payload["my-claim"]
        }

        # 你也可以允许请求并为其添加额外的请求头:
        allow = {
            "allow": true,
            "additional_headers": {
                "x-my-claim": my_claim
            }
        } {
            my_claim := jwt.payload["my-claim"]
        }
        jwt = { "payload": payload } {
            auth_header := input.request.headers["Authorization"]
            [_, jwt] := split(auth_header, " ")
            [_, payload, _] := io.jwt.decode(jwt)
        }

你可以使用 官方 OPA playground 原型和实验策略。例如,可以在这里找到上述示例策略

规范元数据字段

字段详情示例
regoRego 策略语言见上文
defaultStatus拒绝响应时返回的状态码"403"
readBody如果设置为 true(默认值),则会完整读取每个请求的请求体到内存中,并可用于策略决策。如果你的策略不依赖于检查请求体,考虑将其禁用(设置为 false)以获得显著的性能提升。"false"
includedHeaders以逗号分隔的、不区分大小写的请求头集合,这些请求头将被包含在请求输入中。默认情况下,请求头不会传递给策略。若要在输入中接收传入请求头,请包含此配置"x-my-custom-header, x-jwt-header"

Dapr 配置

要应用中间件,必须在 配置中引用它。请参阅中间件管道

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  httpPipeline:
    handlers:
    - name: my-policy
      type: middleware.http.opa

输入

此中间件提供 HTTPRequest 作为输入。

HTTPRequest

HTTPRequest 输入包含关于传入 HTTP 请求的所有相关信息。

type Input struct {
  request HTTPRequest
}

type HTTPRequest struct {
  // 请求方法(例如 GET、POST 等...)
  method string
  // 原始请求路径(例如 "/v2/my-path/")
  path string
  // 将路径分解为多个部分以便于使用(例如 ["v2", "my-path"])
  path_parts string[]
  // 原始查询字符串(例如 "?a=1&b=2")
  raw_query string
  // 将查询分解为键及其值
  query map[string][]string
  // 请求头
  // 注意:默认情况下,不包含任何请求头。你必须通过
  // `spec.metadata.includedHeaders` 指定想要接收的请求头(见上文)
  headers map[string]string
  // 请求方案(例如 http、https)
  scheme string
  // 请求体(例如 http、https)
  body string
}

结果

策略必须设置 data.http.allow,其值为 boolean 类型,或带有 allow 布尔属性的 object 类型。allowtrue 将允许请求,而 false 值将拒绝请求,并返回由 defaultStatus 指定的状态码。以下策略使用默认值,演示了对所有请求返回 403 - Forbidden

package http

default allow = false

这等同于:

package http

default allow = {
  "allow": false
}

更改拒绝响应的状态码

拒绝请求时,你可以覆盖返回的状态码。例如,如果你想返回 401 而不是 403,可以执行以下操作:

package http

default allow = {
  "allow": false,
  "status_code": 401
}

添加响应头

要重定向,请添加请求头并将 status_code 设置为返回结果:

package http

default allow = {
  "allow": false,
  "status_code": 301,
  "additional_headers": {
    "Location": "https://my.redirect.site"
  }
}

添加请求头

你还可以在允许的请求上设置额外的请求头:

package http

default allow = false

allow = { "allow": true, "additional_headers": { "X-JWT-Payload": payload } } {
  not input.path[0] == "forbidden"
  // 其中 `jwt` 是另一个规则的结果
  payload := base64.encode(json.marshal(jwt.payload))
}

结果结构

type Result bool
// 或
type Result struct {
  // 是否允许或拒绝传入请求
  allow bool
  // 覆盖拒绝响应的状态码;可选
  status_code int
  // 在允许的请求或拒绝响应上设置请求头;可选
  additional_headers map[string]string
}

相关链接

5 - Router alias http request routing

使用 router alias 中间件将任意 HTTP 路由别名为 Dapr 端点

Router alias HTTP 中间件组件允许您将传入 Dapr 的任意 HTTP 路由转换为有效的 Dapr API 端点。

组件格式

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: routeralias 
spec:
  type: middleware.http.routeralias
  version: v1
  metadata:
    # String containing a JSON-encoded or YAML-encoded dictionary
    # Each key in the dictionary is the incoming path, and the value is the path it's converted to
    - name: "routes"
      value: |
        {
          "/mall/activity/info": "/v1.0/invoke/srv.default/method/mall/activity/info",
          "/hello/activity/{id}/info": "/v1.0/invoke/srv.default/method/hello/activity/info",
          "/hello/activity/{id}/user": "/v1.0/invoke/srv.default/method/hello/activity/user"
        }

在上面的示例中,传入的 HTTP 请求 /mall/activity/info?id=123 会被转换为 /v1.0/invoke/srv.default/method/mall/activity/info?id=123

规范元数据字段

字段详情示例
routes包含 JSON 编码或 YAML 编码字典的字符串。字典中的每个键是传入路径,值是其要转换到的路径。见上面的示例

Dapr 配置

要应用中间件,必须在配置中引用它。请参阅中间件管道

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  httpPipeline:
    handlers:
    - name: routeralias 
      type: middleware.http.routeralias

相关链接

6 - RouterChecker HTTP 请求路由

使用 routerchecker 中间件阻止无效的 HTTP 请求路由

RouterChecker HTTP [中间件](https://docs.dapr.io/zh-hans/operations/components/middleware/)组件利用正则表达式来检查 HTTP 请求路由的有效性,防止无效路由进入 Dapr 集群。RouterChecker 组件会过滤掉错误请求,从而减少遥测和日志数据中的噪音。

组件格式

RouterChecker 将一组规则应用于传入的 HTTP 请求。你可以使用正则表达式在组件元数据中定义这些规则。在以下示例中,HTTP 请求 RouterChecker 被设置为根据 ^[A-Za-z0-9/._-]+$ 正则表达式验证所有请求消息。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: routerchecker 
spec:
  type: middleware.http.routerchecker
  version: v1
  metadata:
  - name: rule
    value: "^[A-Za-z0-9/._-]+$"

在此示例中,上述定义将产生以下通过/失败案例:

PASS /v1.0/invoke/demo/method/method
PASS /v1.0/invoke/demo.default/method/method
PASS /v1.0/invoke/demo.default/method/01
PASS /v1.0/invoke/demo.default/method/METHOD
PASS /v1.0/invoke/demo.default/method/user/info
PASS /v1.0/invoke/demo.default/method/user_info
PASS /v1.0/invoke/demo.default/method/user-info

FAIL /v1.0/invoke/demo.default/method/cat password
FAIL /v1.0/invoke/demo.default/method/" AND 4210=4210 limit 1
FAIL /v1.0/invoke/demo.default/method/"$(curl

规范元数据字段

字段详情示例
ruleHTTP 请求 RouterChecker 使用的正则表达式^[A-Za-z0-9/._-]+$

Dapr 配置

要应用该中间件,必须在[配置](https://docs.dapr.io/zh-hans/concepts/configuration-concept/)中引用它。请参阅[中间件管道](https://docs.dapr.io/zh-hans/operations/components/middleware/#customize-processing-pipeline)。

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  httpPipeline:
    handlers:
    - name: routerchecker 
      type: middleware.http.routerchecker

相关链接

7 - Sentinel 容错中间件组件

使用 Sentinel 中间件来保障应用的可靠性和弹性

Sentinel 是一个强大的容错组件,以"流量"为切入点,涵盖了流量控制、流量整形、并发限制、熔断降级和自适应系统保护等多个领域,从而保障微服务的可靠性和弹性。

Sentinel HTTP 中间件 使 Dapr 能够利用 Sentinel 的强大能力来保护你的应用程序。有关 Sentinel 的更多细节,你可以参考 Sentinel Wiki

组件格式

在以下定义中,每秒最大请求数设置为 10:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: sentinel
spec:
  type: middleware.http.sentinel
  version: v1
  metadata:
  - name: appName
    value: "nodeapp"
  - name: logDir
    value: "/var/tmp"
  - name: flowRules
    value: >-
      [
        {
          "resource": "POST:/v1.0/invoke/nodeapp/method/neworder",
          "threshold": 10,
          "tokenCalculateStrategy": 0,
          "controlBehavior": 0
        }
      ]

规格元数据字段

字段详情示例
appName当前运行服务的名称nodeapp
logDir日志目录路径/var/tmp/sentinel
flowRulesSentinel 流量控制规则的 JSON 数组流量控制规则
circuitBreakerRulesSentinel 熔断规则的 JSON 数组熔断规则
hotSpotParamRulesSentinel 热点参数流量控制规则的 JSON 数组热点规则
isolationRulesSentinel 隔离规则的 JSON 数组隔离规则
systemRulesSentinel 系统规则的 JSON 数组系统规则

一旦达到限制,请求将返回 HTTP 状态码 429:请求过多

每个规则定义中的 resource 字段需特别注意。在 Dapr 中,它遵循以下格式:

POST/GET/PUT/DELETE:Dapr HTTP API 请求路径

所有具体的 HTTP API 信息可以在 Dapr API 参考 中找到。在上述示例配置中,resource 字段设置为 POST:/v1.0/invoke/nodeapp/method/neworder

Dapr 配置

要使中间件生效,必须在 配置 中引用该中间件。请参阅 中间件管道

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: daprConfig
spec:
  httpPipeline:
    handlers:
      - name: sentinel
        type: middleware.http.sentinel

相关链接

8 - 将请求体转换为大写

使用 uppercase 中间件测试您的 HTTP 管道是否正常工作

uppercase HTTP 中间件 将请求体转换为大写字母,用于测试管道是否正常工作。它仅应用于本地开发。

组件格式

在以下定义中,它将请求体的内容转换为大写:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: uppercase
spec:
  type: middleware.http.uppercase
  version: v1

此组件没有需要配置的 metadata

Dapr 配置

要应用中间件,必须在配置中引用它。请参阅中间件管道

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  httpPipeline:
    handlers:
    - name: uppercase
      type: middleware.http.uppercase

相关链接

9 - Wasm

在 HTTP 管道中使用 Wasm 中间件

WebAssembly 是一种安全执行跨语言编译代码的机制。运行时负责加载并运行 WebAssembly 模块(Wasm),这些模块通常以 .wasm 为扩展名的二进制文件形式存在。

通过 Wasm HTTP 中间件,你可以使用自定义逻辑处理传入请求或构造响应,这些逻辑会被编译成 Wasm 二进制文件。换句话说,你可以使用外部文件扩展 Dapr,而无需将代码预编译到 daprd 二进制文件中。Dapr 内嵌了 wazero 来实现这一能力,且无需 CGO 依赖。

Wasm 二进制文件通过 URL 加载。例如,file://rewrite.wasm 会从进程当前目录加载 rewrite.wasm。在 Kubernetes 环境中,请参考如何:将 Pod 卷挂载到 Dapr 边车来配置包含 Wasm 模块的文件系统挂载。

也支持从远程 URL 获取 Wasm 二进制文件。这种情况下,URL 必须严格指向单个 Wasm 二进制文件。例如:

  • http://example.com/rewrite.wasm,或
  • https://example.com/rewrite.wasm

组件格式

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: wasm
spec:
  type: middleware.http.wasm
  version: v1
  metadata:
  - name: url
    value: "file://router.wasm"
  - name: guestConfig
    value: {"environment":"production"}

规格元数据字段

用户至少需要提供一个实现 http-handler 接口的 Wasm 二进制文件。具体编译方法将在后续说明。

字段说明是否必填示例
url用于实例化的 Wasm 二进制资源 URL。支持的协议方案包括 file://http://https://file:// URL 的路径是相对于 Dapr 进程的,除非以 / 开头表示绝对路径。file://hello.wasm, https://example.com/hello.wasm
guestConfig传递给 Wasm 客户端的可选配置。用户可以传入任意字符串,由客户端代码自行解析。environment=production,{"environment":"production"}

Dapr 配置

要使中间件生效,必须在 configuration 中引用它。请参阅中间件管道

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  httpPipeline:
    handlers:
    - name: wasm
      type: middleware.http.wasm

注意:与原生中间件相比,WebAssembly 中间件会消耗更多资源。这会导致资源约束比原生代码实现的相同逻辑更快出现。生产环境使用时应该控制最大并发

生成 Wasm

此组件允许你使用自定义逻辑处理传入请求或生成响应,这些逻辑通过 http-handler 应用二进制接口(ABI)编译而成。handle_request 函数接收传入请求,可以根据需要操作该请求或生成响应。

要编译 Wasm,必须使用符合 http-handler 规范的客户端 SDK,例如 TinyGo

以下是一个 TinyGo 示例:

package main

import (
	"strings"

	"github.com/http-wasm/http-wasm-guest-tinygo/handler"
	"github.com/http-wasm/http-wasm-guest-tinygo/handler/api"
)

func main() {
	handler.HandleRequestFn = handleRequest
}

// handleRequest 实现了一个简单的 HTTP 路由器。
func handleRequest(req api.Request, resp api.Response) (next bool, reqCtx uint32) {
	// 如果 URI 以 /host 开头,则去掉该前缀并分发给下一个处理器。
	if uri := req.GetURI(); strings.HasPrefix(uri, "/host") {
		req.SetURI(uri[5:])
		next = true // 继续执行宿主机上的下一个处理器。
		return
	}

	// 返回静态响应
	resp.Headers().Set("Content-Type", "text/plain")
	resp.Body().WriteString("hello")
	return // 跳过下一个处理器,因为我们已经写入了响应。
}

如果使用 TinyGo,请按以下方式编译,并将 spec 元数据字段中的 url 设置为输出文件的位置(例如 file://router.wasm):

tinygo build -o router.wasm -scheduler=none --no-debug -target=wasi router.go`

Wasm guestConfig 示例

以下是如何使用 guestConfig 向 Wasm 传递配置的示例。在 Wasm 代码中,可以使用客户端 SDK 中定义的 handler.Host.GetConfig 函数来获取配置。在下面的示例中,Wasm 中间件解析了组件中定义的 JSON 配置里的 environment 字段。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: wasm
spec:
  type: middleware.http.wasm
  version: v1
  metadata:
  - name: url
    value: "file://router.wasm"
  - guestConfig
    value: {"environment":"production"}

下面是 TinyGo 的示例:

package main

import (
	"encoding/json"
	"github.com/http-wasm/http-wasm-guest-tinygo/handler"
	"github.com/http-wasm/http-wasm-guest-tinygo/handler/api"
)

type Config struct {
	Environment string `json:"environment"`
}

func main() {
	// 获取配置字节,即组件中定义的 guestConfig 值。
	configBytes := handler.Host.GetConfig()
	
	config := Config{}
	json.Unmarshal(configBytes, &config)
	handler.Host.Log(api.LogLevelInfo, "Config environment: "+config.Environment)
}

相关链接

10 - 速率限制

使用速率限制中间件来限制每秒请求数

速率限制 HTTP 中间件 允许限制每秒允许的最大 HTTP 请求数。速率限制可以保护您的应用程序免受拒绝服务(DoS)攻击。DoS 攻击可能由恶意的第三方发起,也可能由您软件中的错误引起(即"友军误伤"式 DoS 攻击)。

组件格式

在以下定义中,每秒最大请求数设置为 10:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: ratelimit
spec:
  type: middleware.http.ratelimit
  version: v1
  metadata:
  - name: maxRequestsPerSecond
    value: 10

规范元数据字段

字段详情示例
maxRequestsPerSecond按远程 IP 计算的每秒最大请求数。
组件会查看 X-Forwarded-ForX-Real-IP 请求头来确定调用者的 IP。
10

一旦达到限制,请求将失败并返回 HTTP 状态码 429: Too Many Requests

或者,可以使用最大并发设置来对应用程序进行速率限制,该设置适用于所有流量,无论远程 IP、协议或路径如何。

Dapr 配置

要应用中间件,必须在配置中引用它。请参阅中间件管道

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  httpPipeline:
    handlers:
    - name: ratelimit
      type: middleware.http.ratelimit

相关链接