Dapr牵手.NET学习笔记:状态管理之docker-compose发布
Dapr牽手.NET學習筆記:想入非非的服務調用
Dapr牽手.NET學習筆記:跨物理機負載均衡服務調用
Dapr牽手.NET學習筆記:用docker-compose部署服務
說明:為了給出demo的全貌,這篇有點長,如果有上一篇的基礎,會更容易閱讀一些。
在分布式應用,有狀態服務是常態,特別是多副本應用,就需要共用緩存來解決數據統一的狀況,所以dapr也把狀態管理做成一個標準組件。
下面通過docker-compose來發布OrderSystem項目和PaymentSystem項目,他們分別有自己的狀態數據,并且測試它們之間的訪問性。
下面是項目的目錄結構,components文件是dapr組件配置文件夾,B2C是docker-compose的文件夾
OrderSystem項目
HomeController.cs
using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using System; using System.Net; using System.Net.Http; using System.Threading.Tasks;namespace OrderSystem.Controllers; [ApiController] [Route("[controller]")] public class HomeController : ControllerBase {private readonly ILogger<HomeController> _logger;private readonly IHttpClientFactory _clientFactory;private readonly string? _payUrl;private readonly string _stateUrl;public HomeController(ILogger<HomeController> logger, IHttpClientFactory clientFactory, IConfiguration configuration){_stateUrl = configuration.GetSection("StateUrl").Value;_payUrl = configuration.GetSection("payurl").Value;_clientFactory = clientFactory;_logger = logger;}[HttpGet("/order")]public async Task<IActionResult> Order(){try{_logger.LogInformation($"下單開始");await Task.Delay(400);_logger.LogInformation($"訂單完成 調用支付系統");var client = _clientFactory.CreateClient();var content = await client.GetStringAsync(_payUrl);return new JsonResult(new { order_result = "訂單成功", pay_result = content });}catch (Exception exc){_logger.LogCritical(exc, exc.Message);return new JsonResult(new { order_result = "訂單成功,支付失敗", message = exc.Message });}}[HttpPost("/writekeys")]public async Task<IActionResult> WriteKeys([FromBody] KeyEntity[] keys){var client = _clientFactory.CreateClient();var jsonContent = System.Text.Json.JsonSerializer.Serialize(keys);var content = new StringContent(jsonContent);var response = await client.PostAsync(_stateUrl, content);return Ok(await response.Content.ReadAsStringAsync());}[HttpGet("/readekey/{key}")]public async Task<IActionResult> ReadKey(string key){var client = _clientFactory.CreateClient();var response = await client.GetAsync($"{_stateUrl}/{key}");return new JsonResult(new { key = await response.Content.ReadAsStringAsync(), host = Dns.GetHostName() });}[HttpPost("/readekeys")]public async Task<IActionResult> ReadKeys([FromBody] string[] keys){var client = _clientFactory.CreateClient();var jsonContent = System.Text.Json.JsonSerializer.Serialize(keys);var content = new StringContent(jsonContent);var response = await client.PostAsync($"{_stateUrl}/bulk", content);return Ok(await response.Content.ReadAsStringAsync());}[HttpDelete("/deletekey/{key}")]public async Task<IActionResult> DeleteData(string key){var client = _clientFactory.CreateClient();var response = await client.DeleteAsync($"{_stateUrl}/{key}");return Ok(await response.Content.ReadAsStringAsync());} } public class KeyEntity {public string Key { get; set; }public string Value { get; set; } }appsettings.json
{"Urls": "http://*:80","Logging": {"LogLevel": {"Default": "Information","Microsoft": "Warning","Microsoft.Hosting.Lifetime": "Information"}},"AllowedHosts": "*","PayUrl": "http://localhost:3500/v1.0/invoke/pay/method/pay","StateUrl": "http://localhost:3500/v1.0/state/statestore" }OrderSystem項目的Dockerfile
PaymentSystem項目
HomeControllers.cs與OrderSystem的狀態代碼是一樣的,這里就不占篇幅。
PaymentSystem項目的appsettings.json
{"Urls": "http://*:80","Logging": {"LogLevel": {"Default": "Information","Microsoft": "Warning","Microsoft.Hosting.Lifetime": "Information"}},"AllowedHosts": "*","StateUrl": "http://localhost:3500/v1.0/state/statestore" }PaymentSystem項目的Dockerfile
OrderSystem項目和PaymentSystem項目的Dockerfile中的路徑要和docker-compose.yml中的設置有關,所以分享出來,以供參考。
B2C
docker-compose.yml,這里定義了一個b2c-dapr,作為互通網絡,打通應用與redis等服務的通道。其中ordersystem對宿主機的端口還是3500,paymentsystem對宿主機的端口分別是3601,3602
Dapr組件配置
statestore.yaml,其中value的值要改成redis,而不是localhost,這里要連接同一個網絡里的redis服務
apiVersion: dapr.io/v1alpha1 kind: Component metadata:name: statestore spec:type: state.redisversion: v1metadata:- name: redisHostvalue: redis:6379- name: redisPasswordvalue: ""- name: actorStateStorevalue: "true"啟動docker-compose
docker-compose?up?-d
啟動后各服務的狀態
測試:
對order服務進行設置狀態,這里調用的是dpar服務調用對外的接口,3500是order服務sidecar對外端口。
同理調用order服務的狀態數據,返回設置的值
接下來測試從pay服務中調用order服務的狀態,返回結果為空,這里的地址為:localhost:3601/v1.0/invoke/pay/method/readekey/USER00001
下面換成從pay1服務的3601中訪問order服務的狀態,結果有值,url為localhost:3601/v1.0/invoke/order/method/readekey/USER00001,根本原因可能你想到了,這本質上調的還是order服務的接口,只不過是利用pay1的sidecar調用order的sidecar實現的,因為服務調用是通著,所以能調用到,這里可以通過查看返回的host值證明。
接下來測試pay服務,兩個副本,訪問狀態數據的case。下面是通過3601設置狀態。
通過pay1的sidecar對外端口訪問,url是localhost:3601/v1.0/invoke/pay/method/readekey/PAY00001
通過pay2的sidecar對外端口訪問,url是localhost:3602/v1.0/invoke/pay/method/readekey/PAY00001
可見狀態數據很好的被隔了,如果跨服務訪問狀態數據,可以通過服務開放api來實現。
最后看一眼redis數據吧,清晰的展示了服務和數據的關系。
總結
以上是生活随笔為你收集整理的Dapr牵手.NET学习笔记:状态管理之docker-compose发布的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .NET 6 中的 Configurat
- 下一篇: C# 通过正则表达式来限制控件输入有效性