一步一步教你如何擼 Dapr 之綁定
如果說 Actor 是 dapr 有狀態服務的內部體現的話,那綁定應該是 dapr 對 serverless 這部分的體現了。我們可以通過綁定極大的擴展應用的能力,甚至未來會成爲 serverless 的基礎。最開始接觸 dapr 的時候,會在其官方首頁看到這麼一句話 “Dapr is a portable, serverless, event-driven runtime” 一個可移植的,服務器的,事件驅動的運行時。可移植很容易理解,事件驅動也有所體現。那這個無服務器(serverless) 呢?今天我們就講講 dapr 是如何 serverless 的。
附錄:(如果你覺得對你有用,請給個 star)
一、電商 Demo 地址:https://github.com/sd797994/Oxygen-Dapr.EshopSample
二、通訊框架地址:https://github.com/sd797994/Oxygen-Dapr
serverless 還是有必要提兩嘴,知道的同學可以直接略過。直接翻開 CNCF 對 serverless 的定義:“Serverless 是指構建和運行不需要服務器管理的應用程序的概念”,這個概念說起來非常的大哈,實際上根據各家雲平臺提供的 serverless 服務來看,其主要作用是將開發者的應用程序和服務器操作系統環境進行了隔離,讓開發人員不再關心服務器(而不是完全不需要服務器!),只需要通過雲函數的方式編寫特定的業務代碼即可對外提供服務。每一個函數會被編譯成一個容器鏡像,當外部請求過來時 Serverless 會激活這個函數運行我們的鏡像實例,當請求量激增時,Serverless 會幫我們橫向擴容多個實例來抗住請求。當一段時間沒有請求後,Serverless 又會幫我們逐步縮容雲函數實例直到實例變爲 0。這樣當沒有請求時的大部分時間裏雲服務商不會收取你的 CPU / 內存 / 網絡的費用,僅僅收取一個磁盤費用(託管雲函數鏡像需要)。這裏面涉及到兩個問題,一個是雲函數的擴容 / 縮容機制,一個就是雲函數本身如何調用其他服務比如我要持久化數據 / 發送郵件 / 寫短信 / 訂閱?在各家雲商提供的 Serverless 架構裏,擴容縮容自然是通過 k8s 來實現的,而調用外部服務則被封裝成了自家的雲服務(比如阿里雲可以調用 RDS 讀寫數據庫。調用 OSS 讀寫對象,相應的自家的 Serverless 架構都提供了相關函數的功能)。
那 Dapr 如何實現 Serverless 的呢?但凡熟悉 k8s 的同學應該對自動化擴容、縮容這部分比較容易理解, 其基於 k8s 的 HPA 機制運作,dapr 通過對 KEDA 集成實現了這部分的功能,不過這不是今天我們要講的重點。另外一個問題,雲函數如何調用外部服務?這就是今天我們要講的重點——綁定機制的實現。dapr 的綁定提供了非常多的外部組件訪問支持,訪問這個列表可以查詢具體的支持情況,隨着 dapr 的逐步迭代我相信這個列表還會逐步增加最終將覆蓋主流的大部分我們會用到的服務組件。這樣最終我們將無需和某個雲服務商的 Serverless 做技術綁定,只需要 dapr 即可實現 Serverless!而我們的應用程序將會變得非常輕量級,幾乎不需要集成特定組件 sdk(比如數據庫訪問 sdk、sms 短信 sdk、ios 消息推送 sdk 等等等等)。只需要提供一個對外服務的 restapi,內部完成業務操作後其餘的部分交給 dapr 幫我們完成即可。
今天就來看看我們通過 dapr 是如何完成對數據庫訪問的,這裏依然使用我們的 eshop 進行舉例,在 eshop 中我們試着訪問我們的用戶數據庫的 Account 表。首先我們需要創建一個 bingding 類型的 component,比較簡單隻需要申明這是一個 bindings.postgres 的 Component,包含一個鏈接字符串指向我們的 infrastructure 下的 postgres 這個 k8s service。
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: accountpostgres
namespace: dapreshop
spec:
type: bindings.postgres
version: v1
metadata:
- name: url
value: user=postgres password=Mytestpwd#123 host=postgres.infrastructure port=5432 dbname=AccountDb sslmode=disable
接着我們編寫代碼來實現對該 component 進行訪問,通過查詢 Account 獲取用戶信息並打印到 postman 中
首先我們實現一個簡單的 http 請求用於查詢我們的綁定服務:
public class HttpHelper
{
private static async Task<string> GetResultAsync(string componentName, string sql)
{
var req = new HttpRequestMessage(HttpMethod.Post, $"http://localhost:3500/v1.0/bindings/{componentName}");
req.Content = new StringContent(JsonSerializer.Serialize(new { operation = "query", metadata = new { sql = sql } }));
var resp = await new HttpClient().SendAsync(req);
if (resp.IsSuccessStatusCode)
{
var result = await resp.Content.ReadAsStringAsync();
return result;
}
else
throw new NotSupportedException($"component無效或不支持的sql查詢語句");
}
public static async Task<List<T>> GetResultAsync<T>(string componentName, string sql) where T:class
{
var str = await GetResultAsync(componentName, sql);
var obj = JsonSerializer.Deserialize<List<object>>(str);
var result = new List<T>();
foreach (JsonElement item in obj)
{
result.Add(AccountConvetor(item) as T);
}
return result;
}
static Infrastructure.PersistenceObject.Account AccountConvetor(JsonElement item)
{
var t = new Infrastructure.PersistenceObject.Account();
t.Id = Guid.Empty;//由於不知名的原因uuid的鍵讀取出來的值並不是uuid而是一個數組
t.LoginName = item[1].GetString();
t.Password = item[2].GetString();
t.NickName = item[3].GetString();
t.State = (Domain.Enums.AccountState)item[4].GetInt32();
return t;
}
}
接着在 AccountQueryService 中創建一個 GetAccountListByDapr 用於暴露該服務到外部:
[AuthenticationFilter(false)]
public async Task<ApiResult> GetAccountListByDapr()
{
var result = await HttpHelper.GetResultAsync<Infrastructure.PersistenceObject.Account>("accountpostgres", "select * from public.\"Account\"");
return ApiResult.Ok(result);
}
然後我們通過 postman 發起一個訪問:
可以看到成功的通過 httpclient 調用 dapr 獲取到了數據庫裏的數據。這裏還有些小的問題比如我的 id 是一個 uuid 格式,通過 dapr 讀取出來變成了一個數組,還不知道是什麼原因。不過大體思路就是這樣了,至少目前通過 dapr 可以和阿里雲 oss、ios 消息推送、mysql、kafka、mqtt、postgresql、rabbitmq、redis 等等等等我們常用的耳熟能詳的服務 / 組件進行集成,而你唯一需要關心的只是通過訪問 dapr 的 api 來發送操作 / 獲取數據僅此而已,dapr 將組件集成的複雜度從應用層面遷移後,對於開發者來講通過 dapr 要實現一個 serverless 至少從技術層面來看已經沒有多少阻礙了。好了,今天的分享就到這裏~
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/QdEvkLqdUzHVyybUhhy0og