一行代码让你的项目轻松使用Dapr
介绍
Dapr简化了云原生开发,让开发可以把焦点放在应用的业务逻辑上,从而让代码简单、可移植,那作为一个.Net开发者,我们也希望项目可以快速用上dapr,那究竟应该如何做呢?
Dapr提出了Sidecar(边车)的概念,在启动项目时再额外启动一个Sidecar, 通过Sidecar可以解决进程间通信,为此官方提供了两种部署方式:
- 自托管方式下运行Dapr
- 在 Kubernetes 模式中部署和运行 Dapr
其中Kubernetes模式部署是通过Kubernetes来完成的,在开发中我们更多的是通过自托管模式使用Dapr,那自托管模式是怎么做的呢?
使用命令行工具,在项目根目录输入:
dapr run --app-id assignment-server --app-port 5038 dotnet run
参考以上详细文档操作后,我们就可以在命令行工具中执行dapr invoke --app-id assignment-server --method hello或者Http请求来调用对应的应用的方法
看似好像也不是很复杂,但如果你需要调试dotnet项目呢?再复杂一点的需要启动多个项目进行调试呢?端口一多起来的确会显得很麻烦。
有没有什么办法可以解决呢?有,docker-compose。
但我还不想用这么重的东西,我想像平时开发项目一样直接在windows上运行可不可以?
Masa.Utils.Development.Dapr.AspNetCore 它来了
协助管理dapr进程,用于开发时减少对docker compose的依赖
瞌睡了就有人送枕头,一句话让我们了解到了它的作用,正好解决了我们需要通过命令行来启动dapr的问题,那下面我们看看这个怎么用:
入门
本着绝对不多写一行代码的心态,我们准备出发了……
从大佬doddgu的博客的链接中发现一份源码地址,为防止后期文档调整,先fork一份到自己仓库
git clone https://github.com/zhenlei520/dapr-study-room.git
使用命令行工具打开目录dapr-study-room\Assignment03,然后执行命令
dotnet add package Masa.Utils.Development.Dapr.AspNetCore --version 0.4.0-preview.3
或使用Visual Studio打开解决方案Assignment03,选中Assignment.Server并安装Masa.Utils.Development.Dapr.AspNetCore
打开
Program.cs,并添加DaprStarter(注意看有注释的那一行)using Masa.Utils.Development.Dapr.AspNetCore; var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDaprStarter();//添加DaprStarter即可
var app = builder.Build(); app.Map("/hello", () => Console.WriteLine("Hello World!")); app.Run();
使用命令行工具执行命令验证dapr是否启动成功
dapr invoke --app-id Assignment-Server-00D861D0C0B7 --method hello
此时会有小伙伴问了,为什么app-id是Assignment-Server-00D861D0C0B7?
查看文档后发现Masa.Utils.Development.Dapr.AspNetCore的app-id生成规则为:AppId + AppIdDelimiter + AppIdSuffix,其中
- AppId默认:项目名.Replace(".","-")
- AppIdSuffix默认:网卡地址
由于我们的项目名为Assignment.Server,当前电脑的网卡地址是00D861D0C0B7,所以dapr最终的appid为Assignment-Server-00D861D0C0B7,到这里,Masa.Utils.Development.Dapr.AspNetCore的使用讲解已经完成了
冷知识,为什么 . 要换成 - ?
因为Dapr的AppId采用FQDN:(Fully Qualified Domain Name)全限定域名:同时带有主机名和域名的名称。(通过符号“.”)
为什么要加网卡地址作为后缀?
因为目前自托管默认采用mDNS,会导致局域网内用户的AppId互相污染。你的同事和你一起在开发,都启动了A应用,你俩就自动负载了,那后果自然就是请求也到处跑了。
进阶
如果我希望自己指定AppId而不是使用默认的规则怎么办呢?目前支持三种写法:
- 根据规则(配置默认装配)
- 根据规则 + 代码指定(配置自定义装配)
- 根据配置文件(根据IConfiguration配置生成)
配置默认装配(也是上面介绍的一行代码的方式)
修改Program.cs文件
// 省略上述代码
builder.Services.AddDaprStarter();
根据规则 + 代码指定(配置自定义装配)
修改Program.cs文件
// 省略上述代码
builder.Services.AddDaprStarter(opt =>
{
opt.AppId = "masa-dapr-test";
opt.AppPort = 5001;
opt.AppIdSuffix = "";
opt.DaprHttpPort = 8080;
opt.DaprGrpcPort = 8081;
});
基于默认装配的升级版,在默认装配基础上通过指定特殊参数完成特殊需求,未配置的参数将使用默认值
根据IConfiguration配置生成
- 修改
appsettings.json
{
"DaprOptions": {
"AppId": "masa-dapr-test",
"AppPort": 5001,
"AppIdSuffix": "",
"DaprHttpPort": 8080,
"DaprGrpcPort": 8081
}
}
- 修改
Program.cs
builder.Services.AddDaprStarter(builder.Configuration.GetSection("DaprOptions"));
优势:更改appsettings.json配置后,dapr sidecar会自动更新,项目无需重启
Masa.Utils.Development.Dapr.AspNetCore的设计思路
设计思路基于两个方面,其一本机自动启动dapr sidecar还可以正常调试.Net项目,其二简化配置
技术选型
我们有两种启动dapr slidecar的方式:
- dapr run
- daprd
两者之间的差别如下所示:
完整的对比可查看:https://docs.dapr.io/reference/arguments-annotations-overview/
通过对比我们发现,我们的目标使用daprd与Dapr CLI都可以实现,那为什么Masa.Utils.Development.Dapr选择的是Dapr CLI,而不是daprd呢?
核心的原因是dapr可以通过dapr list命令很简单的就获取到当前运行的所有dapr程序,而daprd无法获取。如果使用daprd,那我们就需要使用C#代码通过操作dll获取具体执行的dapr命令,且多平台支持不好,所以暂时用了Dapr CLI
更优秀的Dapr管理需要做到什么?
- 使用简单
- 参数可配置
- 功能支持选择性启动
- Dapr保活
- 配置支持动态更新
为了能更方便的使用,我们做了以下约定:
- 针对dapr的非必填项,默认关闭不启用,手动配置参数后开启
- 针对dapr的必填项: app-id、app-port、dapr-http-port、dapr-grpc-port 自动生成并配置
app-id 生成规则
其中dapr的app-id默认生成规则为:AppId + AppIdDelimiter + AppIdSuffix,其中
- AppId默认:项目名.Replace(".","-")
- AppIdDelimiter默认:-
- AppIdSuffix默认:当前机器网卡地址
当AppIdSuffix赋值为空字符串,dapr的AppId的生成规则为:AppId
app-port 获取
private ushort GetAppPort(DaprOptions options)
{
var server = _serviceProvider.GetRequiredService<IServer>();
var addresses = server.Features.Get<IServerAddressesFeature>()?.Addresses;
if (addresses is { IsReadOnly: false, Count: 0 })
throw new Exception("Failed to get the startup port, please specify the port manually");
return addresses!
.Select(address => new Uri(address))
.Where(address
=> (options.EnableSsl is true && address.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase))
|| address.Scheme.Equals(Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase))
.Select(address => (ushort)address.Port).FirstOrDefault();
}
为了防止启动过程中修改端口,过早的获取到被弃用的端口。因此我们使用后台任务启动dapr sidecar
dapr-http-port、dapr-grpc-port获取
因为支持用户配置,所以我们遵循下面的顺序
如果指定端口,被占用则自动kill port所在进程,保证可以sidecar可以正常启动
为什么端口占用就要先kill,复用不行吗?
因为sidecar有初始化配置,程序调整的代码影响到sidecar配置变更我们无法检测,所以启动时保证是最新的是比较合适的选择
如果未指定端口,则交还给dapr,通过Dapr CLI的规则生成对应的http-port或grpc-port
Dapr保活
为了保证dapr进程是活跃的,我们在库中建立了一个心跳检查任务用来检测当前的dapr进程是否是活跃的,当dapr进程意外停止后会被重启,且配置信息与上一次成功的dapr配置保持不变
如果不需要保活机制的话可以将EnableHeartBeat改为false,则不启用dapr保活机制
配置支持动态更新
我们通过IOptionsMonitor的OnChange方法来监听配置的变更,当配置变更后我们会通过IDaprProcess 提供的Refresh方法来重启dapr进程,并重新调整环境变量信息
本章源码
Assignment03
https://github.com/zhenlei520/dapr-study-room
开源地址
MASA.BuildingBlocks:https://github.com/masastack/MASA.BuildingBlocks
MASA.Contrib:https://github.com/masastack/MASA.Contrib
MASA.Utils:https://github.com/masastack/MASA.Utils
MASA.EShop:https://github.com/masalabs/MASA.EShop
MASA.Blazor:https://github.com/BlazorComponent/MASA.Blazor
如果你对我们的 MASA Framework 感兴趣,无论是代码贡献、使用、提 Issue,欢迎联系我们

一行代码让你的项目轻松使用Dapr的更多相关文章
- win10一行代码搭建本地html项目
最近玩了下web项目,需要部署到本地查看效果. 一:准备 1.安装python或者安装node.js 2.html项目文件 二:python搭建 1.进入html文件的路径 2.通过python命令部 ...
- Android Studio发布项目到jcenter,一行代码引入Module
前面我们使用自己封装的okhttp项目时候,只需要app/build.gradle文件中加一行代码就能使用项目. compile 'com.ansen.http:okhttpencapsulation ...
- Jenkins file一行代码部署.NET程序到K8S
什么是Jenkins共享库 随着微服务的增多,每个项目的都需要pipline文件,这样的话Pipeline代码冗余度高,并且pipeline的功能越来越复杂. jenkins可以使用Shared Li ...
- 翻遍互联网都找不到的解决方案,一行代码轻松实现 Gitbook 默认折叠左侧菜单效果
Gitbook 是一款产品文档构建工具,也可以用于构建个人博客,默认情况下电脑端访问时左侧菜单是展开状态,可偏偏有人想要实现默认折叠效果,于是诞生了这篇文章! 善良的我选择帮助别人 可能是网上关于 G ...
- MAC 系统升级10.10以后PHP验证码错误的解决办法。[ 一行代码轻松解决! ]
MAC 升级到10.10 以后PHP版本为5.5,初步判定是由于FreeType 字体库的原因,导致GD库有些问题,总之就是验证码出不来.很多大牛给出的办法是重新编译PHP,这对于手头有项目的人来说可 ...
- 每一行代码都有记录—如何用git一步步探索项目的历史
每一行代码都有一块被隐藏了的文档信息. 下面的代码片段不管是谁写的,其第4行因为某些原因要访问一个DOM结点的clientLeft属性,但却对结果不作任何处理.这十分的莫名其妙,你能告诉我他们为什么要 ...
- 一行代码轻松实现拖动效果[JQuery]
写JS实现拖动需要一大堆不便维护的代码,实属麻烦,Google了大半天,发现了一个优秀的Jquery插件EasyDrag,只需要一行代码便可轻松在主流浏览器上 实现拖动效果. $(document ...
- Asp.Net Core 轻松学-一行代码搞定文件上传 JSONHelper
Asp.Net Core 轻松学-一行代码搞定文件上传 前言 在 Web 应用程序开发过程中,总是无法避免涉及到文件上传,这次我们来聊一聊怎么去实现一个简单方便可复用文件上传功能:通过创建 ...
- 一行代码轻松修改 Text Field 和 Text View 的光标颜色 — By 昉
众所周知,Text Field 和 Text View 的光标颜色默认都是系统应用的那种蓝色,如图: 而在实际开发中为了让视觉效果更统一,我们可能会想把那光标的颜色设置成和界面色调一致的颜色.其实在 ...
随机推荐
- R数据分析:纵向分类结局的分析-马尔可夫多态模型的理解与实操
今天要给大家分享的统计方法是马尔可夫多态模型,思路来源是下面这篇文章: Ward DD, Wallace LMK, Rockwood K Cumulative health deficits, APO ...
- MySQL 面试题MySQL 中有哪几种锁?
1.表级锁:开销小,加锁快:不会出现死锁:锁定粒度大,发生锁冲突的概率最 高,并发度最低. 2.行级锁:开销大,加锁慢:会出现死锁:锁定粒度最小,发生锁冲突的概率最 低,并发度也最高. 3.页面锁:开 ...
- MySQL 获取每月多少日的sql写法
# 写法1 指定 年月 的共有多少日 select DATEDIFF(DATE_ADD(CONCAT( 2020, '-', '03','-','01'),INTERVAL 1 MONTH),CONC ...
- Mybaits 的优点?
1.基于 SQL 语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任 何影响,SQL 写在 XML 里,解除 sql 与程序代码的耦合,便于统一管理:提供 XML 标签,支持编写动态 SQL ...
- 您对 Distributed Transaction 有何了解?
分布式事务是指单个事件导致两个或多个不能以原子方式提交的单独数据源的突 变的任何情况.在微服务的世界中,它变得更加复杂,因为每个服务都是一个工 作单元,并且大多数时候多个服务必须协同工作才能使业务成功 ...
- TCP 重传、滑动窗⼝、流量控制、拥塞控制
重传机制 TCP 会在以下两种情况发⽣超时重传: 数据包丢失 确认应答丢失 重传超时 重传超时是TCP协议保证数据可靠性的另一个重要机制,其原理是在发送某一个数据以后就开启一个计时器,在一定时间内如果 ...
- 提交Form表单,submit之前做js判断处理
效果: 在点击提交按钮时,首先进行js判断, 如果不符合条件,则alert出提示信息,并return false. 主要点就在于给form表单添加一个onsubmit事件. 在onsubmit事件中定 ...
- 罗振宇2022"时间的朋友"跨年演讲
罗振宇2022"时间的朋友"跨年演讲 行就行,不行我再想想办法. 原来,还能这么干! 堆资源不是解决问题的唯一道路,还是那句话:"处于困境中的人往往只关注自己的问题.而解 ...
- 《JavaScript Dom编程艺术》读书笔记(二)
算术操作符 加减乘除这些算术操作中的每一种都必须借助于相应的操作符才能完成.操作符是JavaScript为完成各种操作而定义的一些符号.等号(=).加号(+).减号(-).乘号(*).除号(/). 下 ...
- Codepen 每日精选(2018-4-4)
按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以打开原始页面. 纯 css 画的扫雷游戏界面https://codepen.io/alejuss/fu... 线条简单的小 ...