题记:这篇开始逐一深入介绍各个构件块,从服务调用开始

原理

所谓服务调用,就是通过这个构件块让你方便的通过HTTP或者gRPC协议同步调用其他服务的方法,这些方法也是通过HTTP或者gRPC来暴露的。而方便的含义在于,你无需担心如下问题:

  • 如何发现其他服务,不用关心调用的链路以及负载均衡
  • 调用过程中如何保证安全性
  • 在遇到瞬态错误或中断的时候如何处理重试
  • 如何记录调用链路的跟踪信息

Dapr本身并没有提供额外的API让你去利用这些特性,上面所有的一切都通过Sidecar模式帮你横切到Dapr边车实例中自动处理。如下图所示:

你的服务对其他服务发起的一切服务调用都要经过Dapr边车实例,其他服务接收的一切服务调用同样也要经过Dapr实例。分别执行如下步骤:

  1. 如果服务A要对服务B发起调用(不管HTTP还是gRPC),其实调用的目标是服务A的Dapr边车;
  2. Dapr会利用Dapr的命名解析组件(后续文章会介绍)来找到服务B的的Dapr边车位置;
  3. 然后服务A的Dapr边车就把调用请求转发给服务B的边车了;
  4. 由于服务B的边车和服务B是配对的,知道服务B的调用信息(比如端口),所有请求被再次转发给服务B,服务B完成服务调用的业务处理;
  5. 服务B处理完,把服务调用响应结果返回给服务B的Dapr边车;
  6. 服务B的Dapr边车返回响应结果给服务A的Dapr边车;
  7. 服务A的Dapr边车最后把响应结果返回给服务A本身。

能力

从上面的原理可以看出,通过成对的Dapr边车,来作为服务之间调用的中介,就可以简化服务和Dapr边车之间的调用方式,就可以强化边车之间的调用方式。

这什么意思呢?就是Dapr把服务调用之间的一些共性且复杂的问题帮你解决掉(两个边车之间的调用),你只用采用最基本的HTTP和gRPC功能来暴露你的服务或者调用你的服务(服务与边车之间的调用)。由此,你可以获得Dapr给你提供的如下能力:

  • 寻址和负载均衡:Dapr自动帮你找到要调用的目标服务,并自动对目标服务的多个实例进行负载均衡。
  • 命名空间范围限定:可以把服务放到特定的命名空间内,从而方便隔离各类服务。这个能力最常见的用途就是用命名空间来限定运行环境(开发、测试、生产等)。不过这个能力和托管环境有关,目前只有Kubernetes支持。
  • 重试:在分布式环境中,远程服务出现瞬态故障是很常见的(可能由网络、负载、安全等因素造成),所以在微服务架构中针对同步服务调用必须实现重试机制。传统的方式下,(就算有重试框架的帮助下)需要在业务逻辑代码中编写很多冗长的重试代码。通过Dapr边车内置的重试机制极度简化了这个问题。目前Dapr的会间隔1秒最多重试3次。
  • 安全通信:分布式环境,通信的安全性也是一个需要重点关注的领域。Dapr提供了一个名为Sentry的基础服务,让边车之间的通信基于mTLS来进行安全保证(mTLS的证书会自动更新)。
  • 安全访问:在安全通信的mTLS证书的基础,可以通过配置信任域(TrustDomain)和应用标识(App Identity)来进行访问控制。在这里暂时不对此话题展开。
  • 可观测性:默认情况下,Dapr会收集边车之间服务调用的度量和跟踪信息,从而帮助开发人员来洞察和诊断应用程序。也就是说,高大上的分布式跟踪直接由Dapr提供内置支持了。
  • 可替换的服务发现:原理里面提到Dapr之间的服务发现会依赖于一个称之为命名解析组件的东西,实际上这个东西可以在不同的托管环境中进行替换。默认情况下,在Kubernetes里面,是使用DNS Service来作为命名解析组件的实现。

规范

由于服务调用这个构件块并没有为服务应用提供什么可直接访问的能力,所以整个规范也相对简单,仅仅规定了调用其他应用的URL模式,即通过如下地址来发送HTTP请求(或gRPC请求):

POST/GET/PUT/DELETE http://localhost:<daprPort>/v1.0/invoke/<appId>/method/<method-name>

上面的URL地址涉及到几个约定好的参数:

  • daprPort:这是Dapr边车暴露的HTTP端口(默认50001)或者gRPC端口(默认3500);可以通过 dapr run--dapr-grpc-port--dapr-http-port 来设置;应用内可以通过 DAPR_HTTP_PORTDAPR_GRPC_PORT 这两个环境变量来获得端口值。
  • appId:这是目标应用的AppId,在命名空间(如果有)内唯一的标识;可以通过 dapr run--app-id 来设置。
  • method-name:这是需要调用的目标应用的接口名称,一般是根路径(比如 /hello )或者嵌套路径(比如 /api/weather )也是支持的。

DOTNET SDK

作为DOTNET博主,我就仅介绍DOTNET SDK的情况。由于服务调用规范本身就简单,所以SDK也相对简单。对于被调用端,目前并没有提供任何辅助的能力,你只需要使用适合的现成框架来暴露HTTP或者gRPC端点。

对于调用端,提供了一个客户端类 DaprClient,有如下方法来帮助你发送服务调用的请求:

  • InvokeMethodAsync
  • InvokeMethodRawAsync
  • InvokeMethodWithResponseAsync

对于DaprClient具体的用法可以参见这里的示例代码:https://github.com/dapr/dotnet-sdk/blob/master/samples/Client/DaprClient/Program.cs#L217

internal static async Task InvokeDepositServiceOperationAsync(DaprClient client)
{
Console.WriteLine("Invoking deposit");
var data = new { id = "17", amount = (decimal)99 }; // Invokes a POST method named "depoit" that takes input of type "Transaction" as define in the RoutingSample.
Console.WriteLine("invoking"); var a = await client.InvokeMethodAsync<object, Account>("routing", "deposit", data, HttpInvocationOptions.UsingPost());
Console.WriteLine("Returned: id:{0} | Balance:{1}", a.Id, a.Balance); Console.WriteLine("Completed");
}

用法与例子

要了解服务调用构件块具体如何使用的,照着官方文档做就是了。

对于不想看英文文档的同学,可以关注我们Dapr中文社区的翻译过程(也欢迎加入):https://github.com/dapr-cn/docs

另外我在单独写一个Dapr的Quickstarts(正在逐步完善中),大家可以参考:https://github.com/heavenwing/dapr-dotnet-quickstarts/tree/main/ServiceInvocation

彩蛋——如何暴露gRPC端点

最后,官方文档里面其实没有把如何暴露gRPC端点这个话题讲清楚,不过在SDK中其实已经把dapr的Protobuf 封装好了(其实是自动生成好了),你引用了SDK中的Dapr.Client包就可以直接使用。我之前根据dapr的protobuf协议实现了一个例子,其实就是实现 AppCallback.AppCallbackBaseTask<InvokeResponse> OnInvoke(InvokeRequest request, ServerCallContext context) 方法,并通过ASP.NET Core来托管。 代码已经合并到SDK中的samples部分,见:https://github.com/dapr/dotnet-sdk/blob/master/samples/AspNetCore/GrpcServiceSample/Readme.md。调用代码见:https://github.com/dapr/dotnet-sdk/blob/master/samples/Client/DaprClient/Program.cs#L298

后来我觉得这个示例更加类似quickstarts,而不是SDK的示例,后面我会把这个示例添加到我的quickstarts中,并在SDK中去实现一个真正进行gRPC端点暴露开发的辅助能力,敬请期待。

Dapr微服务应用开发系列3:服务调用构件块的更多相关文章

  1. Dapr微服务应用开发系列0:概述

    题记:Dapr是什么,Dapr包含什么,为什么要用Dapr. Dapr是什么 Dapr(Distributed Application Runtime),是微软Azure内部创新孵化团队的一个开源项目 ...

  2. Dapr微服务应用开发系列1:环境配置

    题记:上篇Dapr系列文章简要介绍了Dapr,这篇来谈一下开发和运行环境配置 本机开发环境配置 安装Docker 为了方便进行Dapr开发,最好(其实不一定必须)首先在本机(开发机器)上安装Docke ...

  3. Dapr微服务应用开发系列2:Hello World与SDK初接触

    题记:上篇介绍了Dapr的环境配置,这次我们来动手尝试一下Dapr应用的开发 Hello World Dapr应用的Hello World其实和其他的Hello World一样简单: 首先用你喜欢的语 ...

  4. 【Qt编程】基于Qt的词典开发系列<十二>调用讲述人

    我们知道,win7系统自带有讲述人,即可以机器读出当前内容,具体可以将电脑锁定,然后点击左下角的按钮即可.之前在用Matlab写扫雷游戏的时候,也曾经调用过讲述人来进行游戏的语音提示.具体的Matla ...

  5. Dapr云原生应用开发系列7:工作流集成

    题记:这篇介绍一个很有意思的东西,Dapr和Logic Apps这样的工作流引擎集成. Dapr工作流 在1年多前,Dapr的孵化团队搞了一个很有意思的东西:把Dapr和Logic Apps集成起来, ...

  6. 微服务项目开发学成在线_day01_CMS服务端开发

    05-CMS需求分析-什么是CMS 什么是CMS?CMS (Content Management System)即内容管理系统,不同的项目对CMS的定位不同.CMS有哪些类型? 每个公司对每个项目的C ...

  7. Swift3.0服务端开发(一) 完整示例概述及Perfect环境搭建与配置(服务端+iOS端)

    本篇博客算是一个开头,接下来会持续更新使用Swift3.0开发服务端相关的博客.当然,我们使用目前使用Swift开发服务端较为成熟的框架Perfect来实现.Perfect框架是加拿大一个创业团队开发 ...

  8. Dapr是如何简化微服务的开发和部署

    基于微服务设计模式的现代应用程序面临着一系列挑战.微服务需要有一个强大的服务发现机制来实现动态连接.它们需要松散耦合,实现自主性和独立缩放.微服务需要支持多种语言,其中每个服务都是以最合适的语言.框架 ...

  9. Blazor+Dapr+K8s微服务之开发环境调试

    1         安装Dapr开发调试环境 1.1         Dapr 完整安装模式不支持开发调试 在上一篇随笔<Blazor+Dapr+K8s微服务之服务调用>中,我们通过为每个 ...

随机推荐

  1. 使用msys2在window下构建和使用Linux的软件

    目录 前言 安装 使用 总结 前言 在window下构建Linux编译环境是很常见的,以前用过mingw弄过差不多的环境. 但是使用msys2后就根本停不下来咯,太好用咯. 安装 去官网下载吧,安装跟 ...

  2. 关于SSRF与CSRF漏洞的解释

    目录 SSRF服务端请求伪造(外网访问内网) 1.SSRF形成原因 2.利用SSRF漏洞的目的 3.SSRF漏洞的用途 4.SSRF漏洞的特性 实例 5.如何挖掘SSRF漏洞 6.常用SSRF去做什么 ...

  3. 导出exe的经验

    安装pyinstaller 首先要找到scripts的绝对路径(主要是找到scripts就行了 先是安装C:\Users\96290\AppData\Local\Programs\Python\Pyt ...

  4. JavaScript的数据类型和数据类型的检测

    数据类型 JavaScript的基础数据类型有,NaN    string   undefined    Null      Boolen    Symbol   Bigint   这些都是基础数据类 ...

  5. day03 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数

    本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数 温故知新 1. 集合 主要作用: 去重 关系测 ...

  6. 实用 nginx.conf 用法大全

    服务器拒绝非GET方式请求保障安全性,因为 DELETE.POST.PUT 是可以修改数据的. Nginx 解决方案 在 nginx.conf 配置文件的网站配置区域中添加如下代码片段: 非 GET ...

  7. scala/java等其他语言从CSV文件中读取数据,使用逗号','分割可能会出现的问题

    众所周知,csv文件默认以逗号","分割数据,那么在scala命令行里查询的数据: 可以看见,字段里就包含了逗号",",那接下来切割的时候,这本应该作为一个整体 ...

  8. swap交换2变量

    #define swap(x,y) {(x)=(x)+(y); (y)=(x)-(y); (x)=(x)-(y);} void swap(int i, int offset){ int temp; t ...

  9. 将将List json 转成List<?>实体

    package TestJson; import java.util.ArrayList; import java.util.List; import java.util.Map; import ne ...

  10. IPSec 专题----转自华为文档

    参考链接:https://support.huawei.com/enterprise/zh/doc/EDOC1000122878?section=j004 IPSec 特性全景 1.介绍 由于IP报文 ...