面向.NET开发人员的Dapr——状态管理
目錄:
面向.NET開發(fā)人員的Dapr——前言
面向.NET開發(fā)人員的Dapr——分布式世界
面向.NET開發(fā)人員的Dapr——俯瞰Dapr
面向.NET開發(fā)人員的Dapr——入門
面向.NET開發(fā)人員的Dapr——參考應用程序
The Dapr state management building block
Dapr 狀態(tài)管理構建基塊
Distributed applications are composed of independent services. While each service should be stateless, some services must track state to complete business operations. Consider a shopping basket service for an e-Commerce site. If the service can't track state, the customer could loose the shopping basket content by leaving the website, resulting in a lost sale and an unhappy customer experience. For these scenarios, state needs to be persisted to a distributed state store. The?Dapr state management building block?simplifies state tracking and offers advanced features across various data stores.
分布式應用程序由獨立的服務組成。雖然每個服務都應該是無狀態(tài)的,但某些服務必須跟蹤狀態(tài)才能完成業(yè)務操作。請考慮電子商務網站的購物籃服務。如果服務無法跟蹤狀態(tài),則客戶可能因離開網站而丟失購物籃內容,導致失銷和客戶不滿。對于這些情況,需要將狀態(tài)保存到分布式狀態(tài)存儲中。?Dapr 狀態(tài)管理構建塊簡化了狀態(tài)跟蹤,并提供了跨各種數據存儲的高級功能。
To try out the state management building block, have a look at the?counter application sample in chapter 3.
若要試用狀態(tài)管理構建塊,請參閱?第3章中的計數器應用程序示例。
What it solves
解決方法
Tracking state in a distributed application can be challenging. For example:
The application may require different types of data stores.
Different consistency levels may be required for accessing and updating data.
Multiple users may update data at the same time, requiring conflict resolution.
Services must retry any short-lived?transient errors?that occur while interacting with the data store.
在分布式應用程序中跟蹤狀態(tài)具有挑戰(zhàn)性。例如:
應用可能需要不同類型的數據存儲。
訪問和更新數據時可能需要不同的一致性級別。
多個用戶可能同時更新數據,需要沖突解決。
在與數據存儲交互時,服務必須重試發(fā)生的任何短暫的?暫時性錯誤?。
The Dapr state management building block addresses these challenges. It streamlines tracking state without dependencies or a learning curve on third-party storage SDKs.
Dapr 狀態(tài)管理構建塊解決了這些難題。它簡化了跟蹤狀態(tài),而無需依賴或學習第三方存儲 Sdk 。
Important
重要
Dapr state management offers a?key/value?API. The feature doesn't support relational or graph data storage.
Dapr 狀態(tài)管理提供 鍵/值 API。此功能不支持關系數據存儲或圖數據存儲。
How it works
工作原理
The application interacts with a Dapr sidecar to store and retrieve key/value data. Under the hood, the sidecar API consumes a configurable state store component to persist data. Developers can choose from a growing collection of?supported state stores?that include Azure Cosmos DB, SQL Server, and Cassandra.
應用程序與 Dapr 邊車(sidecar)交互,以存儲和檢索鍵/值數據。在后臺,邊車 API 使用可配置的狀態(tài)存儲組件來持久保存數據。開發(fā)人員可以從不斷增長的?支持狀態(tài)存儲?集合中進行選擇,其中包括 Azure Cosmos DB、SQL Server 和 Cassandra。
The API can be called with either HTTP or gRPC. Use the following URL to call the HTTP API:
可以通過 HTTP 或 gRPC 調用 API。使用以下 URL 調用 HTTP API:
http://localhost:<dapr-port>/v1.0/state/<store-name>/<dapr-port>:Dapr 偵聽的 HTTP 端口。
<store-name>:要使用的狀態(tài)存儲組件的名稱。
Figure 5-1 shows how a Dapr-enabled shopping basket service stores a key/value pair using the Dapr state store component named?statestore.
圖5-1 顯示了 借助Dapr 的購物籃服務如何使用名為statestore?的 Dapr 狀態(tài)存儲組件來存儲鍵/值對?。
Figure 5-1. Storing a key/value pair in a Dapr state store.
圖 5-1。在 Dapr 狀態(tài)存儲中存儲鍵/值對。
Note the steps in the previous figure:
The basket service calls the state management API on the Dapr sidecar. The body of the request encloses a JSON array that can contain multiple key/value pairs.
The Dapr sidecar determines the state store based on the component configuration file. In this case, it's a Redis cache state store.
The sidecar persists the data to the Redis cache.
請注意上圖中的步驟:
購物籃服務在 Dapr 邊車上調用狀態(tài)管理 API。請求正文包含一個可包含多個鍵/值對的 JSON 數組。
Dapr 邊車基于組件配置文件確定狀態(tài)存儲。在這種情況下,它是一個 Redis 緩存狀態(tài)存儲。
邊車將數據保存到 Redis 緩存。
Retrieving the stored data is a similar API call. In the example below, a?curl?command retrieves the data by calling the Dapr sidecar API:
檢索存儲的數據使用類似的 API 調用。在下面的示例中,?curl命令通過調用 DAPR 邊車 API 來檢索數據:
curl http://localhost:3500/v1.0/state/statestore/basket1The command returns the stored state in the response body:
此命令將在響應正文中返回已存儲狀態(tài):
{"items": [{"itemId": "DaprHoodie","quantity": 1}],"customerId": 1 }The following ps explain how to use the more advanced features of the state management building block.
以下各節(jié)介紹如何使用狀態(tài)管理構建基塊的更高級的功能。
Consistency
一致性
The?CAP theorem?is a set of principles that apply to distributed systems that store state. Figure 5-2 shows the three properties of the CAP theorem.
CAP 定理是一組適用于分布式系統(tǒng)存儲狀態(tài)的原則。圖5-2 顯示了 CAP 定理的三個特性。
Figure 5-2. The CAP theorem.
圖 5-2。CAP 定理。
The theorem states that distributed data systems offer a trade-off between consistency, availability, and partition tolerance. And, that any datastore can only?guarantee two of the three properties:
Consistency?(C). Every node in the cluster responds with the most recent data, even if the system must block the request until all replicas update. If you query a "consistent system" for an item that is currently updating, you won't get a response until all replicas successfully update. However, you'll always receive the most current data.
Availability?(A). Every node returns an immediate response, even if that response isn't the most recent data. If you query an "available system" for an item that is updating, you'll get the best possible answer the service can provide at that moment.
Partition Tolerance?(P). Guarantees the system continues to operate even if a replicated data node fails or loses connectivity with other replicated data nodes.
定理指出,分布式數據系統(tǒng)提供一致性、可用性和分區(qū)容差之間的權衡。而且,任何數據存儲只能?保證三個特性中的兩個:
一致性?(C) 。群集中的每個節(jié)點都將使用最新的數據做出響應,在所有副本更新之前,系統(tǒng)都必須阻塞請求。如果在 "一致性系統(tǒng)"中查詢正在更新的項,則在所有副本都成功更新之前,將不會收到響應。但是,您將始終接收最新的數據。
可用性?(A)?。每個節(jié)點都立即返回響應,即使返回的不是最新數據。如果您在 "可用系統(tǒng)" 中查詢正在更新的項,則您將獲得該服務在此時可以提供的值。
分區(qū)容差?(P) 。保證系統(tǒng)可持續(xù)運行,即使某個副本數據節(jié)點發(fā)生故障或失去與其他副本數據節(jié)點的連接。
Distributed applications must handle the?P?property. As services communicate among each other with network calls, network disruptions (P) will occur. With that in mind, distributed applications must either be?AP?or?CP.
分布式應用程序必須滿足 P 特性。隨著服務彼此間的網絡調用通信,會發(fā)生網絡中斷 (P) 。考慮到這一點,分布式應用程序必須在 AP 或 CP中二選一。
AP?applications choose availability over consistency. Dapr supports this choice with its?eventual consistency?strategy. Consider an underlying data store, such as Azure CosmosDB, which stores redundant data on multiple replicas. With eventual consistency, the state store writes the update to one replica and completes the write request with the client. After this time, the store will asynchronously update its replicas. Read requests can return data from any of the replicas, including those replicas that haven't yet received the latest update.
AP 應用程序選擇 "可用性高于一致性"。Dapr 通過其?最終一致性?策略支持此選擇。請考慮使用底層數據存儲(例如 Azure CosmosDB)將冗余數據存儲在多個副本上。對于最終一致性,狀態(tài)存儲會將更新寫入一個副本并完成與客戶端的寫入請求。此后,存儲將以異步方式更新其它副本。讀取請求可以返回任何副本的數據,包括尚未收到最新更新的副本。
CP?applications choose consistency over availability. Dapr supports this choice with its?strong consistency?strategy. In this scenario, the state store will synchronously update?all?(or, in some cases, a?quorum?of) required replicas?before?completing the write request. Read operations will return the most up-to-date data consistently across replicas.
CP 應用程序選擇“一致性高于可用性”。Dapr 通過其?強一致性?策略支持此選擇。在此方案中,狀態(tài)存儲將在完成寫請求之前,同步更新?所有?(或在某些情況下,為規(guī)定數量) 必需副本。讀取操作將返回跨副本一致的最新數據。
The consistency level for a state operation is specified by attaching a?consistency hint?to the operation. The following?curl?command writes a?Hello=World?key/value pair to a state store using a strong consistency hint:
通過將?一致性提示?附加到操作來指定狀態(tài)操作的一致性級別。以下 curl 命令使用強一致性提示向狀態(tài)存儲寫入一個鍵/值對?Hello=World?:
curl -X POST http://localhost:3500/v1.0/state/<store-name> \-H "Content-Type: application/json" \-d '[{"key": "Hello","value": "World","options": {"consistency": "strong"}}]'Important
重要
It is up to the Dapr state store component to fulfill the consistency hint attached to the operation. Not all data stores support both consistency levels. If no consistency hint is set, the default behavior is?eventual.
這取決于Dapr 狀態(tài)存儲組件是否滿足附加在操作上的一致性提示。并非所有數據存儲都支持這兩種一致性級別。如果未設置任何一致性提示,則默認行為為最終一致性。
Concurrency
并發(fā)
In a multi-user application, there's a chance that multiple users will update the same data concurrently (at the same time). Dapr supports optimistic concurrency control (OCC) to manage conflicts. OCC is based on an assumption that update conflicts are uncommon because users work on different parts of the data. It's more efficient to assume an update will succeed and retry if it doesn't. The alternative, implementing pessimistic locking, can affect performance with long-running locking causing data contention.
在多用戶應用程序中,有可能多個用戶同時更新相同的數據。Dapr 支持樂觀并發(fā)控制 (OCC) 來管理沖突。OCC 基于一個假設,因為用戶處理數據的不同部分,所以更新沖突很少見。假設更新將成功,如果不成功,則重試,這樣更高效。另一個選擇是,實現(xiàn)悲觀鎖,長時間運行的鎖定會導致數據爭用,影響性能。
Dapr supports optimistic concurrency control (OCC) using ETags. An ETag is a value associated with a specific version of a stored key/value pair. Each time a key/value pair updates, the ETag value updates as well. When a client retrieves a key/value pair, the response includes the current ETag value. When a client updates or deletes a key/value pair, it must send that ETag value back in the request body. If another client has updated the data in the meantime, the ETags won't match and the request will fail. At this point, the client must retrieve the updated data, make the change again, and resubmit the update. This strategy is called?first-write-wins.
Dapr 使用 Etag支持樂觀并發(fā)控制。ETag 是與存儲的鍵/值對的特定版本相關聯(lián)的值。鍵/值對的每次更新時,ETag 值也會更新。當客戶端檢索鍵/值對時,返回的響應包括當前 ETag 值。當客戶端更新或刪除鍵/值對時,它必須在請求正文中發(fā)送該 ETag 值。如果在這期間其他客戶端更新了數據,則 Etag 不會匹配,請求將失敗。此時,客戶端必須檢索更新的數據,重新修改,然后重新提交更新。此策略稱為?先寫入勝出。
Dapr also supports a?last-write-wins?strategy. With this approach, the client doesn't attach an ETag to the write request. The state store component will always allow the update, even if the underlying value has changed during the session. Last-write-wins is useful for high-throughput write scenarios with low data contention. As well, overwriting an occasional user update can be tolerated.
Dapr 還支持后寫入勝出策略。使用此方法時,客戶端不會將 ETag 附加到寫入請求。狀態(tài)存儲組件將始終允許更新,即使基礎值在會話期間已更改也是如此。后寫入勝出對于數據爭用較少的高吞吐量寫入方案非常有用。同樣,偶爾覆蓋用戶更新是可以容忍的。
Transactions
事務
Dapr can write?multi-item changes?to a data store as a single operation implemented as a transaction. This functionality is only available for data stores that support?ACID?transactions. At the time of this writing, these stores include Redis, MongoDB, PostgreSQL, SQL Server, and Azure CosmosDB.
Dapr 可以將?多項更改?作為單項操作單個事務寫入數據存儲區(qū)。此功能僅適用于支持?ACID?事務的數據存儲。撰寫本文時,這些存儲包括 Redis、MongoDB、PostgreSQL、SQL Server 和 Azure CosmosDB。
In the example below, a multi-item operation is sent to the state store in a single transaction. All operations must succeed for the transaction to commit. If one or more of the operations fail, the entire transaction rolls back.
在下面的示例中,多項操作將作為單個事務發(fā)送到狀態(tài)存儲。所有操作必須全部成功才能提交事務。如果一個或多個操作失敗,則將回滾整個事務。
curl -X POST http://localhost:3500/v1.0/state/<store-name>/transaction \-H "Content-Type: application/json" \-d '{"operations": [{"operation": "upsert","request": { "key": "Key1", "value": "Value1"}},{"operation": "delete","request": { "key": "Key2" }}]}'For data stores that don't support transactions, multiple keys can still be sent as a single request. The following example shows a?bulk?write operation:
對于不支持事務的數據存儲,還可以將多個鍵作為單個請求發(fā)送。下面的示例演示了一個批量寫入操作:
curl -X POST http://localhost:3500/v1.0/state/<store-name> \-H "Content-Type: application/json" \-d '[{ "key": "Key1", "value": "Value1" },{ "key": "Key2", "value": "Value2" }]'For bulk operations, Dapr will submit each key/value pair update as a separate request to the data store.
對于批量操作,Dapr 會將每個鍵/值對更新作為單獨的請求提交到數據存儲區(qū)。
Use the Dapr .NET SDK
使用 Dapr .NET SDK
The Dapr .NET SDK provides language-specific support for .NET Core platform. Developers can use the?DaprClient?class introduced in?chapter 3?to read and write data. The following example shows how to use the?DaprClient.GetStateAsync<TValue>?method to read data from a state store. The method expects the store name,?statestore, and key,?AMS, as parameters:
Dapr .NET SDK 為 .NET Core 平臺提供特定于語言的支持。開發(fā)人員可以使用第3章?中引入的類?DaprClient?來讀取和寫入數據。下面的示例演示如何使用?DaprClient.GetStateAsync<TValue>?方法從狀態(tài)存儲中讀取數據。此方法要求使用存儲名稱(statestore?)和鍵(?AMS?)作為參數:
var weatherForecast = await daprClient.GetStateAsync<WeatherForecast>("statestore", "AMS");If the state store contains no data for key?AMS, the result will be?default(WeatherForecast).
如果狀態(tài)存儲不包含鍵為AMS的任何數據?,則結果將是?default(WeatherForecast)?。
To write data to the data store, use the?DaprClient.SaveStateAsync<TValue>?method:
若要將數據寫入數據存儲,請使用?DaprClient.SaveStateAsync<TValue>?方法:
daprClient.SaveStateAsync("statestore", "AMS", weatherForecast);The example uses the?last-write-wins?strategy as an ETag value isn't passed to the state store component. To use optimistic concurrency control (OCC) with a?first-write-wins?strategy, first retrieve the current ETag using the?DaprClient.GetStateAndETagAsync?method. Then write the updated value and pass along the retrieved ETag using the?DaprClient.TrySaveStateAsync?method.
該示例使用?后寫入勝出 策略,因為 ETag 值不傳遞到狀態(tài)存儲組件。若要使用樂觀并發(fā)控制 (使用?先寫入勝出 策略) ,請首先使用方法DaprClient.GetStateAndETagAsync檢索當前 ETag ?。然后,使用方法DaprClient.TrySaveStateAsync 寫入更新后的值并傳遞先前檢索到的 ETag ?。
var (weatherForecast, etag) = await daprClient.GetStateAndETagAsync<WeatherForecast>("statestore", city);// ... make some changes to the retrieved weather forecastvar result = await daprClient.TrySaveStateAsync("statestore", city, weatherForecast, etag);The?DaprClient.TrySaveStateAsync?method fails when the data (and associated ETag) has been changed in the state store after the data was retrieved. The method returns a boolean value to indicate whether the call succeeded. A strategy to handle the failure is to simply reload the updated data from the state store, make the change again, and resubmit the update.
如果在檢索數據后狀態(tài)存儲中更改了數據 (和關聯(lián)的 ETag) ,則DaprClient.TrySaveStateAsync方法將失敗。方法返回一個布爾值,指示調用是否成功。處理故障的策略是只需從狀態(tài)存儲重新加載已更新的數據,重新進行更改,然后重新提交更新。
If you always want a write to succeed regardless of other changes to the data, use the?last-write-wins?strategy.
如果你始終希望寫入成功,而不考慮數據的其他更改,請使用?后寫入勝出 策略。
The SDK provides other methods to retrieve data in bulk, delete data, and execute transactions. For more information, see the?Dapr .NET SDK repository.
SDK 提供了用于批量檢索數據、刪除數據和執(zhí)行事務的其他方法。有關詳細信息,請參閱?Dapr .NET SDK 存儲庫。
ASP.NET Core integration
ASP.NET Core 集成
Dapr also supports ASP.NET Core, a cross-platform framework for building modern cloud-based web applications. The Dapr SDK integrates state management capabilities directly into the?ASP.NET Core model binding?capabilities. Configuration is simple. Add the?IMVCBuilder.AddDapr?by appending the?.AddDapr?extension method in your?Startup.cs?class as shown in the next example:
Dapr 還支持 ASP.NET Core,這是一個跨平臺框架,用于構建基于云的現(xiàn)代 web 應用程序。Dapr SDK 直接將狀態(tài)管理功能集成到?ASP.NET Core 模型綁定。配置非常簡單。?通過?在Startup類中追加擴展方法.AddDapr來添加,如下面的示例中所示:
public void ConfigureServices(IServiceCollection services) {services.AddControllers().AddDapr(); }Once configured, Dapr can inject a key/value pair directly into a controller action using the ASP.NET Core?FromState?attribute. Referencing the?DaprClient?object is no longer necessary. The next example shows a Web API that returns the weather forecast for a given city:
配置后,Dapr 可以使用 ASP.NET Core??FromState 特性?將鍵/值對直接注入控制器操作。?不再需要引用對象DaprClient。下一個示例顯示了一個 Web API,該 API 返回給定城市的天氣預報:
[HttpGet("{city}")] public ActionResult<WeatherForecast> Get([FromState("statestore", "city")] StateEntry<WeatherForecast> forecast) {if (forecast.Value == null){return NotFound();}return forecast.Value; }In the example, the controller loads the weather forecast using the?FromState?attribute. The first attribute parameter is the state store,?statestore. The second attribute parameter,?city, is the name of the?route template?variable to get the state key. If you omit the second parameter, the name of the bound method parameter (forecast) is used to look up the route template variable.
在此示例中,控制器使用FromState特性加載天氣預報??。第一個特性參數是狀態(tài)存儲(statestore)?。第二個特性參數 (city?)是用于獲取狀態(tài)鍵的?路由模板?變量的名稱。如果省略第二個參數,則使用綁定方法參數的名稱 (forecast) 查找路由模板變量。
The?StateEntry?class contains properties for all the information that is retrieved for a single key/value pair:?StoreName,?Key,?Value, and?ETag. The ETag is useful for implementing optimistic concurrency control (OCC) strategy. The class also provides methods to delete or update retrieved key/value data without requiring a?DaprClient?instance. In the next example, the?TrySaveAsync?method is used to update the retrieved weather forecast using OCC.
StateEntry類包含被檢索的單個鍵/值對所有信息的屬性:?StoreName?、?Key?、?Value?和?ETag?。ETag 有助于實現(xiàn) (OCC) 策略的開放式并發(fā)控制。該類還提供了刪除或更新檢索到的鍵/值數據的方法,無需再使用?DaprClient?對象。在下一個示例中,?TrySaveAsync?方法用于使用 OCC 更新檢索到的天氣預報。
[HttpPut("{city}")] public async Task Put(WeatherForecast updatedForecast, [FromState("statestore", "city")] StateEntry<WeatherForecast> currentForecast) {// update cached current forecast with updated forecast passed into service endpointcurrentForecast.Value = updatedForecast;// update state storevar success = await currentForecast.TrySaveAsync();// ... check result }State store components
狀態(tài)存儲組件
At the time of this writing, Dapr provides support for the following transactional state stores:
在撰寫本文時,Dapr 為以下事務狀態(tài)存儲提供支持:
Azure CosmosDB
Azure SQL Server
MongoDB
PostgreSQL
Redis
Dapr also includes support for state stores that support CRUD operations, but not transactional capabilities:
Dapr 還包括對支持 CRUD 操作的狀態(tài)存儲的支持,但不支持事務功能:
Aerospike
Azure Blob Storage
Azure Table Storage
Cassandra
Cloudstate
Couchbase
etcd
Google Cloud Firestore
Hashicorp Consul
Hazelcast
Memcached
Zookeeper
Configuration
配置
When initialized for local, self-hosted development, Dapr registers Redis as the default state store. Here's an example of the default state store configuration. Note the default name,?statestore:
在為本地自承載開發(fā)初始化時,Dapr 將 Redis 注冊為默認的狀態(tài)存儲。下面是默認狀態(tài)存儲配置的示例。請注意默認名稱?statestore?:
apiVersion: dapr.io/v1alpha1 kind: Component metadata:name: statestore spec:type: state.redisversion: v1metadata:- name: redisHostvalue: localhost:6379- name: redisPasswordvalue: ""- name: actorStateStorevalue: "true"Note
備注
Many state stores can be registered to a single application each with a different name.
許多狀態(tài)存儲可以注冊到單個應用程序,每個應用程序都有不同的名稱。
The Redis state store requires?redisHost?and?redisPassword?metadata to connect to the Redis instance. In the example above, the Redis password (which is an empty string by default) is stored as a plain string. The best practice is to avoid clear-text strings and always use secret references. To learn more about secret management, see?chapter 10.
Redis 狀態(tài)存儲需要?redisHost?和?redisPassword?元數據來連接到 Redis 實例。在上面的示例中,Redis 密碼 (默認值為空字符串) 以純字符串形式存儲。最佳做法是避免使用明文并始終使用加密引用。若要了解有關機密管理的詳細信息,請參閱第?10 章。
The other metadata field,?actorStateStore, indicates whether the state store can be consumed by the actors building block.
其他元數據字段指示參與者構建塊actorStateStore 是否可以使用狀態(tài)存儲區(qū)。
Key prefix strategies
key前綴策略
State store components enable different strategies to store key/value pairs in the underlying store. Recall the earlier example of a shopping basket service storing items a customer wishes to purchase:
狀態(tài)存儲組件允許以不同的策略在底層存儲中存儲鍵/值對。回憶早期的購物車服務示例,其中存放了客戶希望購買的商品:
curl -X POST http://localhost:3500/v1.0/state/statestore \-H "Content-Type: application/json" \-d '[{"key": "basket1","value": {"customerId": 1,"items": [{ "itemId": "DaprHoodie", "quantity": 1 }]}}]'Using the Redis Console tool, look inside the Redis cache to see how the Redis state store component persisted the data:
使用 Redis 控制臺工具,進入 Redis 緩存里查看 Redis 狀態(tài)存儲組件如何保存數據:
127.0.0.1:6379> KEYS * 1) "basketservice||basket1"127.0.0.1:6379> HGETALL basketservice||basket1 1) "data" 2) "{\"items\":[{\"itemId\":\"DaprHoodie\",\"quantity\":1}],\"customerId\":1}" 3) "version" 4) "1"The output shows the full Redis?key?for the data as?basketservice||basket1. By default, Dapr uses the?application id?of the Dapr instance (basketservice) as a prefix for the key. This naming convention enables multiple Dapr instances to share the same data store without key name collisions. For the developer, it's critical always to specify the same?application id?when running the application with Dapr. If omitted, Dapr will generate a unique application ID. If the?application id?changes, the application can no longer access the state stored with the previous key prefix.
輸出顯示數據的完整 Redis?鍵?basketservice||basket1?。默認情況下,Dapr 使用Dapr 實例的?application id??(basketservice)?作為key的前綴 。此命名慣例允許多個 Dapr 實例共享相同的數據存儲,而不會發(fā)生鍵名稱沖突。對于開發(fā)人員來說,?在運行使用 Dapr 的應用程序時,指定相同的application id?是至關重要的。如果省略,則 Dapr 將生成唯一的application ?ID。如果更改了?application id?,應用程序將無法再訪問使用上一個key前綴存儲的狀態(tài)。
That said, it's possible to configure a?constant value?for the key prefix in the?keyPrefix?metadata field in the state store component file. Consider the following example:
即便如此,可以在狀態(tài)存儲組件配置文件中的keyprefix元數據字段中為key配置前綴。請看下面的示例:
spec:metadata:- name: keyPrefix- value: MyPrefixA constant key prefix enables the state store to be accessed across multiple Dapr applications. What's more, setting the?keyPrefix?to?none?omits the prefix completely.
使用常量key前綴可以跨多個 Dapr 應用程序訪問狀態(tài)存儲。更多操作,將?keyPrefix?設置為?none?完全省略前綴。
Reference application: eShopOnDapr
參考應用程序:eShopOnDapr
This book includes a reference application entitled?eShopOnDapr. It's modeled from an earlier Microsoft microservices reference application,?eShopOnContainers.
本書包括一個名為?eShopOnDapr?的參考應用程序。它從早期的 Microsoft 微服務參考應用程序?eShopOnContainers?進行建模。
The original?eShopOnContainers?architecture used an?IBasketRepository?interface to read and write data for the basket service. The?RedisBasketRepository?class provided the implementation using Redis as the underlying data store:
原始?eShopOnContainers?架構使用?IBasketRepository?接口來讀取和寫入購物車服務的數據。?RedisBasketRepository類提供了使用 Redis 作為底層數據存儲的實現(xiàn):
public class RedisBasketRepository : IBasketRepository {private readonly ConnectionMultiplexer _redis;private readonly IDatabase _database;public RedisBasketRepository(ConnectionMultiplexer redis){_redis = redis;_database = redis.GetDatabase();}public async Task<CustomerBasket> GetBasketAsync(string customerId){var data = await _database.StringGetAsync(customerId);if (data.IsNullOrEmpty){return null;}return JsonConvert.DeserializeObject<CustomerBasket>(data);}// ... }This code uses the third-party?StackExchange.Redis?NuGet package. The following steps are required to load the shopping basket for a given customer:
此代碼使用第三方?StackExchange.Redis?NuGet 包。若要為給定客戶加載購物籃,需執(zhí)行以下步驟:
Inject a?ConnectionMultiplexer?into the constructor. The?ConnectionMultiplexer?is registered with the dependency injection framework in the?Startup.cs?file:? ? ??將ConnectionMultiplexer?注入到構造函數中。?在?Startup.cs?文件中使用依賴注入框架注入ConnectionMultiplexer?:
services.AddSingleton<ConnectionMultiplexer>(sp => {var settings = sp.GetRequiredService<IOptions<BasketSettings>>().Value;var configuration = ConfigurationOptions.Parse(settings.ConnectionString, true);configuration.ResolveDns = true;return ConnectionMultiplexer.Connect(configuration); });Use the?ConnectionMultiplexer?to create an?IDatabase?instance in each consuming class.? ? ??使用?ConnectionMultiplexer 在每個使用類中創(chuàng)建?IDatabase?實例。
Use the?IDatabase?instance to execute a Redis StringGet call using the given?customerId?as the key.? ? ??使用給定的customerId?作為鍵,使用?IDatabase?實例執(zhí)行 Redis StringGet 調用 ,并傳參customerId?。
Check if data is loaded from Redis; if not, return?null.? ? ??檢查數據是否已從 Redis 加載;如果不是,則返回?null?。
Deserialize the data from Redis to a?CustomerBasket?object and return the result.? ? ??將 Redis 中的數據反序列化為?CustomerBasket?對象并返回。
In the updated?eShopOnDapr?reference application, a new?DaprBasketRepository?class replaces the?RedisBasketRepository?class:
在更新后的?eShopOnDapr?參考應用程序中,使用新?DaprBasketRepository?類替換?RedisBasketRepository?類:
public class DaprBasketRepository : IBasketRepository {private const string StoreName = "eshop-basket-statestore";private readonly DaprClient _daprClient;public DaprBasketRepository(DaprClient daprClient){_daprClient = daprClient ?? throw new ArgumentNullException(nameof(daprClient));;}public async Task<CustomerBasket> GetBasketAsync(string customerId){return await _daprClient.GetStateAsync<CustomerBasket>(StoreName, customerId);}// ... }The updated code uses the Dapr .NET SDK to read and write data using the state management building block. The new steps to load the basket for a customer are dramatically simplified:
Inject a?DaprClient?into the constructor. The?DaprClient?is registered with the dependency injection framework in the?Startup.cs?file.
Use the?DaprClient.GetStateAsync?method to load the customer's shopping basket items from the configured state store and return the result.
更新的代碼使用 Dapr .NET SDK,通過狀態(tài)管理構建塊讀取和寫入數據。為客戶加載購物籃的新步驟大大簡化:
將DaprClient?注入到構造函數中。?DaprClient注冊到文件中的依賴關系注入框架?Startup.cs?。
使用?DaprClient.GetStateAsync?方法從已配置的狀態(tài)存儲中加載客戶的購物籃項,并返回結果。
The updated implementation still uses Redis as the underlying data store. But, Dapr abstracts the?StackExchange.Redis?references and complexity from the application. A Dapr configuration file is all that's needed:
更新后的實現(xiàn)仍然使用 Redis 作為底層數據存儲。但是,Dapr 從應用程序中抽離了?StackExchange.Redis?引用和復雜性。Dapr 配置文件是必需的:
apiVersion: dapr.io/v1alpha1 kind: Component metadata:name: eshop-basket-statestorenamespace: eshop spec:type: state.redisversion: v1metadata:- name: redisHostvalue: redis:6379- name: redisPasswordsecretKeyRef:name: redisPassword auth:secretStore: eshop-secretstoreThe Dapr implementation also simplifies changing the underlying data store. For example, switching to Azure Table Storage requires only changing the contents of the configuration file. No code changes are necessary.
Dapr 實現(xiàn)還簡化了底層數據存儲的更改。例如,若要切換到 Azure 表存儲,只需更改配置文件的內容。不需要更改代碼。
Summary
摘要?
The Dapr state management building block offers an API for storing key/value data across various data stores. The API provides support for:
Bulk operations
Strong and eventual consistency
Optimistic concurrency control
Multi-item transactions
Dapr 狀態(tài)管理構建塊提供了一個 API,用于在各種數據存儲中存儲鍵/值數據。API 為以下內容提供支持:
批量操作
強一致性和最終一致性
樂觀并發(fā)控制
多項事務
The .NET SDK provides language-specific support for .NET Core and ASP.NET Core. Model binding integration simplifies accessing and updating state from ASP.NET Core controller action methods.
.NET SDK 為 .NET Core 和 ASP.NET Core 提供特定于語言的支持。模型綁定集成簡化了訪問和更新狀態(tài)(通過在ASP.NET Core 控制器操作方法中使用FromState特性)。
In the eShopOnDapr reference application, the benefits to moving to Dapr state management are clear:
The new implementation uses fewer lines of code.
It abstracts away the complexity of the third-party?StackExchange.Redis?API.
Replacing the underlying Redis cache with a different type of data store now only requires changes to the state store configuration file.
在 eShopOnDapr 參考應用程序中,轉向 Dapr 狀態(tài)管理的好處是顯而易見的:
新實現(xiàn)使用更少的代碼行。
它消除了第三方 API?StackExchange.Redis?的復雜性?。
只需要更改狀態(tài)存儲配置文件就可以替換底層數據存儲類型。
目錄:
面向.NET開發(fā)人員的Dapr——前言
面向.NET開發(fā)人員的Dapr——分布式世界
面向.NET開發(fā)人員的Dapr——俯瞰Dapr
面向.NET開發(fā)人員的Dapr——入門
面向.NET開發(fā)人員的Dapr——參考應用程序
總結
以上是生活随笔為你收集整理的面向.NET开发人员的Dapr——状态管理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 面向.NET开发人员的Dapr——目录
- 下一篇: NET问答: 为什么仅有 getter