新聞中心
Dapr 入門教程之中間件
作者:陽明 2022-09-30 06:36:25
云計算
云原生 通過 Dapr 配置添加的其他中間件會按定義順序添加到管道中,該管道適用于所有 Dapr API 端點,包括狀態(tài)、發(fā)布/訂閱、服務(wù)調(diào)用、綁定、安全等。

目前創(chuàng)新互聯(lián)已為上千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)頁空間、網(wǎng)站托管維護、企業(yè)網(wǎng)站設(shè)計、章貢網(wǎng)站維護等服務(wù),公司將堅持客戶導向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。
Dapr 允許通過鏈接一系列中間件組件來定義自定義處理管道。一個請求在被路由到用戶代碼之前會經(jīng)過所有定義的中間件組件,然后在返回到客戶端之前以相反的順序經(jīng)過定義的中間件。
Dapr 中間件
Dapr 中間件
當啟動的時候,Dapr sidecar 會構(gòu)造一個中間件處理管道。默認情況下,管道由 tracing 中間件和 CORS 中間件組成。通過 Dapr 配置添加的其他中間件會按定義順序添加到管道中,該管道適用于所有 Dapr API 端點,包括狀態(tài)、發(fā)布/訂閱、服務(wù)調(diào)用、綁定、安全等。
如以下配置示例定義了一個使用 OAuth 2.0 中間件和大寫中間件組件的自定義管道。在這種情況下,所有請求都通過 OAuth 2.0 協(xié)議進行授權(quán),并轉(zhuǎn)換為大寫,然后再轉(zhuǎn)發(fā)給用戶代碼。
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
name: pipeline
namespace: default
spec:
httpPipeline:
handlers:
- name: oauth2
type: middleware.http.oauth2
- name: uppercase
type: middleware.http.uppercase
與其他構(gòu)建塊組件一樣,中間件組件是可擴展的,目前 Dapr 已經(jīng)支持的中間件如下表所示。
|
中間件 |
描述 |
狀態(tài) |
組件版本 |
|
OAuth2 Authorization Grant flow |
在 Web API 上啟用 OAuth2 授權(quán)授予流 |
Alpha |
v1 |
|
OAuth2 Client Credentials Grant flow |
在 Web API 上啟用 OAuth2 客戶端憑據(jù)授予流 |
Alpha |
v1 |
|
OpenID Connect |
在 Web API 上使用 OpenID Connect 驗證持有者令牌 |
Alpha |
v1 |
|
Rate limit |
限制每秒允許的 HTTP 請求的最大請求數(shù) |
Alpha |
v1 |
|
Rego/OPA Policies |
將 Rego/OPA 策略應(yīng)用于傳入的 Dapr HTTP 請求 |
Alpha |
v1 |
|
RouterChecker |
使用 RouterChecker 中間件來阻止無效的 http 請求路由 |
Alpha |
v1 |
|
Sentinel |
使用 Sentinel 中間件保證應(yīng)用程序的可靠性和彈性 |
Alpha |
v1 |
|
Uppercase |
將請求正文轉(zhuǎn)換為大寫字母 (demo) |
Stable |
v1 |
|
WASM |
在 HTTP 管道中使用 WASM 中間件 |
Alpha |
v1 |
這些中間件的實現(xiàn)源碼位可以在 Github 倉庫 https://github.com/dapr/components-contrib/tree/master/middleware/http 中找到。
自定義中間件
Dapr 使用 FastHTTP 來實現(xiàn)其 HTTP 服務(wù)器,所以自定義的 HTTP 中間件需要編寫為 FastHTTP handler,你的中間件需要實現(xiàn)一個如下所示的 Middleware 接口:
package middleware
import (
"github.com/valyala/fasthttp"
)
type Middleware interface {
GetHandler(metadata Metadata) (func(h fasthttp.RequestHandler) fasthttp.RequestHandler, error)
}
該接口定義了一個返回 fasthttp.RequestHandler 和 error 的 GetHandler 方法。我們自定義的中間件處理程序?qū)崿F(xiàn)可以包括任何入站邏輯、出站邏輯:
func (m *customMiddleware) GetHandler(metadata Metadata) (func(fasthttp.RequestHandler) fasthttp.RequestHandler, error) {
var err error
return func(h fasthttp.RequestHandler) fasthttp.RequestHandler {
return func(ctx *fasthttp.RequestCtx) {
h(ctx)
}
}, err
}然后你可以將你自定義的中間件組件貢獻給 components-contrib 存儲庫。當 components-contrib 接受你的提交后,然后需要在 Dapr 運行時的倉庫中的 https://github.com/dapr/dapr/tree/master/cmd/daprd/components 下面添加一個中間件注冊文件。
注冊中間件
比如 uppercase 中間件的注冊如下代碼所示:
package components
import (
"strings"
"github.com/valyala/fasthttp"
"github.com/dapr/components-contrib/middleware"
httpMiddlewareLoader "github.com/dapr/dapr/pkg/components/middleware/http"
httpMiddleware "github.com/dapr/dapr/pkg/middleware/http"
"github.com/dapr/kit/logger"
)
func init() {
httpMiddlewareLoader.DefaultRegistry.RegisterComponent(func(log logger.Logger) httpMiddlewareLoader.FactoryMethod {
return func(metadata middleware.Metadata) (httpMiddleware.Middleware, error) {
return func(h fasthttp.RequestHandler) fasthttp.RequestHandler {
return func(ctx *fasthttp.RequestCtx) {
body := string(ctx.PostBody())
ctx.Request.SetBody([]byte(strings.ToUpper(body)))
h(ctx)
}
}, nil
}
}, "uppercase")
}
不過我們也可以發(fā)現(xiàn) Dapr 對于中間件的擴展并沒有完全放開,如果用戶有特定的需求需要將代碼在主倉庫中進行更新,這勢必也降低了靈活性,不過也可以避免因為低質(zhì)量的中間件造成 Dapr 各種問題。
OAuth 中間件示例
接下來我們配置一個 OAuth 中間件來說明下 Dapr 中中間件的使用方法。通過配置一個 OAuth 中間件,在不修改應(yīng)用程序的情況下在 Web API 上啟用 OAuth 授權(quán)。這種設(shè)計將認證/授權(quán)問題從應(yīng)用程序中分離出來,因此應(yīng)用程序運維人員可以采用和配置認證/授權(quán)提供者而不影響應(yīng)用程序代碼。
dapr oauth 中間件
這里我們在 K8s 集群中使用 ingress-nginx 作為 ingress 控制器,如果沒有安裝可以使用下面的 Helm chart 來快速安裝:
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install my-release ingress-nginx/ingress-nginx
首先我們編寫了一個使用 Node.js 開發(fā)的 echoapp,如下所示:
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.use(bodyParser.json());
const port = 3000;
app.get("/echo", (req, res) => {
var text = req.query.text;
console.log("Echoing: " + text);
res.send("Access token: " + req.headers["authorization"] + " Text: " + text);
});
app.listen(port, () => console.log(`Node App listening on port ${port}!`));然后編寫了一個 /echo 接口,獲取了請求 header 頭中的 authorization 信息和客戶端的請求文本信息。
接下來我們這里使用 Github 來實現(xiàn)認證授權(quán),首先前往 https://github.com/settings/developers 注冊一個 OAuth 應(yīng)用,如下所示:
新建 OAuth 應(yīng)用
這里我們指定的應(yīng)用 URL 為 http://echo.dapr.local,點擊 Register application 注冊新應(yīng)用,注冊后在應(yīng)用詳情頁面可以獲取到 clientId 信息,clientSecret 信息需要手動點擊 Generate a new client secret 按鈕獲取,將該兩個參數(shù)值記錄下來,后續(xù)會使用到。
獲取clientSecret
然后將我們的 echoapp 應(yīng)用部署到 Kubernetes 集群中去,對應(yīng)的資源清單如下所示:
apiVersion: apps/v1
kind: Deployment
metadata:
name: echoapp
labels:
app: echo
spec:
selector:
matchLabels:
app: echo
template:
metadata:
labels:
app: echo
annotations:
dapr.io/enabled: "true"
dapr.io/app-id: "echoapp"
dapr.io/app-port: "3000"
dapr.io/config: "pipeline"
spec:
containers:
- name: echo
image: dapriosamples/middleware-echoapp:latest
ports:
- containerPort: 3000
imagePullPolicy: Always
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: echo-ingress
spec:
ingressClassName: nginx
rules:
- host: echo.dapr.local
http:
paths:
- backend:
service:
name: echoapp-dapr
port:
number: 80
path: /
pathType: Prefix
注意上面我們創(chuàng)建了一個 Ingress 對象,用來暴露 echoapp 應(yīng)用,需要注意的是我們并沒有主動創(chuàng)建 Service 對象,而是直接關(guān)聯(lián)的 echoapp-dapr 這個 Service,其 80 端口映射到 echoapp 應(yīng)用的 dapr sidecar 中的 3500 端口。
另外注意上面為應(yīng)用添加的注解,其中有一個 dapr.io/config: "pipeline",這是用來指定使用的配置對象的,所以我們還需要創(chuàng)建一個名為 pipeline 的 Configuration 對象:
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
name: pipeline
spec:
tracing:
samplingRate: "1"
zipkin:
endpointAddress: "http://zipkin.default.svc.cluster.local:9411/api/v2/spans"
httpPipeline:
handlers:
- type: middleware.http.oauth2
name: oauth2
這里我們?yōu)?echoapp 應(yīng)用配置了一個 middleware.http.oauth2 類型的中間件,對應(yīng)處理器的名稱為 oauth2,該處理器對應(yīng)中 Dapr 中的一個 Component 組件,如下所示:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: oauth2
spec:
type: middleware.http.oauth2
version: v1
metadata:
- name: clientId
value: ""
- name: clientSecret
value: ""
- name: scopes
value: ""
- name: authURL
value: "https://github.com/login/oauth/authorize"
- name: tokenURL
value: "https://github.com/login/oauth/access_token"
- name: redirectURL
value: "http://echo.dapr.local"
- name: authHeaderName
value: "authorization"
要使用 Dapr OAuth 中間件,需要配置以下信息:
- Client ID
- Client secret
- Scopes
- Authorization URL
- Token URL
下表是一些比較熱門授權(quán)服務(wù)器的 Authorization/Token URLs:
|
Server |
Authorization URL |
Token URL |
|
Azure AAD |
https://login.microsoftonline.com/{tenant}/oauth2/authorize |
https://login.microsoftonline.com/{tenant}/oauth2/token |
|
GitHub |
https://github.com/login/oauth/authorize |
https://github.com/login/oauth/access_token |
|
|
https://accounts.google.com/o/oauth2/v2/auth |
https://accounts.google.com/o/oauth2/token https://www.googleapis.com/oauth2/v4/token |
|
|
https://api.twitter.com/oauth/authorize |
https://api.twitter.com/oauth2/token |
我們這里使用的 GitHub 的授權(quán)服務(wù)器配置,還要注意最后添加的 authHeaderName: authorization 屬性,上面我們代碼中就是從 Header 頭從獲取的 authorization 的值。
接下來創(chuàng)建上面的所有資源對象即可,創(chuàng)建完成后記得要將 echo.dapr.local 域名映射到 ingress 控制器。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
echoapp-b7f5469cb-hzvth 2/2 Running 0 51s
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echoapp-dapr ClusterIP None80/TCP,50001/TCP,50002/TCP,9090/TCP 69m
$ kubectl get ingress echo-ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
echo-ingress nginx echo.dapr.local 192.168.0.52 80 59m
然后接下來我們就可以在瀏覽器中輸入 http://echo.dapr.local/v1.0/invoke/echoapp/method/echo?text=hello 來訪問應(yīng)用中的 echo 方法了,正常訪問的時候會出現(xiàn) 502 錯誤,不符合預(yù)期。
502錯誤
這是因為從 Dapr 1.4 版本開始,daprd 進程就被鎖定為只接受來自 pod 邊界的連接,以實現(xiàn)良好的安全措施。如果要啟用外部調(diào)用 Dapr,則需要在應(yīng)用中添加以下注解:
dapr.io/sidecar-listen-addresses: "0.0.0.0"
將該注解添加到 Deployment 中,更新后再次訪問 http://echo.dapr.local/v1.0/invoke/echoapp/method/echo?text=hello 就正常了,第一次會跳轉(zhuǎn)到 GitHub 進行授權(quán)。
github 授權(quán)
授權(quán)后會自動跳轉(zhuǎn)回來,正常就會顯示 echo 接口返回的數(shù)據(jù),包括 Access Token 的數(shù)據(jù)和 text 參數(shù)的值。
echo 方法
到這里我們就實現(xiàn)了在 Dapr 中為應(yīng)用啟用 OAuth 中間件,對原始應(yīng)用沒有任何侵入性。
新聞名稱:Dapr 入門教程之中間件
網(wǎng)頁鏈接:http://m.fisionsoft.com.cn/article/djpsdji.html


咨詢
建站咨詢
