Service Invoke | 服务调用是什么?

服务调用是 dapr 的 building blocks 的其中一部分,用于执行直接而安全的服务间方法调用。

通过服务调用,应用程序可以使用 gRPCHTTP 这样的标准协议来发现并可靠地与其他应用程序通信。

在多个需要相互通信的服务环境中(多进程、分布式、微服务),通常面临以下问题:

  • 如何发现和调用不同服务上的方法?
  • 如何安全地调用其他服务?
  • 如何处理重试和瞬态错误?
  • 如何使用分布式跟踪调用图来诊断生产中的问题?

Dapr 服务调用具备的能力

Dapr 通过提供服务调用 API 来应对这些问题,这种调用 API 作为反向代理与内置的服务发现相结合, 同时利用内置分布式跟踪、计量、错误处理、加密等功能。

Dapr 采用边车(Sidecar)、去中心化的架构 。 要使用 Dapr 来调用应用程序,请在任意 Dapr 实例上使用 invoke 这个API。 sidecar 编程模型鼓励每个应用程序与自己的 Dapr 实例对话。 Dapr 实例会相互发现并进行通信。

dapr 的 service invoke 同样是 Sidecar 编程模型,具备以下能力:

  • 服务发现,on k8s(用于Cloud端部署) 的 DNS(CoreDNS) 和 self-hosted (用于Edge端/独立部署)的 mDNS 模式;
  • 失败重试,服务通信访问失败执行相应的访问策略授权,比如应用程序可以控制哪些其他应用程序允许调用或授权可做什么;
  • 服务熔断,避免负载过大从而导致响应变慢或失败的情况,使应用程序增强健壮性;
  • 通信安全,使用 mTLS 加密服务调用,包括通过 Dapr 哨兵服务来自动证书翻转(certificate rollover);
  • 负载均衡,使用 mDNS 协议提供轮询负载均衡的服务调用请求,例如用于本地或多个联网的物理机器;
  • 可观测性,内置分布式链路跟踪、计量,以便为应用程序提供洞察和诊断;

可插拔服务发现

Dapr 可以在各种托管平台(云 / Cloud端 / Edge)上运行。为了启用 服务发现服务调用,Dapr 使用可插入的 名称解析组件 。例如,Kubernetes 名称解析组件使用 Kubernetes DNS 服务来解析集群中运行的其他应用程序的位置。自承载计算机可以使用 mDNS 名称解析组件。Consul 名称解析组件可用于任何托管环境,包括 Kubernetes 或自托管环境。

名称解析组件

  • Self-hosted(自宿主/自承载)模式:
  1. dapr 内置的 mDNS(运行时/daprd 默认)
  • 第三方组件:
  1. Kubernetes DNS(CoreDNS)
  2. HashiCorp Consul

注意:在 Kubernetes 版本 1.11 和更高版本中,CoreDNS 是默认的 DNS 服务器。
警告: 从 v1.18 开始,在 kubeadm 中使用 kube-dns 的支持已被废弃,并已在 v1.21 版本中删除。

服务调用负载均衡

Dapr 使用 mDNS 协议为服务调用请求提供 轮循机制的负载平衡,例如,对于单台计算机或多台联网的物理机。

下图显示了其工作原理的示例。如果您有 1 个具有应用程序 ID 的应用程序实例和 3 个具有应用程序 ID 的应用程序实例,并且您从一个应用程序调用到另一个应用程序,则 Dapr 会在 3 个实例(Instance)之间轮循机制。这些实例可以位于同一台计算机上,也可以位于不同的计算机上。FrontEnd Cart 和 FrontEnd Cart

注意:同一应用的 N 个实例具有相同的应用 ID,因为每个应用的应用 ID 是唯一的。您可以拥有该应用程序的多个实例,其中所有这些实例都具有相同的应用程序 ID。

Dapr 服务调用的逻辑

  1. Service A 对 Service B 发起 HTTP/gRPC 的调用;

  2. Dapr 使用运行在给定托管平台(hosting platform)上的名称解析组件(name resolution component )发现 Service B 的位置;

  3. Dapr 将消息转发至 Service B 的 Dapr 边车(Sidecar);
    注:Dapr 边车之间的所有调用考虑到性能都优先使用 gRPC,仅服务与 Dapr 边车之间的调用可以是 HTTP 或 gRPC。

  4. Service B 的 Dapr 边车将请求转发至 Service B 上的特定端点 (或方法) ,Service B 随后运行其相应的业务逻辑代码;

  5. Service B 发送响应给 Service A,响应将转至 Service B 的边车;

  6. Service B 的 Dapr 边车将消息转发至 Service A 的 Dapr 边车。

  7. Service A 接收响应信息;

任何应用程序都可以通过使用本机 API 来调内置 Dapr 的 Sidecar API。这个 API 可以用 HTTP 或 gRPC 协议调用,使用下面的 URL 来调用 HTTP API:

http://localhost:<dapr-port>/v1.0/invoke/<application-id>/method/<method-name>
  • dapr-port : dapr监听的端口。
  • application-id:服务要调用的另一个服务的id。
  • method-name:服务要调用的另一个服务的方法名称(路由字符串)。

使用 Dapr for dotnet SDK

Dapr .NET SDK 为 .NET 开发者提供了一个易用的、语言相关的开发工具来和Dapr进行集成。SDK为开发者提供了三种远程服务调用的方式:

  1. Invoke HTTP services using HttpClient
  2. Invoke HTTP services using DaprClient
  3. Invoke gRPC services using DaprClient

Dapr 服务调用项目演示(HTTP协议)

上面对 dapr service invoke 做了相应的介绍,接下来我们采用 .net6 (dapr 语言,框架,平台无关,可选择你喜欢的语言/框架演示)分别创建 2 个 WebAPI 项目做演示:

服务(Service) 框架类型 编程语言/平台 Nuget 包
FrontEnd ASP.NET Core Web API C# / .NET6 Dapr.AspNetCore
BackEnd ASP.NET Core Web API C# / .NET6 \

目标:实现 FrontEnd 服务对应 BackEnd 服务的调用(此处我们使用 HTTP 协议演示)。

分别修改服务的 HTTP 端口配置

根据上面的规划创建如下项目结构:

指定 BackEnd 服务的默认启动端口 5000,修改如下配置(applicationUrl):

{"$schema": "https://json.schemastore.org/launchsettings.json","iisSettings": {"windowsAuthentication": false,"anonymousAuthentication": true,"iisExpress": {"applicationUrl": "http://localhost:26409","sslPort": 0}},"profiles": {"BackEnd": {"commandName": "Project","dotnetRunMessages": true,"launchBrowser": true,"launchUrl": "swagger","applicationUrl": "http://localhost:5000","environmentVariables": {"ASPNETCORE_ENVIRONMENT": "Development"}},"IIS Express": {"commandName": "IISExpress","launchBrowser": true,"launchUrl": "swagger","environmentVariables": {"ASPNETCORE_ENVIRONMENT": "Development"}}}
}

和上面类似,同样修改 FrontEnd 服务默认的启动端口 5001(此处省略 json 配置信息);

BackEnd 服务编写 API 接口

此处使用默认的天气(WeatherForecast)接口,代码如下:

using Microsoft.AspNetCore.Mvc;
using BackEnd.Model;namespace BackEnd.Controllers
{[ApiController][Route("[controller]/[action]")]public class WeatherForecastController : ControllerBase{private static readonly string[] Summaries = new[]{"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"};private readonly ILogger<WeatherForecastController> _logger;public WeatherForecastController(ILogger<WeatherForecastController> logger){_logger = logger;}[HttpGet]public IEnumerable<WeatherForecast> Get(){_logger.LogInformation("进入 BackEnd.WeatherForecast.Get 方法");return Enumerable.Range(1, 5).Select(index => new WeatherForecast{Date = DateTime.Now.AddDays(index),TemperatureC = Random.Shared.Next(-20, 55),Summary = Summaries[Random.Shared.Next(Summaries.Length)]}).ToArray();}}
}

FrontEnd 服务中添加 Dapr 服务

如果是以前Web API的方式( .net core 3.1.x 或 .net 5.0.x 版本),可以在Startup.cs 文件 ConfigureServices 方法加入一行代码

services.AddControllers().AddDapr();

如果使用 Minimal API (.net 6.x 版本)可以在 Program.cs 文件中的 var builder = WebApplication.CreateBuilder(args); 之后加入一行代码

builder.Services.AddControllers().AddDapr();

FrontEnd 服务添加相应的 Nuget 依赖包

接下来我们为 FrontEnd 服务添加 Nuget 包【Dapr.AspNetCore v1.6.0】

FrontEnd 服务编写 Service invoke 调用 Demo

演示 3 种方式的 http 服务调用:

  1. 使用 HttpClient 调用 HTTP 服务;
  2. 使用 DaprClient 调用 HTTP 服务;
  3. 使用构造函数注入方式(DI)DaprClient 调用 HTTP 服务;
using Dapr.Client;
using FrontEnd.Model;
using Microsoft.AspNetCore.Mvc;namespace FrontEnd.Controllers
{[Route("api/[controller]/[action]")][ApiController]public class DaprHttpInvokeController : ControllerBase{private readonly static string _appId = "backend";private readonly static string _methodName = "WeatherForecast/Get";private readonly ILogger<DaprHttpInvokeController> _logger;private readonly DaprClient _daprClient;public DaprHttpInvokeController(ILogger<DaprHttpInvokeController> logger, DaprClient daprClient){_logger = logger;_daprClient = daprClient; // (推荐)构造函数注入 DaprClient}[HttpGet]public async Task<ActionResult> GetAsync(){_logger.LogInformation("构建 HttpClient 调用 BackEnd 服务");using var httpClient = DaprClient.CreateInvokeHttpClient();var result = await httpClient.GetAsync($"http://{_appId}/{_methodName}");var resultContent = string.Format("result is {0} {1}", result.StatusCode, await result.Content.ReadAsStringAsync());return Ok(resultContent);}[HttpGet]public async Task<ActionResult> Get2Async(){_logger.LogInformation("构建 DaprClient 调用 BackEnd 服务");using var daprClient = new DaprClientBuilder().Build();var result = await daprClient.InvokeMethodAsync<IEnumerable<WeatherForecast>>(HttpMethod.Get, _appId, _methodName);return Ok(result);}[HttpGet]public async Task<ActionResult> Get3Async(){_logger.LogInformation("构造函数 DI 注入 daprClient 调用 BackEnd 服务");var result = await _daprClient.InvokeMethodAsync<IEnumerable<WeatherForecast>>(HttpMethod.Get, _appId, _methodName);return Ok(result);}}
}

使用 Dapr CLI 启动 app 服务

使用 dapr cli 按顺序先启动 BackEnd 服务,再启动 FrontEnd 服务,命令如下:

# dapr cli 启动 BackEnd  服务,指定 sidecar 端口为 3502(默认为3500),指定 app-port 是 5000,指定 app-id 为 backend,与 BackEnd默认 http 端口保持一致;
dapr run --dapr-http-port 3502 --app-port 5000 --app-id backend dotnet run# dapr cli 启动 FrontEnd 服务,指定 sidecar 端口为 3501(默认为3500),指定 app-port 是 5001,指定 app-id 为 frontend,与 FrontEnd默认 http 端口保持一致;
dapr run --dapr-http-port 3501 --app-port 5001 --app-id frontend dotnet run

此处演示的服务均在相同的宿主机环境,注意 Sidecar 端口区分,避免冲突;

注:BackEnd 和 FrontEnd 服务如果是发布文件,把后面的 dotnet run 命令修改为指定路径的发布文件 .dll 名称即可,例如 dotnet .\BackEnd\bin\Release\net6.0\BackEnd.dll

  • 查看更多 dapr run 用法示例:dapr run -h
Run Dapr and (optionally) your application side by side. Supported platforms: Self-hostedUsage:dapr run [flags]Examples:# Run a .NET application
dapr run --app-id myapp --app-port 5000 -- dotnet run# Run a Java application
dapr run --app-id myapp -- java -jar myapp.jar# Run a NodeJs application that listens to port 3000
dapr run --app-id myapp --app-port 3000 -- node myapp.js# Run a Python application
dapr run --app-id myapp -- python myapp.py# Run sidecar only
dapr run --app-id myapp# Run a gRPC application written in Go (listening on port 3000)
dapr run --app-id myapp --app-port 3000 --app-protocol grpc -- go run main.goFlags:-a, --app-id string                    The id for your application, used for service discovery--app-max-concurrency int          The concurrency level of the application, otherwise is unlimited (default -1)-p, --app-port int                     The port your application is listening on (default -1)-P, --app-protocol string              The protocol (gRPC or HTTP) Dapr uses to talk to the application (default "http")--app-ssl                          Enable https when Dapr invokes the application-d, --components-path string           The path for components directory (default "C:\\Users\\sws-dev-server\\.dapr\\components")-c, --config string                    Dapr configuration file (default "C:\\Users\\sws-dev-server\\.dapr\\config.yaml")-G, --dapr-grpc-port int               The gRPC port for Dapr to listen on (default -1)--dapr-http-max-request-size int   Max size of request body in MB (default -1)-H, --dapr-http-port int               The HTTP port for Dapr to listen on (default -1)--enable-profiling                 Enable pprof profiling via an HTTP endpoint-h, --help                             Print this help message--log-level string                 The log verbosity. Valid values are: debug, info, warn, error, fatal, or panic (default "info")-M, --metrics-port int                 The port of metrics on dapr (default -1)--placement-host-address string    The address of the placement service. Format is either <hostname> for default port or <hostname>:<port> for custom port (default "localhost")--profile-port int                 The port for the profile server to listen on (default -1)-u, --unix-domain-socket string        Path to a unix domain socket dir. If specified, Dapr API servers will use Unix Domain SocketsGlobal Flags:--log-as-json   Log output in JSON format
  • dapr run 启动 BackEnd 服务:
Starting Dapr with id backend. HTTP Port: 3502. gRPC Port: 53516
time="2022-03-15T16:04:06.9484626+08:00" level=info msg="starting Dapr Runtime -- version 1.6.0 -- commit 4bb25fab444c4f1a1bf0ffd74293dbd4fdcea580" app_id=backend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:04:06.9484626+08:00" level=info msg="log level set to: info" app_id=backend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:04:06.9484626+08:00" level=info msg="metrics server started on :53517/" app_id=backend instance=sws-it-dev scope=dapr.metrics type=log ver=1.6.0
time="2022-03-15T16:04:06.952488+08:00" level=info msg="standalone mode configured" app_id=backend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:04:06.952488+08:00" level=info msg="app id: backend" app_id=backend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:04:06.952488+08:00" level=info msg="mTLS is disabled. Skipping certificate request and tls validation" app_id=backend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:04:06.9726362+08:00" level=info msg="local service entry announced: backend -> 192.168.10.251:53521" app_id=backend instance=sws-it-dev scope=dapr.contrib type=log ver=1.6.0
time="2022-03-15T16:04:06.9732999+08:00" level=info msg="Initialized name resolution to mdns" app_id=backend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:04:06.9732999+08:00" level=info msg="loading components" app_id=backend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:04:06.9776088+08:00" level=info msg="component loaded. name: pubsub, type: pubsub.redis/v1" app_id=backend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:04:06.9776088+08:00" level=info msg="waiting for all outstanding components to be processed" app_id=backend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:04:06.9808041+08:00" level=info msg="detected actor state store: statestore" app_id=backend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:04:06.9808041+08:00" level=info msg="component loaded. name: statestore, type: state.redis/v1" app_id=backend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:04:06.9808041+08:00" level=info msg="all outstanding components processed" app_id=backend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:04:06.9808041+08:00" level=info msg="enabled gRPC tracing middleware" app_id=backend instance=sws-it-dev scope=dapr.runtime.grpc.api type=log ver=1.6.0
time="2022-03-15T16:04:06.9813394+08:00" level=info msg="enabled gRPC metrics middleware" app_id=backend instance=sws-it-dev scope=dapr.runtime.grpc.api type=log ver=1.6.0type=log ver=1.6.0
time="2022-03-15T16:04:06.9813394+08:00" level=info msg="enabled metrics http middleware" app_id=backend instance=sws-it-dev scope=dapr.runtime.http type=log ver=1.6.0
time="2022-03-15T16:04:06.9813394+08:00" level=info msg="enabled tracing http middleware" app_id=backend instance=sws-it-dev scope=dapr.runtime.http type=log ver=1.6.0
time="2022-03-15T16:04:06.9818624+08:00" level=info msg="http server is running on port 3502" app_id=backend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:04:06.9818624+08:00" level=info msg="The request body size parameter is: 4" app_id=backend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:04:06.9818624+08:00" level=info msg="enabled gRPC tracing middleware" app_id=backend instance=sws-it-dev scope=dapr.runtime.grpc.internal type=log ver=1.6.0
time="2022-03-15T16:04:06.9824163+08:00" level=info msg="enabled gRPC metrics middleware" app_id=backend instance=sws-it-dev scope=dapr.runtime.grpc.internal type=log ver=1.6.0
time="2022-03-15T16:04:06.9824163+08:00" level=info msg="internal gRPC server is running on port 53521" app_id=backend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:04:06.9824163+08:00" level=info msg="application protocol: http. waiting on port 5000.  This will block until the app is listening on that port." app_id=backend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
== APP == ��������...
Updating metadata for app command: dotnet run
You're up and running! Both Dapr and your app logs will appear here.== APP == info: Microsoft.Hosting.Lifetime[14]
== APP ==       Now listening on: http://localhost:5000
== APP == info: Microsoft.Hosting.Lifetime[0]
== APP ==       Application started. Press Ctrl+C to shut down.
== APP == info: Microsoft.Hosting.Lifetime[0]
== APP ==       Hosting environment: Development
== APP == info: Microsoft.Hosting.Lifetime[0]
== APP ==       Content root path: C:\Users\sws-dev-server\Desktop\dapr-demo\dapr-demo-all\BackEnd\
time="2022-03-15T16:04:08.6315432+08:00" level=info msg="application discovered on port 5000" app_id=backend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:04:08.8113386+08:00" level=info msg="application configuration loaded" app_id=backend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:04:08.8118274+08:00" level=info msg="actor runtime started. actor idle timeout: 1h0m0s. actor scan interval: 30s" app_id=backend instance=sws-it-dev scope=dapr.runtime.actor type=log ver=1.6.0
time="2022-03-15T16:04:08.8155091+08:00" level=info msg="dapr initialized. Status: Running. Init Elapsed 1863.0211000000002ms" app_id=backend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:04:08.9183574+08:00" level=info msg="placement tables updated, version: 0" app_id=backend instance=sws-it-dev scope=dapr.runtime.actor.internal.placement type=log ver=1.6.0
  • dapr run 启动 FrontEnd 服务
Starting Dapr with id frontend. HTTP Port: 3501. gRPC Port: 53577
time="2022-03-15T16:07:29.6081037+08:00" level=info msg="starting Dapr Runtime -- version 1.6.0 -- commit 4bb25fab444c4f1a1bf0ffd74293dbd4fdcea580" app_id=frontend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:07:29.608619+08:00" level=info msg="log level set to: info" app_id=frontend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:07:29.608619+08:00" level=info msg="metrics server started on :53578/" app_id=frontend instance=sws-it-dev scope=dapr.metrics type=log ver=1.6.0
time="2022-03-15T16:07:29.6112893+08:00" level=info msg="standalone mode configured" app_id=frontend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:07:29.6112893+08:00" level=info msg="app id: frontend" app_id=frontend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:07:29.6122979+08:00" level=info msg="mTLS is disabled. Skipping certificate request and tls validation" app_id=frontend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:07:29.6311265+08:00" level=info msg="local service entry announced: frontend -> 192.168.10.251:53582" app_id=frontend instance=sws-it-dev scope=dapr.contrib type=log ver=1.6.0
time="2022-03-15T16:07:29.6321288+08:00" level=info msg="Initialized name resolution to mdns" app_id=frontend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:07:29.6321288+08:00" level=info msg="loading components" app_id=frontend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:07:29.6353047+08:00" level=info msg="component loaded. name: pubsub, type: pubsub.redis/v1" app_id=frontend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:07:29.6353047+08:00" level=info msg="waiting for all outstanding components to be processed" app_id=frontend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:07:29.6379374+08:00" level=info msg="detected actor state store: statestore" app_id=frontend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:07:29.6379374+08:00" level=info msg="component loaded. name: statestore, type: state.redis/v1" app_id=frontend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:07:29.6379374+08:00" level=info msg="all outstanding components processed" app_id=frontend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:07:29.6384667+08:00" level=info msg="enabled gRPC tracing middleware" app_id=frontend instance=sws-it-dev scope=dapr.runtime.grpc.api type=log ver=1.6.0
time="2022-03-15T16:07:29.6384667+08:00" level=info msg="enabled gRPC metrics middleware" app_id=frontend instance=sws-it-dev scope=dapr.runtime.grpc.api type=log ver=1.6.0
time="2022-03-15T16:07:29.6384667+08:00" level=info msg="API gRPC server is running on port 53577" app_id=frontend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:07:29.6389943+08:00" level=info msg="enabled metrics http middleware" app_id=frontend instance=sws-it-dev scope=dapr.runtime.http type=log ver=1.6.0
time="2022-03-15T16:07:29.6389943+08:00" level=info msg="enabled tracing http middleware" app_id=frontend instance=sws-it-dev scope=dapr.runtime.http type=log ver=1.6.0
time="2022-03-15T16:07:29.6389943+08:00" level=info msg="http server is running on port 3501" app_id=frontend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:07:29.6389943+08:00" level=info msg="The request body size parameter is: 4" app_id=frontend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:07:29.6395291+08:00" level=info msg="enabled gRPC tracing middleware" app_id=frontend instance=sws-it-dev scope=dapr.runtime.grpc.internal type=log ver=1.6.0
time="2022-03-15T16:07:29.6395291+08:00" level=info msg="enabled gRPC metrics middleware" app_id=frontend instance=sws-it-dev scope=dapr.runtime.grpc.internal type=log ver=1.6.0
time="2022-03-15T16:07:29.6395291+08:00" level=info msg="internal gRPC server is running on port 53582" app_id=frontend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:07:29.6395291+08:00" level=info msg="application protocol: http. waiting on port 5001.  This will block until the app is listening on that port." app_id=frontend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
== APP == ��������...
Updating metadata for app command: dotnet run
You're up and running! Both Dapr and your app logs will appear here.== APP == info: Microsoft.Hosting.Lifetime[14]
== APP ==       Now listening on: http://localhost:5001
== APP == info: Microsoft.Hosting.Lifetime[0]
== APP ==       Application started. Press Ctrl+C to shut down.
== APP == info: Microsoft.Hosting.Lifetime[0]
== APP ==       Hosting environment: Development
== APP == info: Microsoft.Hosting.Lifetime[0]
== APP ==       Content root path: C:\Users\sws-dev-server\Desktop\dapr-demo\dapr-demo-all\FrontEnd\
time="2022-03-15T16:07:31.3547333+08:00" level=info msg="application discovered on port 5001" app_id=frontend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:07:31.5798394+08:00" level=info msg="application configuration loaded" app_id=frontend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:07:31.5802044+08:00" level=info msg="actor runtime started. actor idle timeout: 1h0m0s. actor scan interval: 30s" app_id=frontend instance=sws-it-dev scope=dapr.runtime.actor type=log ver=1.6.0
time="2022-03-15T16:07:31.5839825+08:00" level=info msg="dapr initialized. Status: Running. Init Elapsed 1972.6932000000002ms" app_id=frontend instance=sws-it-dev scope=dapr.runtime type=log ver=1.6.0
time="2022-03-15T16:07:31.6965976+08:00" level=info msg="placement tables updated, version: 0" app_id=frontend instance=sws-it-dev scope=dapr.runtime.actor.internal.placement type=log ver=1.6.0

使用 Dapr CLI 查看运行中的 app 服务

dapr list

输出信息:

APP ID    HTTP PORT  GRPC PORT  APP PORT  COMMAND     AGE  CREATED              PID
backend   3502       53516      5000      dotnet run  6h   2022-03-15 16:04.06  13268
frontend  3501       55148      5001      dotnet run  5h   2022-03-15 17:26.04  6504

分别查看 BackEnd 服务和 FrontEnd 服务的 Swagger 页面,显示如下:

  • BackEnd 服务 => http://localhost:5000/swagger/index.html
  • FrontEnd 服务 => http://localhost:5001/swagger/index.html

测试服务的可访问性

先测试下 BackEnd 服务的 API 接口是否可正常访问,访问测试如下:

  • 使用 curl 访问测试:
curl -X 'GET' \'http://localhost:5000/WeatherForecast/Get' \-H 'accept: text/plain'
  • 使用 Swagger 页面或 ApiPost 工具访问测试:


测试结果 BackEnd 服务的 API 接口可正常访问,接下在 FrontEnd 服务的 Swagger 页面测试调用 BackEnd 服务的 API 接口,测试如下:

  • 使用 curl 访问测试:
# 1.构建 HttpClient 调用 BackEnd 服务
curl -X 'GET' \'http://localhost:5001/api/DaprHttpInvoke/Get' \-H 'accept: */*'# 2.构建 DaprClient 调用 BackEnd 服务
curl -X 'GET' \'http://localhost:5001/api/DaprHttpInvoke/Get2' \-H 'accept: */*'# 3.构造函数 DI 注入 daprClient 调用 BackEnd 服务
curl -X 'GET' \'http://localhost:5001/api/DaprHttpInvoke/Get3' \-H 'accept: */*'
  • 使用 Swagger 页面访问测试:

  • Dapr CLI 测试 API 访问性

调用 BackEnd 服务的 【http://localhost:5000/WeatherForecast/Get】接口:

dapr invoke --app-id backend --verb "GET" --method WeatherForecast/Get

输出信息:

[{"date":"2022-03-17T11:46:04.3251768+08:00","temperatureC":24,"temperatureF":75,"summary":"Chilly"},{"date":"2022-03-18T11:46:04.3251995+08:00","temperatureC":6,"temperatureF":42,"summary":"Hot"},{"date":"2022-03-19T11:46:04.3251998+08:00","temperatureC":-3,"temperatureF":27,"summary":"Warm"},{"date":"2022-03-20T11:46:04.3252+08:00","temperatureC":51,"temperatureF":123,"summary":"Scorching"},{"date":"2022-03-21T11:46:04.3252001+08:00","temperatureC":37,"temperatureF":98,"summary":"Freezing"}]
App invoked successfully

调用 FrontEnd 服务的【http://localhost:5001/api/DaprHttpInvoke/Get4】接口:

dapr invoke --app-id frontend --verb "GET" --method api/DaprHttpInvoke/Get4

输出信息:

[{"date":"2022-03-17T11:47:12.5673945+08:00","temperatureC":-17,"temperatureF":2,"summary":"Sweltering"},{"date":"2022-03-18T11:47:12.5674017+08:00","temperatureC":-2,"temperatureF":29,"summary":"Bracing"},{"date":"2022-03-19T11:47:12.567402+08:00","temperatureC":38,"temperatureF":100,"summary":"Bracing"},{"date":"2022-03-20T11:47:12.5674021+08:00","temperatureC":38,"temperatureF":100,"summary":"Balmy"},{"date":"2022-03-21T11:47:12.5674023+08:00","temperatureC":-11,"temperatureF":13,"summary":"Sweltering"}]
App invoked successfully

其他另外两个服务调用类似,经测试均可正常调用,此处就不在截图说明。

总结

在需要多服务链路调用的环境中,Dapr 服务调用构建块通过使用 Dapr sidecar 作为服务的反向代理来解决这些相应的挑战,分布式环境中服务调用面临的 “挑战” 全部下沉到 Dapr Sidecar 构建块(building block),从而让开发人员更加专注于项目的业务代码环境;

  • Dapr .NET SDK 提供了多种调用远程方法的途径,对于 HttpClient 的支持能够让开发者重用现存代码并能够与其他现存的框架进行集成(比如:Refit、RestSharp、Polly)。
  • DaprClient 支持使用 HTTP 或 gRPC 语义直接使用 Dapr 的服务调用 API。
  • HttpClient 只支持使用 HTTP 协议来使用 Dapr 的服务调用 API。
  • Dapr Sidecar 模式使 基础设施模块业务代码 分离,与目标服务分离,但各自是独立的进程(daprd.exe)运行,整体形成统一的原子体对外提供服务。

参考文档

  • 【服务调用概述】=> https://docs.dapr.io/zh-hans/developing-applications/building-blocks/service-invocation/service-invocation-overview/

Dapr for dotnet | 服务调用-Service invoke(HTTP协议)相关推荐

  1. 3. Caller 服务调用 - dapr

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

  2. Dapr 客户端 搭配 WebApiClientCore 玩耍服务调用

    使用Dapr 客户端 处理服务调用,需要遵循的他的模式,通常代码是这个样子的: var client = DaprClient.CreateInvokeHttpClient(appId: " ...

  3. Dapr + .NET Core实战(二) 服务调用

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

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

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

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

    介绍 通过使用服务调用,您的应用程序可以使用标准的gRPC或HTTP协议与其他应用程序可靠.安全地通信. 为什么不直接用HttpClientFactory呢 先问几个问题: 如何发现和调用不同服务的方 ...

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

    欢迎大家参加4小时Dapr+.NET 5的实战课程 课程链接     https://ke.qq.com/course/4000292?tuin=1271860f 什么是GRPC gRPC 是一种与语 ...

  7. 面向.NET开发人员的Dapr——服务调用

    目录: 面向.NET开发人员的Dapr--前言 面向.NET开发人员的Dapr--分布式世界 面向.NET开发人员的Dapr--俯瞰Dapr 面向.NET开发人员的Dapr--入门 面向.NET开发人 ...

  8. Dapr牵手.NET学习笔记:想入非非的服务调用

    demo运行环境:Windows10,Docker(dapr_zipkin,dapr_redid,dapr_placement) 安装:dapr init 卸载:dapr uninstall,然后删除 ...

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

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

  10. 18_Android中Service的生命周期,远程服务,绑定远程服务,aidl服务调用,综合服务案例,编写一个应用程序调用远程支付宝远程服务场景

    ============================================================================ 服务的生命周期: 一.采用start的方式开始 ...

最新文章

  1. keras添加正则化全连接_收藏!改善TensorFlow模型的4种方法你需要了解的关键正则化技术(2)...
  2. Facebook AI新研究:可解释神经元或许会阻碍DNN的学习
  3. Windows server 2003下Oracle10g安装图解
  4. 求m ,n 两个数的最小公倍数
  5. Java黑皮书课后题第2章:2.15(几何:两点间距离)编写程序,提示用户输入两个点(x1,y1)和(x2,y2),显示两点距离
  6. stringbuffer mysql_javascript制作sql转换为stringBuffer的小工具
  7. ffmpeg运行在服务器上,FFMPEG安装在服务器上
  8. mysql select high_priority_MySQL进阶SELECT语法篇
  9. FDA批准首个无需人类医生指导的AI,可独立诊断眼科疾病
  10. 开源大数据周刊-第37期
  11. 图像处理小tip——中值滤波的多种实现(包括快速中值滤波算法)
  12. 后台管理系统——02首页布局
  13. Springboot(大总结)
  14. phpstorm误删文件恢复
  15. App云测试平台免费功能汇总
  16. 黑镜第一至二季/全集Black Mirror迅雷下载
  17. java如何接收十六进制_JAVA十六进制数据接收与传输
  18. Oracle v12.2 Bug 27163928触发ORA-4031 导致实例crash.
  19. java web下载文件设置
  20. ChinaSkills-网络系统管理(2022改革Linux部分SDN软件定义网络[OpenDayLight]CentOS7.9安装运行预测)

热门文章

  1. log怎么用计算机求,手机计算器log怎么用
  2. 浅谈feature-based 和 fine-tune
  3. linux删除文件名的文件夹,Linux删除文件夹和修改文件名
  4. 【人工智能Prolog】ancestor 递归
  5. 32位操作系统电脑上的打印机如何共享给64位操作系统的电脑想要使用_hudingyin_新浪博客
  6. 怎样修复win10计算机系统,几种常见修复win10系统情况及修复方法介绍
  7. UVa OJ 10105
  8. asio Tcp服务退出时崩溃bug
  9. 《此生未完成》:她说,名利权情,没有一样是不辛苦的
  10. 密码学--认证协议(Authentication Protocol)分类