面向.NET开发人员的Dapr——服务调用
目錄:
面向.NET開發人員的Dapr——前言
面向.NET開發人員的Dapr——分布式世界
面向.NET開發人員的Dapr——俯瞰Dapr
面向.NET開發人員的Dapr——入門
面向.NET開發人員的Dapr——參考應用程序
面向.NET開發人員的Dapr——狀態管理
The Dapr service invocation building block
Dapr 服務調用構建塊
Across a distributed system, one service often needs to communicate with another to complete a business operation. The?Dapr service invocation building block?can help streamline the communication between services.
在分布式系統中,一項服務通常需要與其他服務進行通信才能完成業務操作。?Dapr 服務調用構建塊可幫助簡化服務之間的通信。
What it solves
解決方法
Making calls between services in a distributed application may appear easy, but there are many challenges involved. For example:
Where the other services are located.
How to call a service securely, given the service address.
How to handle retries when short-lived?transient errors?occur.
在分布式應用程序中的服務之間進行調用可能會很簡單,但會涉及到許多挑戰。例如:
其他服務的位置。
在給定服務地址的情況下,如何安全地調用服務。
在發生短暫的?暫時性錯誤?時如何處理重試。
Lastly, as distributed applications compose many different services, capturing insights across service call graphs are critical to diagnosing production issues.
最后,分布式應用程序由許多不同的服務構成,跨服務調用圖洞察力對于診斷生產問題至關重要。
The service invocation building block addresses these challenges by using a Dapr sidecar as a?reverse proxy?for your service.
通過 Dapr 邊車作為服務的?反向代理?,使用服務調用構建塊來解決這些難題。
How it works
工作原理
Let's start with an example. Consider two services, "Service A" and "Service B". Service A needs to call the?catalog/items?API on Service B. While Service A could take a dependency on Service B and make a direct call to it, Service A instead invokes the service invocation API on the Dapr sidecar. Figure 6-1 shows the operation.
讓我們從一個示例開始。假設有兩個服務:"服務 A" 和 "服務 B"。服務 A 需要在服務 B 上調用 ?catalog/items?API。雖然服務 A 可能會依賴于服務 B 并直接對其進行調用,但此處服務 A 在 Dapr連車上調用服務調用 API。圖6-1 顯示了該操作。
Figure 6-1. How Dapr service invocation works.
圖 6-1. Dapr 服務調用的工作方式。
Note the steps from the previous figure:
請注意上圖中的步驟:
Service A makes a call to the?catalog/items?endpoint in Service B by invoking the service invocation API on the Service A sidecar.? ? ??服務 A?通過調用其邊車上的服務調用 API,來發出對服務B?終結點(catalog/items?)的請求。
Note? ? ??備注
The sidecar uses a pluggable name resolution mechanism to resolve the address of Service B. In self-hosted mode, Dapr uses?mDNS?to find it. When running in Kubernetes mode, the Kubernetes DNS service determines the address. ?? ? 邊車使用可插接式名稱解析機制來解析服務 B 的地址。在自承載模式下,Dapr 使用?mdn?來確定地址。在 Kubernetes 模式下運行時,Kubernetes DNS 服務將確定地址。
The Service A sidecar forwards the request to the Service B sidecar. ?? ??服務 A 的邊車將請求轉發到服務 B 的邊車。
The Service B sidecar makes the actual?catalog/items?request against the Service B API.? ? ??服務 B 的邊車對?服務 b 的終結點?catalog/items? 發出實際請求。
Service B executes the request and returns a response back to its sidecar. ?? ??服務 B 執行請求,并將響應返回給其邊車。
The Service B sidecar forwards the response back to the Service A sidecar. ?? ??服務 B 的邊車將響應轉發回服務A的邊車。
The Service A sidecar returns the response back to Service A. ?? ??服務 A 的連車將響應返回給服務 A。
Because the calls flow through sidecars, Dapr can inject some useful cross-cutting behaviors:
Automatically retry calls upon failure.
Make calls between services secure with mutual (mTLS) authentication, including automatic certificate rollover.
Control what operations clients can do using access control policies.
Capture traces and metrics for all calls between services to provide insights and diagnostics.
由于調用流過邊車,Dapr 可以注入一些有用的橫切(AOP思想)行為:
失敗時自動重試調用。
服務器之間調用時使用相互 (mTLS) 身份驗證(包括自動證書滾動更新)。
使用訪問控制策略控制客戶端可以執行的操作。
捕獲服務間所有調用的跟蹤和指標,以提供洞察和診斷。
Any application can invoke a Dapr sidecar by using the native?invoke?API built into Dapr. The API can be called with either HTTP or gRPC. Use the following URL to call the HTTP API:
任何應用程序都可以通過使用 Dapr 中內置的本機?調用 API 來調用 Dapr 邊車??梢酝ㄟ^ HTTP 或 gRPC 調用 API。使用以下 URL 調用 HTTP API:
http://localhost:<dapr-port>/v1.0/invoke/<application-id>/method/<method-name><dapr-port>?the HTTP port that Dapr is listening on. ?? ? Dapr 正在偵聽的 HTTP 端口。
<application-id>?application ID of the service to call. ?? ??要調用服務的應用程序 ID。
<method-name>?name of the method to invoke on the remote service. ?? ??要在遠程服務上調用的方法的名稱。
In the following example, a?curl?call is made to the?catalog/items?'GET' endpoint of?Service B:
在下面的示例中, 對?Service B?的終結點?catalog/items?發出了一個"GET"?調用:
curl http://localhost:3500/v1.0/invoke/serviceb/method/catalog/itemsNote
備注
The Dapr APIs enable any application stack that supports HTTP or gRPC to use Dapr building blocks. Therefore, the service invocation building block can act as a bridge between protocols. Services can communicate with each other using HTTP, gRPC or a combination of both.
Dapr Api允許支持 HTTP 或 gRPC 的任何應用程序堆棧以使用 Dapr 構建基塊。因此,服務調用構建塊可充當協議之間的橋梁。服務可以使用 HTTP、gRPC 或兩者的組合互相通信。
In the next p, you'll learn how to use the .NET SDK to simplify service invocation calls.
在下一節中,你將了解如何使用 .NET SDK 來簡化服務調用。
Use the Dapr .NET SDK
使用 Dapr .NET SDK
The Dapr?.NET SDK?provides .NET developers with an intuitive and language-specific way to interact with Dapr. The SDK offers developers three ways of making remote service invocation calls:
Invoke HTTP services using HttpClient
Invoke HTTP services using DaprClient
Invoke gRPC services using DaprClient
Dapr?.NET SDK?為 .net 開發人員提供了直觀的、特定于語言的方式來與 Dapr 交互。SDK 為開發人員提供了三種建立遠程服務調用的方式:
使用 HttpClient 調用 HTTP 服務
使用 DaprClient 調用 HTTP 服務
使用 DaprClient 調用 gRPC 服務
Invoke HTTP services using HttpClient
使用 HttpClient 調用 HTTP 服務
The preferred way to call an HTTP endpoint is to use Dapr's rich integration with?HttpClient. The following example submits an order by calling the?submit?method of the?orderservice?application:
調用 HTTP 終結點的首選方法是使用 Dapr 與?HttpClient?的富集成?。下面的示例通過調用訂單服務的?submit?方法來提交訂單?:
var httpClient = DaprClient.CreateHttpClient(); await httpClient.PostAsJsonAsync("http://orderservice/submit", order);In the example,?DaprClient.CreateHttpClient?returns an?HttpClient?instance that is used to perform Dapr service invocation. The returned?HttpClient?uses a special Dapr message handler that rewrites URIs of outgoing requests. The host name is interpreted as the application ID of the service to call. The rewritten request that's actually being called is:
在此示例中,?DaprClient.CreateHttpClient?返回?HttpClient的實例,?用于執行 Dapr 服務調用。返回的?HttpClient?使用特殊的 Dapr 消息處理程序,該處理程序會重寫傳出請求的 uri。"http://orderservice/submit"中的主機名被解釋為要調用的服務的應用程序 ID。實際調用的重寫請求為:
http://127.0.0.1:3500/v1/invoke/orderservice/method/submitThis example uses the default value for the Dapr HTTP endpoint, which is?http://127.0.0.1:<dapr-http-port>/. The value of?dapr-http-port?is taken from the?DAPR_HTTP_PORT?environment variable. If it's not set, the default port number?3500?is used.
此示例使用 Dapr HTTP 終結點的默認值,即?http://127.0.0.1:<dapr-http-port>/?。?dapr-http-port?的值取自環境變量?DAPR_HTTP_PORT?。如果未設置,則使用默認端口號?3500?。
Alternatively, you can configure a custom endpoint in the call to?DaprClient.CreateHttpClient:
或者,你可以在調用中配置自定義終結點?DaprClient.CreateHttpClient?:
var httpClient = DaprClient.CreateHttpClient(daprEndpoint = "localhost:4000");You can also directly set the base address by specifying the application ID. This makes it possible to use relative URIs when making a call:
還可以通過指定應用程序 ID 來直接設置基地址。這樣就可以在進行調用方法時使用相對 Uri:
var httpClient = DaprClient.CreateHttpClient("orderservice"); await httpClient.PostAsJsonAsync("/submit");The?HttpClient?object is intended to be long-lived. A single?HttpClient?instance can be reused for the lifetime of the application. The next scenario demonstrates how an?OrderServiceClient?class reuses a Dapr?HttpClient?instance:
HttpClient對象旨在長時間存在??梢栽趹贸绦虻纳嫫趦戎貜褪褂脝蝹€?HttpClient?實例。下一個方案演示了?OrderServiceClient?類如何重用 Dapr?HttpClient?實例:
public void ConfigureServices(IServiceCollection services) {// ...services.AddSingleton<IOrderServiceClient, OrderServiceClient>(_ => new OrderServiceClient(DaprClient.CreateInvokeHttpClient("orderservice"))); }In the snippet above, the?OrderServiceClient?is registered as a singleton with the ASP.NET Core dependency injection system. An implementation factory creates a new?HttpClient?instance by calling?DaprClient.CreateInvokeHttpClient. It then uses the newly created?HttpClient?to instantiate the?OrderServiceClient?object. By registering the?OrderServiceClient?as a singleton, it will be reused for the lifetime of the application.
在上面的代碼片段中,使用 ASP.NET Core 依賴關系注入系統將?OrderServiceClient?注冊為單一實例。服務工廠通過調用?DaprClient.CreateInvokeHttpClient?創建一個新的?HttpClient?實例。然后,它使用新創建的?HttpClient?來實例化?OrderServiceClient?對象。通過將OrderServiceClient?注冊?為單一實例,它將在應用程序的生存期內重復使用。
The?OrderServiceClient?itself has no Dapr-specific code. Even though Dapr service invocation is used under the hood, you can treat the Dapr HttpClient like any other HttpClient:
OrderServiceClient本身沒有特定于 Dapr 的代碼。即使在后臺使用 Dapr 服務調用,你也可以像處理任何其他 HttpClient 一樣處理 Dapr HttpClient:
public class OrderServiceClient : IOrderServiceClient {private readonly HttpClient _httpClient;public OrderServiceClient(HttpClient httpClient){_httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));}public async Task SubmitOrder(Order order){var response = await _httpClient.PostAsJsonAsync("submit", order);response.EnsureSuccessStatusCode();} }Using the HttpClient class with Dapr service invocation has many benefits:
HttpClient is a well-known class that many developers already use in their code. Using HttpClient for Dapr service invocation allows developers to reuse their existing skills.
HttpClient supports advanced scenarios, such as custom headers, and full control over request and response messages.
In .NET 5, HttpClient supports automatic serialization and deserialization using System.Text.Json.
HttpClient integrates with many existing frameworks and libraries, such as?Refit,?RestSharp, and?Polly.
通過HttpClient 類使用 Dapr 服務調用有很多好處:
HttpClient 是許多開發人員已在其代碼中使用的眾所周知的類。通過 HttpClient 使用 Dapr 服務調用,開發人員可重復使用其現有技能。
HttpClient 支持高級方案,如自定義標頭,以及對請求和響應消息的完全控制。
在 .NET 5 中,HttpClient 使用System.Text.Js 支持 自動序列化和反序列化。
HttpClient 集成了許多現有框架和庫 ,如Refit、?RestSharp和?Polly。
Invoke HTTP services using DaprClient
使用 DaprClient 調用 HTTP 服務
While HttpClient is the preferred way to invoke services using HTTP semantics, you can also use the?DaprClient.InvokeMethodAsync?family of methods. The following example submits an order by calling the?submit?method of the?orderservice?application:
盡管 通過HttpClient 使用 HTTP 語義調用服務是首選方法,但也可以使用?DaprClient.InvokeMethodAsync?方法族。下面的示例通過調用?orderservice?應用的submit?方法來提交訂單:
var daprClient = new DaprClientBuilder().Build(); try {var confirmation =await daprClient.InvokeMethodAsync<Order, OrderConfirmation>("orderservice", "submit", order); } catch (InvocationException ex) {// Handle error }The third argument, an?order?object, is serialized internally (with?System.Text.JsonSerializer) and sent as the request payload. The .NET SDK takes care of the call to the sidecar. It also deserializes the response to an?OrderConfirmation?object. Because no HTTP method is specified, the request is executed as an HTTP POST.
第三個參數(?order?對象)在內部序列化 (使用?System.Text.JsonSerializer) 并作為請求負載發送。.NET SDK 負責調用邊車。它還會反序列化響應為?OrderConfirmation對象?。由于未指定 HTTP 方法,因此將以 HTTP POST 的形式執行請求。
The next example demonstrates how you can make an HTTP GET request by specifying the?HttpMethod:
下一個示例演示如何通過指定http謂詞來發出 HTTP GET 請求:
var catalogItems = await daprClient.InvokeMethodAsync<IEnumerable<CatalogItem>>(HttpMethod.Get, "catalogservice", "items");For some scenarios, you may require more control over the request message. For example, when you need to specify request headers, or you want to use a custom serializer for the payload.?DaprClient.CreateInvokeMethodRequest?creates an?HttpRequestMessage. The following example demonstrates how to add an HTTP authorization header to a request message:
在某些情況下,可能需要對請求消息進行更多的控制。例如,當你需要指定請求標頭,或你想要有對負載使用自定義序列化時。?DaprClient.CreateInvokeMethodRequest?創建一個?HttpRequestMessage?。下面的示例演示如何在請求消息中增加 HTTP 授權標頭:
var request = daprClient.CreateInvokeMethodRequest("orderservice", "submit", order); request.Headers.Authorization = new AuthenticationHeaderValue("bearer", token);The?HttpRequestMessage?now has the following properties set:
Url =?http://127.0.0.1:3500/v1.0/invoke/orderservice/method/submit
HttpMethod = POST
Content =?JsonContent?object containing the JSON-serialized?order
Headers.Authorization = "bearer <token>"
HttpRequestMessage現在具有以下屬性集:
Url =?http://127.0.0.1:3500/v1.0/invoke/orderservice/method/submit
HttpMethod = POST
Content =?JsonContent?包含 order對象的json字符串
授權標頭= "bearer <token> "
Once you've got the request set up the way you want, use?DaprClient.InvokeMethodAsync?to send it:
按所需方式設置請求后,請使用?DaprClient.InvokeMethodAsync?發送此請求:
var orderConfirmation = await daprClient.InvokeMethodAsync<OrderConfirmation>(request);DaprClient.InvokeMethodAsync?deserializes the response to an?OrderConfirmation?object if the request is successful. Alternatively, you can use?DaprClient.InvokeMethodWithResponseAsync?to get full access to the underlying?HttpResponseMessage:
如果請求成功,DaprClient.InvokeMethodAsync?會反序列化響應 為OrderConfirmation?對象?;蛘?#xff0c;您可以使用?DaprClient.InvokeMethodWithResponseAsync?來獲取對HttpResponseMessage?底層的完全訪問權限?:
var response = await daprClient.InvokeMethodWithResponseAsync(request); response.EnsureSuccessStatusCode();var orderConfirmation = response.Content.ReadFromJsonAsync<OrderConfirmation>();Note
For service invocation calls using HTTP, it's worth considering using the Dapr HttpClient integration presented in the previous p. Using HttpClient gives you additional benefits such as integration with existing frameworks and libraries.
備注
對于使用 HTTP 的服務調用,有必要考慮使用上一節中介紹的 Dapr HttpClient 集成。使用 HttpClient 為你提供了更多好處,例如與現有框架和庫集成。
Invoke gRPC services using DaprClient
使用 DaprClient 調用 gRPC 服務
DaprClient provides a family of?InvokeMethodGrpcAsync?methods for calling gRPC endpoints. The main difference with the HTTP methods is the use of a Protobuf serializer instead of JSON. The following example invokes the?submitOrder?method of the?orderservice?over gRPC.
DaprClient 提供了一系列?InvokeMethodGrpcAsync?方法來調用 gRPC 終結點。與 HTTP 方法的主要區別是使用 Protobuf 序列化,而不是 JSON。下面的示例使用gRPC 調用訂單服務(orderservice)的?submitOrder?方法?。
var daprClient = new DaprClientBuilder().Build(); try {var confirmation = await daprClient.InvokeMethodGrpcAsync<Order, OrderConfirmation>("orderservice", "submitOrder", order); } catch (InvocationException ex) {// Handle error }In the example above, DaprClient serializes the given?order?object using?Protobuf?and uses the result as the gRPC request body. Likewise, the response body is Protobuf deserialized and returned to the caller. Protobuf typically provides better performance than the JSON payloads used in HTTP service invocation.
在上面的示例中,DaprClient?使用?Protobuf?序列化給定order?對象,并使用序列化結果作為 gRPC 請求正文。同樣,響應正文使用 Protobuf 反序列化并返回給調用方。與 HTTP 服務調用中使用的 JSON 負載相比,Protobuf 通常提供更好的性能。
Reference application: eShopOnDapr
參考應用:eShopOnDapr
The original?eShopOnContainers?microservice reference architecture from Microsoft used a mix of HTTP/REST and gRPC services. The use of gRPC was limited to communication between an?aggregator service?and core back-end services. Figure 6-2 show the architecture:
Microsoft 的原始?eShopOnContainers?微服務參考架構混合使用了 HTTP/REST 和 gRPC 服務。gRPC的使用 僅限于?聚合器服務?與核心后端服務之間的通信。圖6-2 顯示了該架構:
Figure 6-2. gRPC and HTTP/REST calls in eShopOnContainers.
圖 6-2. eShopOnContainers 中的 gRPC 和 HTTP/REST 調用。
Note the steps from the previous figure:
The front end calls the?API gateway?using HTTP/REST.
The API gateway forwards simple?CRUD?(Create, Read, Update, Delete) requests directly to a core back-end service using HTTP/REST.
The API gateway forwards complex requests that involve coordinated calls to multiple back-end services to the web shopping aggregator service.
The aggregator service uses gRPC to call core back-end services.
請注意上圖中的步驟:
前端使用 HTTP/REST 調用?API 網關?。
API 網關直接轉發簡單的?CRUD?(使用 HTTP/REST 將) 請求到核心后端服務。
API 網關將涉及多個后端服務的協調調用的復雜請求轉發到 web 購物聚合器服務。
聚合器服務使用 gRPC 來調用核心后端服務。
In the recently updated eShopOnDapr implementation, Dapr sidecars are added to the services and API gateway. Figure 6-3 show the updated architecture:
在最近更新的 eShopOnDapr 實現中,Dapr 邊車被添加到各個服務和 API 網關。圖6-3 顯示了更新后的架構:
Figure 6-3. Updated eShop architecture using Dapr.
圖 6-3。使用 Dapr 的 eShop 架構。
Note the updated steps from the previous figure:
The front end still uses HTTP/REST to call the API gateway.
The API gateway forwards HTTP requests to its Dapr sidecar.
The API gateway sidecar sends the request to the sidecar of the aggregator or back-end service.
The aggregator service uses the Dapr .NET SDK to call back-end services through their sidecar architecture.
請注意上圖中更新了的步驟:
前端仍使用 HTTP/REST 調用 API 網關。
API 網關將 HTTP 請求轉發到其 Dapr 邊車。
API 網關邊車將請求發送到聚合器或后端服務的邊車。
聚合器服務使用 Dapr .NET SDK 通過其邊車調用后端服務。
Dapr implements calls between sidecars with gRPC. So even if you're invoking a remote service with HTTP/REST semantics, a part of the transport is still implemented using gRPC.
Dapr 使用 gRPC 實現連車之間的調用。因此,即使你使用 HTTP/REST 語義調用遠程服務,也仍然會在微服務間使用 gRPC 來交互。
The eShopOnDapr reference application benefits from the Dapr service invocation building block. The benefits include service discovery, automatic mTLS, and observability.
Dapr 服務調用構建塊為eSheopOnDapr參考應用帶來的優點包括服務發現、自動 mTLS 和可觀察性。
Forward HTTP requests using Envoy and Dapr
使用 Envoy 和 Dapr 轉發 HTTP 請求
Both the original and updated eShop application leverage the?Envoy proxy?as an API gateway. Envoy is an open-source proxy and communication bus that is popular across modern distributed applications. Originating from Lyft, Envoy is owned and maintained by the?Cloud-Native Computing Foundation.
eShopOnContainers和eShopOnDapr都將?Envoy?Proxy 用作 API 網關。Envoy 是一個 開放源代碼和跨現代分布式應用程序常用的通信總線。源自 Lyft,Envoy 由?云原生計算基礎擁有和維護。
In the original eShopOnContainers implementation, the Envoy API gateway forwarded incoming HTTP requests directly to aggregator or back-end services. In the new eShopOnDapr, the Envoy proxy forwards the request to a Dapr sidecar. The sidecar provides service invocation, mTLS, and observability.
在原始 eShopOnContainers 實現中,Envoy API 網關會將傳入的 HTTP 請求直接轉發到聚合器或后端服務。在 新的eShopOnDapr 中,Envoy 代理將請求轉發到 Dapr 邊車。邊車提供服務調用、mTLS 和可觀察性。
Envoy is configured using a YAML definition file to control the proxy's behavior. To enable Envoy to forward HTTP requests to a Dapr sidecar container, a?dapr?cluster is added to the configuration. The cluster configuration contains a host that points to the HTTP port on which the Dapr sidecar is listening:
使用 YAML 定義文件對 Envoy 進行配置,以控制代理的行為。為了使 Envoy 能夠將 HTTP 請求轉發到 Dapr 邊車容器,會將一個?dapr?集群添加到配置中。集群配置包含一個主機,該主機指向 Dapr 邊車正在偵聽的 HTTP 端口:
clusters: - name: daprconnect_timeout: 0.25stype: strict_dnshosts:- socket_address:address: 127.0.0.1port_value: 3500The Envoy routes configuration is updated to rewrite incoming requests as calls to the Dapr sidecar (pay close attention to the?prefix_rewrite?key/value pair):
更新 Envoy 路由配置,以將傳入請求重寫為對 Dapr 邊車的調用, (請注意?prefix_rewrite?鍵/值對) :
- name: "c-short"match:prefix: "/c/"route:auto_host_rewrite: trueprefix_rewrite: "/v1.0/invoke/catalog-api/method/"cluster: daprConsider a scenario where the front-end client wants to retrieve a list of catalog items. The Catalog API provides an endpoint for getting the catalog items:
假設前端客戶端要檢索目錄項。Catalog API ?提供用于獲取目錄項的終結點:
[Route("api/v1/[controller]")] [ApiController] public class CatalogController : ControllerBase {[HttpGet("items")]public async Task<IActionResult> ItemsAsync([FromQuery] int pageSize = 10,[FromQuery] int pageIndex = 0){// ...}First, the front end makes a direct HTTP call to the Envoy API gateway.
首先,前端直接使用http調用 Envoy API 網關。
GET http://<api-gateway>/c/api/v1/catalog/items?pageSize=20The Envoy proxy matches the route, rewrites the HTTP request, and forwards it to the?invoke?API of its Dapr sidecar:
?Envoy 代理匹配路由,重寫 HTTP 請求,并將請求轉發到其Dapr 邊車的服務調用API:
GET http://127.0.0.1:3500/v1.0/invoke/catalog-api/method/api/v1/catalog/items?pageSize=20The sidecar handles service discovery and routes the request to the Catalog API sidecar. Finally, the sidecar calls the Catalog API to execute the request, fetch catalog items, and return a response:
?網關Envoy 的邊車進行服務發現并將請求路由到Catalog API 的邊車。最后,Catalog API 的邊車調用Catalog API 來執行請求、提取目錄項并返回響應:
GET http://localhost/api/v1/catalog/items?pageSize=20Make aggregated service calls using the .NET SDK
使用 .NET SDK 進行聚合服務調用
Most calls from the eShop front end are simple CRUD calls. The API gateway forwards them to a single service for processing. Some scenarios, however, require multiple back-end services to work together to complete a request. For these more complex calls, eShop uses the web shopping aggregator service to mediate the workflow across multiple services. Figure 6-4 show the processing sequence of adding an item to your shopping basket:
EShop 前端的大多數調用都是簡單的 CRUD 調用。API 網關將它們轉發給單個服務進行處理。但在某些情況下,需要多個后端服務協調工作來完成請求。對于更復雜的調用,eShop 使用 web 購物聚合器服務來跨多個服務協調工作流。圖6-4 顯示了將商品添加到購物籃的序列圖:
Figure 6-4. Update shopping basket sequence.
圖 6-4 。更新購物籃序列圖。
The aggregator service first retrieves catalog items from the Catalog API. It then validates item availability and pricing. Finally, the aggregator service saves the updated shopping basket by calling the Basket API.
聚合器服務首先從Catalog ?API 中檢索目錄項。然后,它將驗證商品的是否可用(是否有效)和價格。最后,聚合器服務通過調用Basket ?API 來保存更新后的購物車。
The aggregator service contains a?BasketController?that provides an endpoint for updating the shopping basket:
聚合器服務包含一個?BasketController?,它提供用于更新購物籃的終結點:
[Route("api/v1/[controller]")] [Authorize] [ApiController] public class BasketController : ControllerBase {private readonly ICatalogService _catalog;private readonly IBasketService _basket;[HttpPost][HttpPut]public async Task<ActionResult<BasketData>> UpdateAllBasketAsync([FromBody] UpdateBasketRequest data, [FromHeader] string authorization){// Get the item details from the catalog API.var catalogItems = await _catalog.GetCatalogItemsAsync(data.Items.Select(x => x.ProductId));// Check item availability and prices; store results in basket object.var basket = CreateValidatedBasket(data, catalogItems);// Save the shopping basket.await _basket.UpdateAsync(basket, authorization);return basket;}// ... }The?UpdateAllBasketAsync?method gets the?Authorization?header of the incoming request using a?FromHeader?attribute. The?Authorization?header contains the access token that is needed to call protected back-end services.
UpdateAllBasketAsync方法使用FromHeader?特性獲取傳入請求的?Authorization?標頭?。?Authorization?標頭包含調用受保護的后端服務所需的訪問令牌。
After receiving a request to update the basket, the aggregator service calls the Catalog API to get the item details. The Basket controller uses an injected?ICatalogService?object to make that call and communicate with the Catalog API. The original implementation of the interface used gRPC to make the call. The updated implementation uses Dapr service invocation with HttpClient support:
收到更新購物籃的請求后,聚合器服務將調用Catalog API 以獲取商品詳細信息。購物籃控制器使用注入的?ICatalogService?對象與Catalog API 通信。?ICatalogService?接口的原始實現使用 gRPC 進行調用。更新了的實現結合使用 Dapr 服務調用與 HttpClient 支持:
public class CatalogService : ICatalogService {private readonly HttpClient _httpClient;public CatalogService(HttpClient httpClient){_httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));}public Task<IEnumerable<CatalogItem>> GetCatalogItemsAsync(IEnumerable<int> ids){var requestUri = $"api/v1/catalog/items?ids={string.Join(",", ids)}";return _httpClient.GetFromJsonAsync<IEnumerable<CatalogItem>>(requestUri);}// ... }Notice how no Dapr specific code is required to make the service invocation call. All communication is done using the standard HttpClient object.
請注意,不需要 Dapr 特定的代碼就可以調用服務調用。所有通信都是使用標準 HttpClient 對象完成的。
The Dapr HttpClient is injected into the?CatalogService?class in the?Startup.ConfigureServices?method:
在?Startup.ConfigureServices?方法中將 Dapr HttpClient 注入?CatalogService?類:
services.AddSingleton<ICatalogService, CatalogService>(_ => new CatalogService(DaprClient.CreateInvokeHttpClient("catalog-api")));The other call made by the aggregator service is to the Basket API. It only allows authorized requests. The access token is passed along in an?Authorization?request header to ensure the call succeeds:
聚合器服務還調用Basket API。它只允許授權的請求。在?授權?請求標頭中傳遞訪問令牌,以確保調用成功:
public class BasketService : IBasketService {public Task UpdateAsync(BasketData currentBasket, string accessToken){var request = new HttpRequestMessage(HttpMethod.Post, "api/v1/basket"){Content = JsonContent.Create(currentBasket)};request.Headers.Authorization = new AuthenticationHeaderValue(accessToken);var response = await _httpClient.SendAsync(request);response.EnsureSuccessStatusCode();}// ... }In this example too, only standard HttpClient functionality is used to call the service. This allows developers who are already familiar with HttpClient to reuse their existing skills. It even enables existing HttpClient code to use Dapr service invocation without making any changes.
在此示例中,僅使用標準 HttpClient 功能來調用服務。這樣,已經熟悉 HttpClient 的開發人員就可以重復使用其現有技能。甚至現有的 HttpClient 代碼可以用于 Dapr 服務調用,而無需進行任何更改。
Summary
總結
In this chapter, you learned about the service invocation building block. You saw how to invoke remote methods both by making direct HTTP calls to the Dapr sidecar, and by using the Dapr .NET SDK.
本章介紹了服務調用構建塊。你已了解如何通過直接 HTTP 調用 Dapr 邊車并使用 Dapr .NET SDK 調用遠程方法。
The Dapr .NET SDK provides multiple ways to invoke remote methods. HttpClient support is great for developers wanting to reuse existing skills and is compatible with many existing frameworks and libraries. DaprClient offers support for directly using the Dapr service invocation API using either HTTP or gRPC semantics.
Dapr .NET SDK 提供了多種方法來調用遠程方法。HttpClient 支持對于需要重復使用現有技能的開發人員非常有用,并且與許多現有框架和庫兼容。DaprClient 提供通過 HTTP 或 gRPC 語義直接使用 Dapr 服務調用 API 的支持。
The eShopOnDapr reference architecture shows how the original eShopOnContainers solution is modernized by using Dapr service invocation. Adding Dapr to eShop provides benefits such as automatic retries, message encryption using mTLS, and improved observability.
EShopOnDapr 參考架構顯示了如何使用 Dapr 服務調用優化原始 eShopOnContainers 解決方案。將 Dapr 添加到 eShop 提供了一些優點,例如自動重試、使用 mTLS 進行消息加密,以及改進的可觀察性。
目錄:
面向.NET開發人員的Dapr——前言
面向.NET開發人員的Dapr——分布式世界
面向.NET開發人員的Dapr——俯瞰Dapr
面向.NET開發人員的Dapr——入門
面向.NET開發人員的Dapr——參考應用程序
面向.NET開發人員的Dapr——狀態管理
總結
以上是生活随笔為你收集整理的面向.NET开发人员的Dapr——服务调用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 面向.NET开发人员的Dapr——绑定
- 下一篇: 面向.NET开发人员的Dapr——发布和