.NetCore集成Dapr踩坑经历
该篇内容由个人博客同步更新!转载请注明出处
前言
之前自己有个core2.2的项目一直是用的surging作为微服务框架的,后来了解到了dapr,发现比较轻量级,而且像微服务的一些功能比如熔断啥的也用不到,开发部署等也非常方便,故将自己的程序升级到了3.0同时框架改成了dapr,网上查到的好多dapr文章基本都是大差不同,大都是用的git上的示例或者是直接文章翻译很少有提到实战上的一些问题,下面我把我自己遇到的一些问题和解决方法记录一下同时大致讲下安装集成步骤。
前期准备
- 安装 docker(dapr安装完后会在docker中生成两个容器dapr_redis和dapr_placement)
- 安装 dapr cli(用于使用dapr的一些命令)
- 安装 .net core sdk 3.0(dapr只能用于3.0的程序中)
-
下载(nuget上暂时只有预览版,所以直接用源码集成方便源码调试)
注意:安装dapr cli的时候他会让你用 一段powershell脚本安装,但由于国内墙的问题使用不了所以需要xxxxemmmm,另一个办法就是直接去release下载文件
具体安装命令步骤啥的不说了,链接点击过去都有介绍
大致集成步骤
具体的如何集成和配置网上都有大家可以看下这篇git上的集成步骤,我这里直接给大家看下我示例程序的项目结构重要的内容会写在括号里
- clients目录下都是用于调用服务的客户端(这里都是通过actorproxy的rpc方式调用,有点像sf、akka.net和orleans,都引用下面的service_interfaces)
- dapr目录下就是上面下载的dapr源代码
- csrediscore我项目里面用到了redis所以把csrediscore的源代码下载了下来
- service_infrastructure 服务的基础设施存放一些通用的东西或者帮助类
- service_interfaces服务的接口都在这里(引用dapr.actors)
- service_models服务和客户端用到的模型都在这
- service_webapi为客户端提供服务(引用dapr.actors和dapr.actors.aspnetcore)
具体项目依赖如下图
错误内容和解决方法
由于目标计算机积极拒绝,无法连接。
error: daprhttpinteractor: system.net.http.httprequestexception: 由于目标计算机积极拒绝,无法连接。 ---> system.net.sockets.socketexception (10061): 由于目标计算机积极拒绝,无法连接。
这是由于dotnet-sdk默认调用的端口是3500但你通过darp运行的程序端口是随机的所以运行的时候需要指定一个端口通过 -port xx,例如:
dapr run --port 3500 --app-id demo_actor --app-port 5000 dotnet run
或者通过指定程序调用的端口通过设置dapr_http_port
的环境变量来指定程序调用端口
err_invoke_actor
error converting value "err_invoke_actor" to type 'system.nullable
这是由于作者在程序中少写了这个状态应该算个bug我提交了issue但还没回我,具体的在daprerrorcodes文件中最后加一下就行
actor服务中如何使用依赖注入
对于这个问题有两个解决方法:
- 默认的服务实现中构造函数只能有两个参数actorservice和actorid,但是它在注册的时候提供了另一个构造方法,比如我的一个redis服务构造函数是这样的,里面iredisprovider需要通过注入来获取
可以在注册actor的时候提供你所需要的东西,如下
public static iwebhostbuilder createhostbuilder(string[] args)=> webhost.createdefaultbuilder(args) .usestartup<startup>() .useactors(actorruntime => { //重点 actorruntime.registeractor<rediscachesservice>((type) => new actorservice(type, (actorservice, actorid) => new rediscachesservice(new redisprovider(),actorservice, actorid))); }) .useurls($"http://localhost:{5000}/");
- 第一个方法有局限性,和自己new对象没啥区别。所以这里推荐自己实现一个servicelocator用来获取所需要的服务,简单写一下用法,定义一个servicelocator类
public class servicelocator { public static iserviceprovider current { get; set; } }
在startup > configure 中赋值
public void configure(iapplicationbuilder app, iwebhostenvironment env) { servicelocator.current = app.applicationservices; if (env.isdevelopment()) { app.usedeveloperexceptionpage(); } app.usehsts(); }
在actor服务中使用
public rediscachesservice(actorservice actorservice, actorid actorid) : base(actorservice, actorid) { using (var scoped=servicelocator.current.createscope()) { _cr = scoped.serviceprovider.getservice<iredisprovider>().getinstance(); } }
需要注意的点
1.actor服务中的每个方法最多只能有一个参数,多个参数的话都变成写成一个实体进行传递,不然会报错
-
dapr提供了一个可视化界面 这个暂时有点问题,谷歌打不开,但edge可以,貌似是angular的bug,所以推荐大家暂时不要用,因为功能很少不如直接dapr cli方便
结语
大致的问题就如上面这些,但我记得还有几个隔了一天年纪太大忘光了,后续有新问题我会继续更新。不要问我dapr和其它微服务框架比效率性能哪个好,我也没试过。这玩意儿既然是微软开源的我想也不会太差,而且有专业的团队维护,不出太大意外我想发展肯定是越来越好的。
微信关注我哦!(转载注明出处)