在非容器(集群)环境下运行dapr
作者:李俱順
原文:https://www.4async.com/2021/03/2021-03-11-running-dapr-without-container/
前一段時間一直關注的dapr正式發布了v1.0版本(實際上本文發布時還更新了v1.0.1),代表dapr在某些程度上進入穩定狀態,可以嘗試在實際中進行運用。作為我一直關注的項目,在第一時間中進行了嘗試,并試圖引入實際項目中,本文則是針對這些的一些先期測試內容.
什么是dapr?
dapr最早是由微軟開源的(不愧是你),一個可移植的、事件驅動的程序運行時,它使任何開發者都能輕松地構建運行在云和邊緣的彈性、無狀態/有狀態的應用程序,并且可以靈活支持多種開發語言。換而言之,在我看來,dapr可以作為一個serverless落地方案看待和處理,對程序而言,只關注提供的store和消息隊列接口,無需關心架構層面更多內容。
不過在官方的示例教程中,使用的環境為容器環境部署和管理dapr。實際上,除了在容器環境或者容器集群環境下,dapr可以配置為在本地機器上以自托管模式運行。
本地安裝
dapr安裝可以通過官方的dapr-cli實現,dapr-cli可以通過一鍵安裝命令快速安裝:
# wget -q https://raw.githubusercontent.com/dapr/cli/master/install/install.sh -O - | /bin/bash Your system is linux_amd64Dapr CLI is detected: main: line 86: 43656 Segmentation fault $DAPR_CLI_FILE --version Reinstalling Dapr CLI - /usr/local/bin/dapr...Getting the latest Dapr CLI... Installing v1.0.0 Dapr CLI... Downloading https://github.com/dapr/cli/releases/download/v1.0.0/dapr_linux_amd64.tar.gz ... dapr installed into /usr/local/bin successfully. CLI version: 1.0.0 Runtime version: n/aTo get started with Dapr, please visit https://docs.dapr.io/getting-started/可以通過輸入dapr命令確認dapr-cli程序是否被正常安裝成功。
接下來使用dapr-cli安裝所有的runtime等應用。
# dapr init --slim ? Making the jump to hyperspace... ↘ Downloading binaries and setting up components... Dapr runtime installed to /root/.dapr/bin, you may run the following to add it to your path if you want to run daprd directly:export PATH=$PATH:/root/.dapr/bin ? Downloaded binaries and completed components set up. ?? daprd binary has been installed to /root/.dapr/bin. ?? placement binary has been installed to /root/.dapr/bin. ? Success! Dapr is up and running. To get started, go here: https://aka.ms/dapr-getting-started# dapr --version CLI version: 1.0.0 Runtime version: 1.0.1在官方文檔中,如果選擇使用init命令初始化,dapr-cli將會自動嘗試使用容器環境管理相關程序,只有添加--slim參數才會選擇本地化運行。更多用法可以參考dapr help init幫助。默認程序相關內容會安裝在$HOME/.dapr目錄下,這里因為我為了簡便使用了root用戶,因此程序命令所在目錄為/root/.dapr/bin,共安裝了如下命令:
# ls ~/.dapr/bin daprd dashboard placement web從文件名可以看出來daprd是deamon進程,dashboard就是管理面板,placement是用于管理actor分布方案和密鑰范圍的工具。官方文檔中提到在安裝后會使用Reids作為默認的存儲和pub/sub組件,但是我實際安裝下來其實是并沒沒有的,不知道是不是文檔有些過期導致的。這時如果按照官方文檔的例子進行操作啟動程序并嘗試在存儲中保存數據,則會出現報錯的情況:
// 第一個session中執行: # dapr run --app-id myapp --dapr-http-port 3500// 第二個session中執行: # curl -X POST -H "Content-Type: application/json" -d '[{ "key": "name", "value": "Bruce Wayne"}]' http://localhost:3500/v1.0/state/statestore{"errorCode":"ERR_STATE_STORES_NOT_CONFIGURED","message":"state store is not configured"}不過實際上添加組件在dapr中也是比較簡單的,可以通過在$HOME/.dapr/components下添加對應yaml文件實現。
添加Redis作為組件
我們可以在官方文檔中找到一個Redis組件配置模版,可以快速使用:
# redis-store.yml apiVersion: dapr.io/v1alpha1 kind: Component metadata:name: redis-storenamespace: default spec:type: state.redisversion: v1metadata:- name: redisHostvalue: 127.0.0.1:6379- name: redisPasswordvalue: ""當然我們也可以使用Redis Stream功能做pub/sub功能,雖然這個功能已經GA,但是介于Redis Stream的特點,你需要謹慎使用這個功能,這里只是因為是演示所以無所謂:
# redis-pubsub.yml apiVersion: dapr.io/v1alpha1 kind: Component metadata:name: redis-pubsubnamespace: default spec:type: pubsub.redisversion: v1metadata:- name: redisHostvalue: 127.0.0.1:6379- name: redisPasswordvalue: ""- name: consumerIDvalue: "myGroup"這里我們定義了一個store名叫做redis-store,所以我們要把上面的命令修改一下:
# curl -X POST -H "Content-Type: application/json" -d '[{ "key": "name", "value": "Bruce Wayne"}]' http://localhost:3500/v1.0/state/redis-store// 獲取存儲內容 # curl http://localhost:3500/v1.0/state/redis-store/name "Bruce Wayne"同時也可以通過redis-cli獲取Redis中存儲的內容:
# redis-cli 127.0.0.1:6379> keys * 1) "myapp||name" 127.0.0.1:6379> hgetall "myapp||name" 1) "data" 2) "\"Bruce Wayne\"" 3) "version" 4) "1"我們在添加Redis作為存儲時還額外添加了Redis支持發布/訂閱功能,這個功能如何實現呢?這里可能就需要編寫額外程序實現了。我們這里采用官方的例子進行。訂閱在dapr中有兩種形式,一種是采用yaml聲明組件形式,另外一種則可以通過編寫代碼形式實現。當然第一種方式和第二種方式互有優劣,前者更適合無縫集成,后者方便開發控制。這里為了演示直觀性直接采用了編寫代碼方式實現。
package mainimport ("io""log""net/http""github.com/gin-gonic/gin" )func main() {r := gin.Default()r.GET("/dapr/subscribe", func(ctx *gin.Context) {ctx.JSON(http.StatusOK, []map[string]string{{"pubsubname": "redis-pubsub","topic": "deathStarStatus","route": "dsstatus",},})})r.POST("/dsstatus", func(c *gin.Context) {b, _ := io.ReadAll(c.Request.Body)defer c.Request.Body.Close()log.Println(string(b))c.JSON(http.StatusOK, map[string]interface{}{"success": true})})r.Run("127.0.0.1:5000") }使用如下命令啟動編譯后的daprdemo,注意指定文件名時需要填寫路徑或者在$PATH中:
# dapr --app-id subapp --app-port 5000 run ~/daprdemo在程序啟動日志中我們可以看到dapr會嘗試訪問一些默認的endpoint讀取可能的配置:
INFO[0000] application discovered on port 5000 app_id=subapp instance=127.0.0.1 scope=dapr.runtime type=log ver=1.0.1 == APP == [GIN] 2021/03/11 - 10:45:02 | 404 | 949ns | 127.0.0.1 | GET "/dapr/config"INFO[0000] application configuration loaded app_id=subapp instance=127.0.0.1 scope=dapr.runtime type=log ver=1.0.1 INFO[0000] actor runtime started. actor idle timeout: 1h0m0s. actor scan interval: 30s app_id=subapp instance=127.0.0.1 scope=dapr.runtime.actor type=log ver=1.0.1 == APP == [GIN] 2021/03/11 - 10:45:02 | 200 | 540.891μs | 127.0.0.1 | GET "/dapr/subscribe"INFO[0000] app is subscribed to the following topics: [deathStarStatus] through pubsub=redis-pubsub app_id=subapp instance=127.0.0.1 scope=dapr.runtime type=log ver=1.0.1 WARN[0000] redis streams: BUSYGROUP Consumer Group name already exists app_id=subapp instance=127.0.0.1 scope=dapr.contrib type=log ver=1.0.1 INFO[0000] dapr initialized. Status: Running. Init Elapsed 49.674504ms app_id=subapp instance=127.0.0.1 scope=dapr.runtime type=log ver=1.0.1接下來我們嘗試使用dapr-cli對我們之前啟動的myapp發送消息:
dapr publish --publish-app-id myapp --pubsub redis-pubsub --topic deathStarStatus --data '{"status": "completed"}'在程序日志中獲取到的輸出為:
== APP == [GIN] 2021/03/11 - 10:45:05 | 200 | 122.15μs | 127.0.0.1 | POST "/dsstatus"== APP == 2021/03/11 10:45:05 {"id":"9c237504-7cab-4a13-8582-92d9130fd016","source":"myapp","pubsubname":"redis-pubsub","traceid":"00-fba669a086f84650e882e3cadc55082c-ea466c080e359e68-00","data":{"status":"completed"},"specversion":"1.0","datacontenttype":"application/json","type":"com.dapr.event.sent","topic":"deathStarStatus"}當然,除了pub/sub方式,我們也可以借助dapr提供的路由功能,直接進行服務調用:
# curl http://127.0.0.1:3500/v1.0/invoke/subapp/method/dsstatus -X POST {"success":true}其他的組件功能則可以參考官方文檔中描述進行配置即可。
總結
dapr是一個功能強大的serverless運行時,除了上面提到的面向消息和請求存儲的功能以外,還可以控制程序的HTTP請求與gRPC請求等等。除了這些功能外,還包含了服務的管理,還有可觀測性支持等功能,是一個非常有潛力的運行時選擇。
相關文章:
Dapr能否引領云原生中間件的未來?
云原生 | 阿里巴巴的Dapr實踐與探索
Dapr | 云原生的抽象與實現
Dapr 可視化指南
Dapr 知多少 | 分布式應用運行時
Dapr 正式發布 1.0
Dapr 交通流量控制示例
Dapr是如何簡化微服務的開發和部署
微軟開源微服務運行時Dapr,賦能云原生應用開發
YARP實現Dapr服務調用的反向代理
Dapr微服務應用開發系列0:概述
Dapr微服務應用開發系列1:環境配置
Dapr微服務應用開發系列2:Hello World與SDK初接觸
Dapr微服務應用開發系列3:服務調用構件塊
Dapr微服務應用開發系列4:狀態管理構件塊
Dapr微服務應用開發系列5:發布訂閱構建塊
Windows環境下Dapr入門
云原生 | .NET 5 with Dapr 初體驗
通過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之OAuth2授權-百度版
通過Dapr實現一個簡單的基于.net的微服務電商系統(十)——一步一步教你如何擼Dapr之綁定
通過Dapr實現一個簡單的基于.net的微服務電商系統(十一)——一步一步教你如何擼Dapr之自動擴/縮容
WebAssembly + Dapr = 下一代云原生運行時?
dapr 應用開發 | 環境配置
乘風破浪,.Net Core遇見Dapr,為云原生而生的分布式應用運行時
Dapr案例之高德 Serverless 平臺建設及實踐
總結
以上是生活随笔為你收集整理的在非容器(集群)环境下运行dapr的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 记一次 .NET 某HIS系统后端服务
- 下一篇: ML.NET Cookbook:(1)如