通过Dapr实现一个简单的基于.net的微服务电商系统(二)——通讯框架讲解

首先感谢张队@geffzhang公众号转发了上一篇文章,希望广大.neter多多推广dapr,让云原生更快更好的在.net这片土地上落地生根。 

  书接上回通过Dapr实现一个简单的基于.net的微服务电商系统,今天来分享一下这套电商demo的通讯部分到底是如何工作的,看看它是如何屏蔽与dapr繁琐的沟通工作让开发者专注于解决业务问题的。

  首先我们再回顾一下dapr的sidecar是如何与应用相互协同的。和istio类似,dapr的sidecar注入可以分为自动注册和手动注册,下面以手动加注解注册的方式我们来聊一聊dapr的工作逻辑。首先当我们设置一个应用(deployment)的时候,在template-metadata配置了dapr相关注解之后,凡是安装dapr集群的k8s会自动将dapr的sidecar注册到我们的pod中,如下图:

当服务启动后,我们可以用kubectl describe po xxx的方式看到当前该pod会产生两个容器:

  凡是了解k8s的开发人员应该知道。在同一个pod之中,container实例之间的通讯应该是基于同一个虚拟内网的,通俗的说就是两者通讯可以直接通过localhost:port的方式,这是dapr与应用交互的基础。和istio通过iptables 来做流量劫持让Envoy代理可以拦截所有的进出Pod的流量,即将入站流量重定向到 Sidecar,再拦截应用容器的出站流量经过 Sidecar 处理的方案相比,dapr选择了一个更加灵活的方式,也就是它只是主动暴露一个端口(默认3500),将是否和dapr通讯的选择权留给了应用本身。

  当我们发起一个rpc请求时,实际上我们是通过http(or grpc这里不展开)的方式,访问了了http://localhost:3500/v1.0/{invoke}/{servicename}/method/{path} 这么一个地址。sidecar通过解析这个地址得到远程服务名{servicename},以及一个谓词{invoke}以及远程服务的endpoint:{path}。它会通过内部的dns服务名查询servicename得到一个该服务在集群内的实例列表,通过负载均衡的方式发起一个下游调用。这个下游调用也并非直接像普通k8s应用内通过调用service name的方式去调用下游pod的container,而是访问下游pod内的sidecar,通过sidecar再去访问pod内的应用实例。他们之间的调用关系如图所示:  

  通过这样的设计,实际上应用只需要和daprd这个sidcar打交道即可。同时dapr实现了通过谓词解析成不同的服务类型实现。比如服务间调用通过谓词:{invoke}、状态读写的谓词是{state}、订阅发布的谓词是{publish}、{subscribe},几乎所有的行为都可以分解成谓词+服务名+endpoint这种模式(所有api可参考:https://docs.dapr.io/reference/api/),这也是实现这套通讯框架的基础。

   所以剩下的事情就比较简单了,dapr通讯基于http/grpc,所以我们只需要启动一套kestrel+httpclient or grpc service/client即可简单快捷的接入dapr。首先我们还是看看整个repo(https://github.com/sd797994/Oxygen-Dapr)的结构:

  Oxygen这部分主要是包含通用工具层、IOC依赖注入(基于autofac)、本地代理生成器ProxyGenerator。Client主要包含一些远程服务attr标记以及客户端代理工厂。而在Mesh这个单独分层里主要是对Dapr的Actor实现了相关封装、Service层比较简单,只是在hostbuilder启动了一个kestrel并获取所有标记了远程服务的接口来构建路由字典方便将我们的Application服务暴露成restapi。

  本地代理ProxyGenerator实现比较简单,使用了微软自带的代理类DispatchProxy。通过Autofac依赖注入接口的时候将接口和代理类实现注册到ioc容器中,这样当我们通过IServiceProxyFactory.CreateProxy时实际上是从ioc容器中拿到的DispatchProxy实例,这样调用任意该接口的方法都会被路由到DispatchProxy实例,从而实现方法拦截并最终通过RemoteMessageSender类型里的HttpClient发起对dapr的sidecar请求。

  Client层的ServerProxyFactory也比较简单,其实就三个东西,一个是IServiceProxyFactory,这个主要用于发起对远程rpc和actor的调用、一个是IEventBus以及IStateManager,分别用于发布事件和调用dapr的状态管理器。

  Service.Kestrel层主要是通过启动时由RequestDelegateFactory.CreateDelegate的方式将所有注册为remoteservice的接口实现为其构造一个Func<Tservice, Tin, Task<Tout>>这样的匿名委托并将其路由键和该委托注册到一个全局静态字典中。当收到请求时通过kv键值对的方式查询当前key(router)对应的匿名委托,并通过ioc容器构造一个Tservice实例(为什么要请求时创建一个实例?因为这样可以模拟MVC创建controller的方式将Tservice作为一个scope生命周期的对象创建出来,避免Tservice内部的构造函数依赖的非单例对象生命周期失效)

  整个请求收发流程如下:

    1、当客户端通过IServiceProxyFactory.CreateProxy<IxxxServcice>()时获取到该接口的DispatchProxy实例。

    2、实例解析各种参数后发起一个http调用,http请求localhost:3500的sidecar后等待回调。

    3、sidecar将请求组装后发给下游sidecar并由下游sidecar转发给pod内的应用。

    4、应用收到请求后解析path得到对应的RequestDelegate,调用RequestDelegate将请求打到具体的xxxServcice服务上,由服务完成具体的业务。

  Mesh.Dapr则是对Actor行为的一个具体封装,由于原始的dapr sdk需要继承BasicActor然后进行各种actor作业,我采用了另外一种方式,通过emit静态代理的方式创建了一个Actor服务,由其代为接收actor请求后再转发给具体的xxxServcice。同时这个Actor服务会启动一个timer,当timer到期时会进行一次model的版本检查,当版本变化后(一般是由于xxxServcice被调用),会通知xxxServcice继承自基类并重写的SaveData方法,由xxxServcice自身考虑是否需要做业务层的持久化(默认Actor代理服务会自动持久化到dapr的状态设备里),这一步是完全异步的并不会阻塞Actor代理原方法的执行,另外在Actor的使用中,我们也尽量避免在同步调用时去读取第三方的设备可能导致IO阻塞actor。在源码中涉及对actor调用xxxServcice异步的支持,我主要参考了async/await生成状态机的方式创建了一个ActorAsyncStateMachine,由该状态机来完成actor服务调用xxxServcice的async/await实现。

  sample包含一对客户端/服务端案例包含上述涉及的所有远程call,大家可以多参考一下。

  Dapr原始提供了一套sdk用于远程服务,该框架主要是用于实现rpc以及对dapr这些api的自定义封装,当使用这套框架后我们就可以不用再考虑创建具体的webapi控制器,由iapplicationservice申明远程服务后框架即可自动生成代理服务即可。

  该框架的实现方式当然还有诸多不完善或者我没考虑到的地方,主要起到一个抛砖引玉的作用,另外也是通过这个来了解dapr是如何统一了我们网络编程模型的,只有更了解dapr才能更好的使用和推广它。惯例,欢迎fork+star:

  https://github.com/sd797994/Oxygen-Dapr

  https://github.com/sd797994/Oxygen-Dapr.EshopSample  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/303229.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

windows下整合tomcat和nginx

tomcat自带的apache服务器对于并发请求的处理能力比较差&#xff0c;并且耗费资源很大&#xff0c;而nginx这方便却很强悍&#xff0c;以下是在windows下整合tomcat和nginx的过程。 1.准备工作 下载tomcat&#xff08;http://tomcat.apache.org/download-70.cgi&#xff09;,下…

从飞机上看下雨是这样子,太震撼了!

不同的角度&#xff0c;不一样的世界&#xff01;来源&#xff1a;环球顶尖摄影版权归原作者所有&#xff0c;转载仅供学习使用&#xff0c;不用于任何商业用途&#xff0c;如有侵权请留言联系删除&#xff0c;感谢合作。数据与算法之美用数据解决不可能长按扫码关注

linux基础 linhaifeng,Linux基础之命令练习Day2(示例代码)

作业一&#xff1a;1) 新建用户natasha&#xff0c;uid为1000&#xff0c;gid为555&#xff0c;备注信息为“master”2) 修改natasha用户的家目录为/Natasha3) 查看用户信息配置文件的最后一行4) 为natasha用户设置密码“123”5) 查看用户密码配置文件的最后一行6) 将natasha用…

NET问答: 为什么 null + true = string 呢?

咨询区 Javed Akram&#xff1a;请问 null true 为什么是一个 string 类型的 True&#xff0c;代码如下&#xff1a;static void Main(string[] args){string b null true;Console.WriteLine(b);}谁知道这背后的原理&#xff1f;回答区 JaredPar&#xff1a;这是因为你一旦引…

华为21级程序员月薪曝光:270k封神!众网友直呼长见识……

如果一个人的薪水是每月几万&#xff0c;估计很多人都会认为很高&#xff0c;而能拿到这么高薪水的人一定是一个非常优秀人。最近&#xff0c;一名HR在互联网上发布了一个内容。该公司表示在招聘简历中找到华为高管的简历&#xff0c;简历的级别为21&#xff0c;月薪为27万&…

做移动互联网App,你的测试用例足够吗?

我在面试测试工程师时&#xff0c;经常问到的一个问题是“给出Word另存为这个功能的测试用例”。除开基本的测试用例外&#xff0c;考虑到各种异常情况&#xff0c;例如内存已满、硬盘空间不足是非常重要的。但是针对移动互联网App来说&#xff0c;情况还要复杂的多。一个重要原…

linux 手机 wlan信号桥,手机WLAN信号桥是什么?WLAN信号的作用和使用方法

什么是寒假必备&#xff1f;温暖的被窝和wifi绝对是不能少的。今天就给大家介绍一下和手机WIFI有关的WLAN信号桥的知识&#xff0c;让大家在寒假享受WIFI又多了一种选择。感兴趣的可以一起来看看。一、什么是WLAN信号桥&#xff1f;WLAN信号桥简单的来说就是手机连接一个WiFi后…

.NET 6 HotReload的试用

.net v6.0.0-preview.3的HotReload我是极喜欢的&#xff0c;因为之前有这样的需求——状态不丢&#xff0c;上下文不丢。为了验证&#xff0c;安装完.net 6 preview 3后&#xff0c;新建一个webapi项目&#xff0c;写了如下简单代码&#xff1a;using Microsoft.AspNetCore.Mvc…

如何撬动机器学习的冰山一角?

目前&#xff0c;人工智能的应用日渐广泛。而作为人工智能核心的机器学习&#xff0c;是一门多领域的交叉学科&#xff0c;专门研究计算机模拟或实现人类学习行为的方法&#xff0c;以获取新的知识或技能&#xff0c;重新组织已有的知识结构使之不断改善自身的性能。简单来说&a…

linux 下运行libnids,libnids出错

2017/03/28因为246上一般用的东西都比较多了&#xff0c;就直接使用了这部分。但当初编译的时候也不是我弄得。今天想试一下libnids的编程。编译错误在网上查了下&#xff0c;说是版本不够的原因&#xff0c;那我也不能重新编译了&#xff0c;毕竟还有别人说不定用的好好的。gc…

服务治理治什么,10张图告诉你答案

凌晨四点被公司的监控告警叫醒了&#xff0c;告警的原因是生产环境跑批任务发生故障。即刻起床处理故障&#xff0c;但还是花了不少时间才解决。这次故障是一次数据校验的跑批任务&#xff0c;校验前面跑批任务的数据是否正确。幸运的是&#xff0c;之前的核心任务已经完成&…

Mapgis6.7 林相图自动注记 .

林业行业制作林相图是一件比较复杂的事。Mapgis注释和子图分别对应arcmap中的标注和符号&#xff0c;区文件填充颜色对应arcmap中的渲染。由于mapgis中上注释文本和子图号都只能手工一个个去上。如果能结合arcmap出图的强大功能&#xff0c;由arcmap负责制图&#xff0c;mapgis…

在linux文件共享接口,入坑Linux-day13(使用vsftpd服务传输文件、使用Samba或NFS实现文件共享)...

一、文件传输协议#ftp是一种在互联网中进行的文件传输协议&#xff0c;基于客户端/服务器模式&#xff0c;默认使用20、21号端口&#xff0c;其中端口20(数据端口)用于进行数据传输&#xff0c;端口21(命令端口)用于接收客户端发出的相关FTP命令与参数。#FTP工作的两种模式主动…

大数据分析了50万条拼多多商品数据, 得出了这样的结论

一、缘起我在杭州有位朋友&#xff0c;提到有家做社交的电商很火&#xff0c;叫拼多多&#xff0c;我没有在意&#xff0c;直到有一天&#xff0c;我居然在电视上看到了它的广告&#xff0c;广告画面活蹦乱跳&#xff0c;余音绕梁&#xff0c;我惊呆了&#xff0c;想知道这是何…

CentOS 7 安装 Greenplum6 (附 dotNET Core 示例)

Mysql 在面对大数据量的时候&#xff0c;还是表现有些吃力&#xff0c;所以产品中需要扩展能支持海量数据的数据库&#xff0c;这里选择的数据库为 Greenplum6 &#xff0c;Greenplum 底层使用的是开源数据库 PostgreSQL 。本文会介绍怎样在 CentOS 7 中安装 Greenplum6&#x…

linux系统故障实验,Linux常见系统故障排除

导读&#xff1a; 前言 运维人员经常会遇到各式各样的系统故障&#xff0c;如何根据故障特征锁定问题根源&#xff0c;需要的不仅仅是技巧&#xff0c;还有遇到故障时的思路&#xff0c;和对系统内部的理解&#xff0c;本文列出了一些常见的系统故障和处理方法&#xff0c;在那…

MIT正式发布编程语言Julia 1.0:Python、R、C++三合一

MIT 开发的 Julia 语言是全球热度上升最快的编程语言之一&#xff0c;下载量超过 200 万次&#xff0c;下载者包括谷歌、Facebook、FAA 和美国能源部等各个部门的开发者。近日&#xff0c;MIT CSAIL 实验室正式发布了 Julia 1.0&#xff0c;该语言期望结合 C 的速度、Matlab 的…

EFCore3.1+编写自定义的EF.Functions扩展方法

前言本文主要是讲解EF Core3.0 如何实现自定义的数据库扩展函数&#xff0c;虽然EF.Functions 提供了很多数据库函数,但是并不全面.比如加密解密..。这样的话 我们就需要自己扩展这些数据库函数 从而达到调用的目的.本文以达梦数据库为例(其他数据库都一样)..上篇文章推荐: EF …

WSUS2.0数据导入、导出(备份、还原)

以前我们做的WSUS实验都是让WSUS服务器通过互联网连接到微软网站去下 载更新补丁&#xff0c;但是现实的生活中有些网络是与互联网隔绝的&#xff0c;这种情况下可以采用导入导出WSUS数据的方法来解决WSUS的更新问题。先在一台能联网的 WSUS服务器上下载所需更新&#xff0c;然…

linux perl模块检测,Linux有问必答:如何用Perl检测Linux的发行版本

提问:我需要写一个Perl程序&#xff0c;它会包含Linux发行版相关的代码。为此&#xff0c;Perl程序需要能够自动检测运行中的Linux的发行版(如Ubuntu、CentOS、Debian、Fedora等等)&#xff0c;以及它是什么版本号。如何用Perl检测Linux的发行版本&#xff1f;如果要用Perl脚本…