Dapr DotNet5 HTTP 调用
Dapr DotNet5 HTTP 调用
版本介绍
- Dotnet 版本:5.0.100
- Dapr dotnet 版本:0.12.0-preview01
注意: Asp.Net Core 项目中的 launchSettings.json 文件,该文件的中的端口号应和 darp --app-port 端口号相同,否则 dapr 无法正常启动 Asp.Net Core 项目。

工程结构

3 个 .NET 5 项目,ClientA、ServiceB、ServiceC。1 个 .NET Standard 项目,Dtos 。Dtos 用于存储各种传输模型。调用路径如下图所示。新建两个 service 的意义在于展示 http 链路调用通过 dapr 如何实现。
dotnet5-client-a--1-->dotnet5-service-b;
dotnet5-service-b--2-->dotnet5-service-c;
dotnet5-service-c--3-->dotnet5-service-b;
dotnet5-service-b--4-->dotnet5-client-a;
- dotnet5-client-a 做为客户端调用服务 dotnet5-service-b;
- dotnet5-service-b 做为服务中转,既收来自 dotnet5-client-a 客户端的请求,又发起对 dotnet5-service-c 的调用;
- dotnet5-service-c 响应 dotnet5-service-b 的请求;
- dotnet5-service-b 响应 dotnet5-client-a 的请求。
ServiceC
ServiceC 做为 http 调用链路调用终端只需监听 http 调用端口。通过 nuget 包管理工具,选中->Show pre-release packages,搜索 dapr ,选中 Dapr.AspNetCore 安装包。

Startup
在 ConfigureServices(IServiceCollection services) 方法中通过链式调用 AddDapr() 方法注册 Dapr 到 IOC 容器中。内容如下:
using System.Text.Json;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace ServiceC
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().AddDapr().AddJsonOptions(options => {
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
}
);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
HelloController
在 HelloController 中添加 Talk 方法,打印接收的信息并告诉调用方当前服务是谁。具体内容如下:
[ApiController]
public class HelloController : Controller
{
[HttpPost("talk")]
public async Task<SomeResponseBody> Talk(SomeRequestBody someRequestBody)
{
Console.WriteLine(string.Format("{0}:{1}", someRequestBody.Id, someRequestBody.Time));
return await Task.FromResult(new SomeResponseBody
{
Msg = "This is ServiceC"
});
}
}
launchSetting.json
profiles.ServiceC.applicationUrl 端口号一定要修改为 --app-port 相同的端口号,否则通过 dapr 启动项目的时候无法正常启动
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:35737",
"sslPort": 44379
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"ServiceC": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:9201",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
启动
dapr run --app-id dotnet-server-c --app-port 9201 --dapr-http-port 3520 dotnet run
ServiceB
ServiceB 做为调用链中的一个中转节点,既要监听服务,同时还要发起请求。由于 Dapr.AspNetCore 已经引用了 Dapr.Client 。因此不需要再次引用 Dapr.Client。
Startup
下面是 Dapr.AspNetCore AddDapr() 源码,从源码中可知 AddDapr() 方法向控制器中注册 Dapr 集成。同时通过依赖注入容器注册 DaprClient 。DaprClient 可以和 Dapr 运行时交互。比如 HTTP 调用,也正因为如此,ServiceB 的 Startup 文件我们只需拷贝 ServiceC 的 Startup 文件即可。源码如下:
/// <summary>
/// Provides extension methods for <see cref="IMvcBuilder" />.
/// </summary>
public static class DaprMvcBuilderExtensions
{
/// <summary>
/// Adds Dapr integration for MVC to the provided <see cref="IMvcBuilder" />.
/// </summary>
/// <param name="builder">The <see cref="IMvcBuilder" />.</param>
/// <param name="configureClient">The (optional) <see cref="DaprClientBuilder" /> to use for configuring the DaprClient.</param>
/// <returns>The <see cref="IMvcBuilder" /> builder.</returns>
public static IMvcBuilder AddDapr(this IMvcBuilder builder, Action<DaprClientBuilder> configureClient = null)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
// This pattern prevents registering services multiple times in the case AddDapr is called
// by non-user-code.
if (builder.Services.Any(s => s.ImplementationType == typeof(DaprMvcMarkerService)))
{
return builder;
}
builder.Services.AddDaprClient(configureClient);
builder.Services.AddSingleton<DaprMvcMarkerService>();
builder.Services.AddSingleton<IApplicationModelProvider, StateEntryApplicationModelProvider>();
builder.Services.Configure<MvcOptions>(options =>
{
options.ModelBinderProviders.Insert(0, new StateEntryModelBinderProvider());
});
return builder;
}
private class DaprMvcMarkerService
{
}
}
HelloController
通过构造器注入 DaprClient 以发起 Http 调用 ServiceC 提供的服务。
[ApiController]
public class HelloController : ControllerBase
{
private readonly DaprClient daprClient;
public HelloController(DaprClient daprClient)
{
this.daprClient = daprClient;
}
[HttpPost("talk")]
public async Task<SomeResponseBody> Talk(SomeRequestBody someRequestBody)
{
var data = new { Time = DateTime.Now.ToLongDateString(), Id = "This is Service C." };
HTTPExtension httpExtension = new HTTPExtension()
{
Verb = HTTPVerb.Post
};
SomeResponseBody responseBody = await daprClient.InvokeMethodAsync<object, SomeResponseBody>("dotnet-server-c", "talk", data, httpExtension);
Console.WriteLine(string.Format("{0}:{1} \n recieve message:{2}", someRequestBody.Id, someRequestBody.Time, responseBody.Msg));
return await Task.FromResult(new SomeResponseBody
{
Msg = "This is ServiceB"
});
}
launchSetting.json
参考 ServiceC 更改端口号。
启动
dapr run --app-id dotnet-server-b --app-port 9200 --dapr-http-port 3521 dotnet run
ClientA
ClientA 的目的是发起对 ServiceB 服务的调用,因此只需添加 Dapr.Client 用于和 Dapr 运行时交互即可。内容如下:
class Program
{
static async Task Main(string[] args)
{
var jsonOptions = new JsonSerializerOptions()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
PropertyNameCaseInsensitive = true,
};
var client = new DaprClientBuilder()
.UseJsonSerializationOptions(jsonOptions)
.Build();
var data = new { Time = DateTime.Now.ToLongDateString(), Id="This is Client A" };
HTTPExtension httpExtension = new HTTPExtension()
{
Verb = HTTPVerb.Post
};
while (true)
{
var a = await client.InvokeMethodAsync<object, SomeResponseBody>("dotnet-server-b", "talk", data, httpExtension);
Console.WriteLine(a.Msg);
await Task.Delay(5 * 1000);
}
}
}
每间隔 5 秒向 ServiceB 发送一次请求。
启动
dapr run --app-id dotnet5-http-client dotnet run
ClientA 接收内容:
== APP == This is ServiceB
SerivceB 接收内容:
== APP == This is Client A:2020年11月27日 星期五
== APP == recieve message:This is ServiceC
ServiceC 接收内容:
== APP == This is Service C.:2020年11月27日 星期五
总结
至此,DOTNET5 通过 dapr HTTP 调用的示例就结束了。

Dapr DotNet5 HTTP 调用的更多相关文章
- Dapr Golang HTTP 调用
Dapr Golang HTTP 调用 版本介绍 Go 版本:1.15 Dapr Go SKD 版本:0.11.1 工程结构 从上图可知,新建 3 个 Go 启动项目,cmd 为启动项目目录,其中 c ...
- Dapr Java Http 调用
版本介绍 Java 版本:8 Dapr Java SKD 版本:0.9.2 Dapr Java-SDK HTTP 调用文档 有个先决条件,内容如下: Dapr and Dapr CLI. Java J ...
- 手把手教你学Dapr - 4. 服务调用
上一篇:手把手教你学Dapr - 3. 使用Dapr运行第一个.Net程序 介绍 通过使用服务调用,您的应用程序可以使用标准的gRPC或HTTP协议与其他应用程序可靠.安全地通信. 为什么不直接用Ht ...
- Dapr 运用之集成 Asp.Net Core Grpc 调用篇
前置条件: <Dapr 运用> 改造 ProductService 以提供 gRPC 服务 从 NuGet 或程序包管理控制台安装 gRPC 服务必须的包 Grpc.AspNetCore ...
- Dapr微服务应用开发系列3:服务调用构件块
题记:这篇开始逐一深入介绍各个构件块,从服务调用开始 原理 所谓服务调用,就是通过这个构件块让你方便的通过HTTP或者gRPC协议同步调用其他服务的方法,这些方法也是通过HTTP或者gRPC来暴露的. ...
- Dapr初体验之服务调用
初次理解服务调用 在微服务中,有一个难点就是:如果你想使用各个服务组件,你就得知道不同服务的地址和端口,也就是服务发现. 在传统应用我们是怎么做的?就是在web项目里配置上api地址,如下: 在一个w ...
- Caller 服务调用 - Dapr
前言 上一篇我们讲了使用HttpClient的方式调用,那么如果我们现在需要更换为通过dapr实现服务调用,我们需要做哪些事情呢? Caller.Dapr 入门 如果我们的项目原本使用的是Caller ...
- 3. Caller 服务调用 - dapr
前言 上一篇我们讲了使用HttpClient的方式调用,那么如果我们现在需要更换为通过dapr实现服务调用,我们需要做哪些事情呢? Caller.Dapr 入门 如果我们的项目原本使用的是Caller ...
- 微软的分布式应用框架 Dapr
微服务架构已成为构建云原生应用程序的标准,微服务架构提供了令人信服的好处,包括可伸缩性,松散的服务耦合和独立部署,但是这种方法的成本很高,需要了解和熟练掌握分布式系统.为了使用所有开发人员能够使用任何 ...
随机推荐
- APP后台架构开发实践笔记
1 App后台入门 1.1 App后台的功能 (1)远程存储数据: (2)消息中转. 1.2 App后台架构 架构设计的流程 (1) 根据App的设计,梳理出App的业务流程: (2) 把每个业务流程 ...
- ElasticSearch研究
前言 ES相关技术文档,很久之前看的,一门技术时间长不去研究就会容易忘了,应有些小伙伴的要求希望我做一期ES技术专栏,我就把以前看过的相关文档整理整理,给大家分享下. 1 ElasticSearc ...
- 枚举 switch case 标签必须为枚举常量的非限定名称
枚举 switch case 标签必须为枚举常量的非限定名称 错误描述: Error:(63, 24) 错误: 枚举 switch case 标签必须为枚举常量的非限定名称. 解决思路: switch ...
- 【USACO】Cow Brainiacs
题意描述 Cow Brainiacs 求 \(n!\) 在 \(b\) 进制表示下的第一位非 \(0\) 位的数字. 算法分析 闲话 忙人自动略过 之前做过一道 \(10\) 进制表示下的题目,感觉差 ...
- Java的Arrays.sort()方法到底用的什么排序算法
暂时网上看过很多JDK8中Arrays.sort的底层原理,有些说是插入排序,有些说是归并排序,也有说大于域值用计数排序法,否则就使用插入排序...其实不全对.让我们分析个究竟: 1 // Use Q ...
- Codeforces Round #677 (Div. 3) 题解
Codeforces Round #677 (Div. 3) 题解 A. Boring Apartments 题目 题解 简单签到题,直接数,小于这个数的\(+10\). 代码 #include &l ...
- 【Mycat】作为Mycat核心开发者,怎能不来一波Mycat系列文章?
写在前面 Mycat是基于阿里开源的Cobar产品而研发,Cobar的稳定性.可靠性.优秀的架构和性能以及众多成熟的使用案例使得Mycat一开始就拥有一个很好的起点,站在巨人的肩膀上,我们能看到更远. ...
- Serilog 源码解析——解析字符串模板
大家好啊,上一篇中我们谈到 Serilog 是如何决定日志记录的目的地的,那么从这篇开始,我们着重于 Serilog 是向 Sinks 中记录什么的,这个大功能比较复杂,我尝试再将其再拆分成几个小块方 ...
- 归档空间满了 导致Imp卡住
今天在使用exp imp将生产环境数据库导入到测试环境的过程中,imp的时候 发现在导入某张表的时候卡住了. 起初是以为该表比较大的缘故,后来过了很久 发现还是卡在那里. 最后分析原因 发现设置的归档 ...
- php正则匹配整数
<?php if(!preg_match('/^([1-9][0-9]*){1,10}$/',$buy_sku)) { $error['content'] = '请检查库存格式'; echo j ...