通過Dapr實現一個簡單的基於.net的微服務電商系統(十)——一步一步教你如何擼Dapr之綁定

  如果說Actor是dapr有狀態服務的內部體現的話,那綁定應該是dapr對serverless這部分的體現了。我們可以通過綁定極大的擴展應用的能力,甚至未來會成爲serverless的基礎。最開始接觸dapr的時候,會在其官方首頁看到這麼一句話“Dapr is a portable, serverless, event-driven runtime ” 一個可移植的,服務器的,事件驅動的運行時。可移植很容易理解,事件驅動也有所體現。那這個無服務器(serverless)呢?今天我們就講講dapr是如何serverless的。

目錄:
一、通過Dapr實現一個簡單的基於.net的微服務電商系統

二、通過Dapr實現一個簡單的基於.net的微服務電商系統(二)——通訊框架講解

三、通過Dapr實現一個簡單的基於.net的微服務電商系統(三)——一步一步教你如何擼Dapr

四、通過Dapr實現一個簡單的基於.net的微服務電商系統(四)——一步一步教你如何擼Dapr之訂閱發佈

五、通過Dapr實現一個簡單的基於.net的微服務電商系統(五)——一步一步教你如何擼Dapr之狀態管理

六、通過Dapr實現一個簡單的基於.net的微服務電商系統(六)——一步一步教你如何擼Dapr之Actor服務

七、通過Dapr實現一個簡單的基於.net的微服務電商系統(七)——一步一步教你如何擼Dapr之服務限流

八、通過Dapr實現一個簡單的基於.net的微服務電商系統(八)——一步一步教你如何擼Dapr之鏈路追蹤

九、通過Dapr實現一個簡單的基於.net的微服務電商系統(九)——一步一步教你如何擼Dapr之OAuth2授權

十、通過Dapr實現一個簡單的基於.net的微服務電商系統(十)——一步一步教你如何擼Dapr之綁定
附錄:(如果你覺得對你有用,請給個star)
一、電商Demo地址

二、通訊框架地址

  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至少從技術層面來看已經沒有多少阻礙了。好了,今天的分享就到這裏~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章