在這一篇文章將說明在 Dapr 架構下,不同服務之間如何調用,並且以 .NET Core SDK 進行實作。我們將延續上一篇 Dapr 服務調用 (Service invocation) 基本篇 實作內容 (建議您先完成),再建立一個新的 FrontEndWebAPI 與既有 WebAPI  進行互動。 若您還不知道什麼是 Dapr,建議您先閱讀 Dapr 基礎觀念介紹與建立環境


服務調用運作原理




在上一篇文章中,我們已經了解如何使用 Dapr Invoke API 進行服務調用,但應用程式與應用程式之間並不直接使用 localhost:port 來進行互動,而是透過 dapr 啟動服務時指定的 app-id。如上圖所示,服務 A 呼叫 服務 B 時,dapr 會解析 Service B 名稱,進而直接與 Service B 的 dapr 進行溝通。



建構 Dapr.Client 服務

前置作業: 下載範本程式 - https://github.com/matsurigoto/DaprDemo-Original

步驟 1. 點選 工具 > NuGet 套件管理員 > 管理方案的 NuGet 套件...




步驟 2. 搜尋輸入 dapr,選擇 DaprClient 專案安裝 Dapr.Client 套件 


步驟 3. 接下來,我們要以 HttpClient 與 DaprClient 來調用服務,右鍵點選 Controller > 加入 > 控制器





步驟 4. 選擇 API 控制器 - 空白,名稱輸入 DaprController





步驟 5. 貼上下列程式碼

你可以看見在第 16 行程式,我們使用 DaprClient.CreateInvokeHttpClient(); 取得 HttpClient,並在17行直接以 app-id 調用 webapi 服務;在第 27 程式,我們使用 DaprClient Invoke Method,也是直接以 app-id 調用 webapi 服務

using Dapr.Client;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
namespace DaprClientDemo.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class DaprController : ControllerBase
{
[HttpGet("HttpClient")]
public async Task<ActionResult> GetHttpClientResultAsync()
{
using var httpClient = DaprClient.CreateInvokeHttpClient();
var result = await httpClient.GetAsync("http://webapi/WeatherForecast");
var resultContent = string.Format("result is {0} {1}", result.StatusCode, await result.Content.ReadAsStringAsync());
return Ok(resultContent);
}
[HttpGet("DaprClient")]
public async Task<ActionResult> GetDaprClientResultAsync()
{
using var daprClient = new DaprClientBuilder().Build();
var result = await daprClient.InvokeMethodAsync<IEnumerable<WeatherForecast>>(HttpMethod.Get, "webapi", "WeatherForecast");
return Ok(result);
}
}
}



理所當然,您也可以使用相依性注入方式使用 DaprClient,一樣 點選 工具 > NuGet 套件管理員 > 管理方案的 NuGet 套件...,這次我們安裝 Dapr.AspNetCore





步驟 6. 開啟 Startup.cs 找到 ConfigureServices,找到 services.AddControllers(),更改成 services.AddControllers().AddDapr();




步驟 7. 加上建構子,您可以完整的複製貼上以下程式碼

我們在第 13-18 行進行建構子注入後,即可在此 controller 內直接使用 dapr invoke method 方法,如第 40 行程式

using Dapr.Client;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
namespace DaprClientDemo.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class DaprController : ControllerBase
{
private readonly DaprClient _daprClient;
public DaprController(DaprClient daprClient)
{
_daprClient = daprClient;
}
[HttpGet("HttpClient")]
public async Task<ActionResult> GetHttpClientResultAsync()
{
using var httpClient = DaprClient.CreateInvokeHttpClient();
var result = await httpClient.GetAsync("http://webapi/WeatherForecast");
var resultContent = string.Format("result is {0} {1}", result.StatusCode, await result.Content.ReadAsStringAsync());
return Ok(resultContent);
}
[HttpGet("DaprClient")]
public async Task<ActionResult> GetDaprClientResultAsync()
{
using var daprClient = new DaprClientBuilder().Build();
var result = await daprClient.InvokeMethodAsync<IEnumerable<WeatherForecast>>(HttpMethod.Get, "webapi", "WeatherForecast");
return Ok(result);
}
[HttpGet("DaprClientWithDI")]
public async Task<ActionResult> GetDaprClientWithDIResultAsync()
{
var result = await _daprClient.InvokeMethodAsync<IEnumerable<WeatherForecast>>(HttpMethod.Get, "webapi", "WeatherForecast");
return Ok(result);
}
}
}




步驟 8. 右鍵點選方案檔案,選擇建置方案





步驟 9. 開啟命令提示字元,切換到你的專案,





步驟 10. 我們先啟動 DaprWebAPIDemo ,輸入下列指令,

dapr run --app-id webapi --app-port 5100 --dapr-http-port 3500 -- dotnet DaprWebAPIDemo\bin\Debug\netcoreapp3.1\DaprWebAPIDemo.dll --urls=http://localhost:5100/


以瀏覽器開啟 http://localhost:3500/v1.0/invoke/webapi/method/WeatherForecast 進行瀏覽...





步驟 11. 接下來啟動 DaprClientDemo,開啟另一個命令提示字元,切換到相同目錄,輸入下列指令


dapr run --app-id client --app-port 5200 --dapr-http-port 3501 -- dotnet DaprClientDemo\bin\Debug\netcoreapp3.1\DaprClientDemo.dll --urls=http://localhost:5200



步驟 12. 以瀏覽器開啟 http://localhost:3501/v1.0/invoke/client/method/api/dapr/HttpClient 進行瀏覽...




zipkin 檢視關聯

開啟瀏覽器,輸入 http://localhost:9411/,開啟 zipkin (分散式追蹤系統),這次我們點開 Dependencies 進行搜尋,即可看見服務之間的關係。