Dapr在VS2019 + .Net Core 3.1环境的调试
上一篇文章《Dapr在VS2019 + .Net Core 3.1环境的试用》,我们已经成功试用了Dapr,那么接下来,我们讲一下Dapr的调试。
开发环境:Visual Studio 2019 Comunity / .Net Core 3.1 / Dapr CLI 1.5 / Windows 10 企业版 19043.1415
如图所示,应用程序与Dapr是两个单独的进程,它们之间通过HTTP/gRPC在预先定义好的端口沟通。所以无法像普通的项目那样F5一键debug。
在网络上搜索了大半天,都找不到靠谱的调试方式。
找到一篇文章貌似可以调试:Dapr + .NET 实战(九)本地调试
但针对的是VS Code,而且还要修改大段的配置文件,对新手不友好。
也有文章说在VS Code安装一个Dapr扩展就行。
但我想在VS开发啊,毕竟我习惯GUI傻瓜式操作……
所幸,在B站找到一个微软MVP UP主分享的视频,感觉挺不错,在这里分享一下:
在这里用文字表述出来,并且进行小小的改动。
1,修改Program.cs的CreateHostBuilder方法:
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder #if DEBUG .UseUrls("https://localhost:5004")//Debug 环境配合Dapr边车的设置 #endif .UseStartup<Startup>(); });
因为Dapr的SideCar边车要监听来自特定端口的信息,所以我们指定了程序Url。可以参见 ASP.NET Core中配置监听URLs的五种方式
2,修改Startup.cs的ConfigureServices方法:
public void ConfigureServices(IServiceCollection services) { #if DEBUG //Dapr run -a MemberService -G 50004 -H 30004 Process[] processes = Process.GetProcessesByName("daprd"); if (processes.Any(x => x.GetCommandLineArgs().Contains("MemberService")) == false) { //string userFolder = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); //string daprdPath = System.IO.Path.Combine(userFolder, ".dapr\\bin\\daprd.exe"); //string args = " -app-id MemberService -app-port 5004 -dapr-grpc-port 50004 -dapr-http-port 30004";// -components-path D:\\Temp\\Dapr_Demo\\.dapr\\components //Process.Start(daprdPath, args); Process.Start("dapr", "run -a MemberService -p 5004 -G 50004 -H 30004 --app-ssl"); } //Debug 环境,让程序连接特定的Dapr端口 services.AddControllers().AddDapr(config => { config.UseHttpEndpoint("http://localhost:30004"); config.UseGrpcEndpoint("http://localhost:50004"); }); #else services.AddControllers().AddDapr(); #endif }
原理很简单:
a. 检查有没有MemberService的daprd进程,如果没有,则运行dapr run命令,指定名字、监听端口、边车gRPC端口、边车Http端口,以及指定Dapr 调用应用程序时是否启用 https
最后一步,如果创建Member项目的时候勾选了Configure for HTTPS则必须要指定“--app-ssl”,否则就会出现 the server closed connection before returning the first response byte 错误
b. 设置Dapr组件使用指定的Http终结点和gRPC终结点
dapr run命令会在server创建两个进程,一个是dapr,一个是真正干活的daprd
被注释的几行代码就是up主原来的代码,直接运行了daprd。但我发现这样的话,dapr dashboard无法看到dapr app的运行状况,所以我更改了一下,仍然运行dapr run命令。
配合上一篇文章《Dapr在VS2019 + .Net Core 3.1环境的试用》,我们已经可以一键F5对Member进行调试了。
只要在MemberController里面的方法设置断点,则无论是Http请求还是被其他Dapr边车请求,都能够断点调试。
参考:
-------------------------------------------------------------
文中使用了一个扩展方法GetCommandLineArgs,这是.Net没有的,可以查阅:.NET/C# 获取一个正在运行的进程的命令行参数
以下是详细代码:
/// <summary> /// 为 <see cref="Process"/> 类型提供扩展方法。 /// </summary> public static class ProcessExtensions { /// <summary> /// 获取一个正在运行的进程的命令行参数。 /// 与 <see cref="Environment.GetCommandLineArgs"/> 一样,使用此方法获取的参数是包含应用程序路径的。 /// 关于 <see cref="Environment.GetCommandLineArgs"/> 可参见: /// [.NET 命令行参数包含应用程序路径吗?](https://walterlv.com/post/when-will-the-command-line-args-contain-the-executable-path.html) /// </summary> /// <param name="process">一个正在运行的进程。</param> /// <returns>表示应用程序运行命令行参数的字符串。</returns> public static string GetCommandLineArgs(this Process process) { if (process is null) throw new ArgumentNullException(nameof(process)); try { return GetCommandLineArgsCore(); } catch (Win32Exception ex) when ((uint)ex.ErrorCode == 0x80004005) { // 没有对该进程的安全访问权限。 return string.Empty; } catch (InvalidOperationException) { // 进程已退出。 return string.Empty; } string GetCommandLineArgsCore() { using (var searcher = new ManagementObjectSearcher( "SELECT CommandLine FROM Win32_Process WHERE ProcessId = " + process.Id)) using (var objects = searcher.Get()) { var @object = objects.Cast<ManagementBaseObject>().SingleOrDefault(); return @object?["CommandLine"]?.ToString() ?? ""; } } } }