使用Dapr 客户端 处理服务调用,需要遵循的他的模式,通常代码是这个样子的:

var client = DaprClient.CreateInvokeHttpClient(appId: "routing");
var response = await client.GetAsJsonAsync($"/accounts/{17}", cancellationToken);
var account = await response.Content.ReadFromJsonAsync<Account>(cancellationToken: cancellationToken);

我更希望是这样子调用:

public interface IBank

{
            [HttpGet("/accounts/{accountId}")]
            Task<Account> GetUser(string accountId, CancellationToken cancellationToken = default);

[HttpPost("/deposit")]
            Task<Account> Deposit([JsonContent] Transaction transaction, CancellationToken cancellationToken = default);

[HttpPost("/withdraw")]
            [RawReturn(Enable =true, EnsureSuccessStatusCode = false)]
            Task<HttpResponseMessage> Withdraw([JsonContent] Transaction transaction, CancellationToken cancellationToken = default);

}

var account = await bankClient.GetUser("17", cancellationToken);

我们可以用 RefitRestEase 或者是 WebApiClientCore 来达到这样的效果, 那么在Dapr 里面使用这些库如何做到呢, 在Dapr的客户端库里面有一个Handler 的官方实现:InvocationHandler。 搭配这个InvocationHandler 就可以和这几个库,在本文中,我们重点介绍Dapr Client 如何搭配 WebApiClientCore

public interface IBank
{
          [HttpGet("/accounts/{accountId}")]
          Task<Account> GetUser(string accountId, CancellationToken cancellationToken = default);

[HttpPost("/deposit")]
          Task<Account> Deposit([JsonContent] Transaction transaction, CancellationToken cancellationToken = default);

[HttpPost("/withdraw")]
          [RawReturn(Enable =true, EnsureSuccessStatusCode = false)]
          Task<HttpResponseMessage> Withdraw([JsonContent] Transaction transaction, CancellationToken cancellationToken = default);
}

public class WebapiClientExample : Example
   {
       public override string DisplayName => "WebapiClient";

private IBank bankClient;

public WebapiClientExample(IBank bank)
       {
           bankClient = bank;
       }

public override async Task RunAsync(CancellationToken cancellationToken)
       {
           var options = new JsonSerializerOptions(JsonSerializerDefaults.Web);

// Scenario 1: Check if the account already exists.
           Account? account = null;
           try
           {
               account = await bankClient.GetUser("17", cancellationToken);
           }
           catch (ApiException ex)
           {
               // Account does not exist.
           }

Console.WriteLine($"Scenario 1: account '17' {(account is null ? "does not exist" : "already exists")}");

// Scenario 2: Deposit some money
           var transaction = new Transaction()
           {
               Amount = 100m,
               Id = "17",
           };

// read updated balance
           account = await bankClient.Deposit(transaction, cancellationToken);
           Console.WriteLine($"Scenario 2: account '17' has '{account?.Balance}' money");

// Scenario 3: Handle a validation error without exceptions
           transaction = new Transaction()
           {
               Amount = 1_000_000m,
               Id = "17",
           };
           HttpResponseMessage response = null;

response = await bankClient.Withdraw(transaction, cancellationToken);
           if (response.StatusCode != HttpStatusCode.BadRequest)
           {
               // We don't actually expect this example to succeed - we expect a 400
               Console.WriteLine("Something went wrong :(");
               return;
           }
           var problem = await response.Content.ReadFromJsonAsync<ProblemDetails>(cancellationToken: cancellationToken);
           Console.WriteLine($"Scenario 3: got the following errors:");
           foreach (var kvp in problem!.Errors)
           {
               Console.WriteLine($"{kvp.Key}: {string.Join(", ", kvp.Value)}");
           }
       }
   }

var services = new ServiceCollection();
             services.AddTransient<Example, WebapiClientExample>();
             services.AddLogging();

services
                 .AddScoped<InvocationHandler>()
                 .AddHttpApi<WebapiClientExample.IBank>(o => o.HttpHost = new Uri("http://bank"))
                 .AddHttpMessageHandler<InvocationHandler>();
            var serviceprovider = services.BuildServiceProvider();

代码的核心部分就在于上面红色的部分,我们把InvocationHandler 加入到AddHttpApi ,就可以和 dapr 一起玩耍了。

Dapr 客户端 搭配 WebApiClientCore 玩耍服务调用的更多相关文章

  1. Dapr实战(二) 服务调用

    服务调用是什么 在分布式应用程序中的服务之间进行调用会涉及到许多挑战. 例如: 维护其他服务的地址. 如何安全地调用服务. 在发生短暂的 暂时性错误 时如何处理重试. 分布式应用程序调用链路追踪. 服 ...

  2. Blazor+Dapr+K8s微服务之服务调用

    1.1         Dapr环境配置 1.1.1        在开发机安装Docker Desktop并启用Kubernetes 安装过程略,安装好后效果如下:(左下角两个绿色指示Docker和 ...

  3. SpringCloud开发学习总结(七)—— 声明式服务调用Feign(一)

    在实践的过程中,我们会发现在微服务架构中实现客户端负载均衡的服务调用技术Spring Cloud Ribbon<SpringCloud开发学习总结(四)—— 客户端负载均衡Ribbon> ...

  4. Dapr微服务应用开发系列3:服务调用构件块

    题记:这篇开始逐一深入介绍各个构件块,从服务调用开始 原理 所谓服务调用,就是通过这个构件块让你方便的通过HTTP或者gRPC协议同步调用其他服务的方法,这些方法也是通过HTTP或者gRPC来暴露的. ...

  5. Dapr + .NET Core实战(十二)服务调用之GRPC

    什么是GRPC gRPC 是一种与语言无关的高性能远程过程调用 (RPC) 框架. gRPC 的主要优点是: 高性能轻量级 RPC 框架. 协定优先 API 开发,默认使用协议缓冲区,允许与语言无关的 ...

  6. 手把手教你学Dapr - 4. 服务调用

    上一篇:手把手教你学Dapr - 3. 使用Dapr运行第一个.Net程序 介绍 通过使用服务调用,您的应用程序可以使用标准的gRPC或HTTP协议与其他应用程序可靠.安全地通信. 为什么不直接用Ht ...

  7. Caller 服务调用 - Dapr

    前言 上一篇我们讲了使用HttpClient的方式调用,那么如果我们现在需要更换为通过dapr实现服务调用,我们需要做哪些事情呢? Caller.Dapr 入门 如果我们的项目原本使用的是Caller ...

  8. 3. Caller 服务调用 - dapr

    前言 上一篇我们讲了使用HttpClient的方式调用,那么如果我们现在需要更换为通过dapr实现服务调用,我们需要做哪些事情呢? Caller.Dapr 入门 如果我们的项目原本使用的是Caller ...

  9. Http 调用netty 服务,服务调用客户端,伪同步响应.ProtoBuf 解决粘包,半包问题.

    实际情况是: 公司需要开发一个接口给新产品使用,需求如下 1.有一款硬件设备,客户用usb接上电脑就可以,但是此设备功能比较单一,所以开发一个服务器程序,辅助此设备业务功能 2.解决方案,使用Sock ...

随机推荐

  1. OO unit4 summary

    Unit4 一.第四单元作业的架构设计 第四单元个人认为主要是考察对于层次结构的理解,即如何理解并处理好UML图的树状结构组织,在理好层次之间以及层次内部的相互关系之后,就只剩下代码实现的问题了.但是 ...

  2. HashMap 中7种遍历方式的性能分析

    随着 JDK 1.8 Streams API 的发布,使得 HashMap 拥有了更多的遍历的方式,但应该选择那种遍历方式?反而成了一个问题. 本文先从 HashMap 的遍历方法讲起,然后再从性能. ...

  3. Vue(10)表单输入绑定v-model

    v-model v-model指定可以实现表单值与属性的双向绑定.即表单元素中更改了值会自动的更新属性中的值,属性中的值更新了会自动更新表单中的值 绑定的属性和事件 v-model在内部为不同的输入元 ...

  4. csu-acm 1503: 点到圆弧的距离

    1503: 点到圆弧的距离 分析: 先判断点和圆心的连线是否在圆弧范围内,如果在,最短距离即到圆心的距离减去半径的绝对值:反之,为到端点的最短距离. 具体看注释 #include <bits/s ...

  5. Java线程池中的核心线程是如何被重复利用的?

    真的!讲得太清楚了!https://blog.csdn.net/MingHuang2017/article/details/79571529 真的是解惑了 本文所说的"核心线程". ...

  6. [小技巧] 在bash中生成随机数

    译至:http://d.hatena.ne.jp/anmino/20091017/1255705586 bash的SHELL参数RANDOM可以生成0-32767的随机数.想设定从1到N的随机数范围的 ...

  7. 链表逆序---python

    class ListNode: Value = '' # 节点要储存的值,因为Python是弱类型,因此无需传入泛型 Next = None # 下一个节点,初始化时为空值 def __init__( ...

  8. WPF教程十一:简单了解并使用控件模板

    WPF教程十一:简单了解并使用控件模板 这一章梳理控件模板,每个WPF控件都设计成无外观的,但是行为设计上是不允许改变的,比如使用Button的控件时,按钮提供了能被点击的内容,那么自由的改变控件外观 ...

  9. ffmpeg入门篇-滤镜的基本使用

    转发自白狼栈:查看原文 滤镜 什么是滤镜?百度百科介绍说"滤镜主要是用来实现图像的各种特殊效果......". 我们最早在ffmpeg是如何转码的一文中了解过滤镜,来回顾下当时的转 ...

  10. 【剑指offer】77.调整数组顺序使奇数位于偶数前面

    77.调整数组顺序使奇数位于偶数前面 知识点:数组:快速排序:冒泡排序: 题目描述 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部 ...