zoukankan      html  css  js  c++  java
  • 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主分享的视频,感觉挺不错,在这里分享一下:

    一起学习 Dapr 调试&部署

    在这里用文字表述出来,并且进行小小的改动。

    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边车请求,都能够断点调试。

    参考:

    一起学习 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() ?? "";
                    }
                }
            }
        }
  • 相关阅读:
    字符串型
    字符型
    实型(浮点型)
    sizeof
    数据类型
    标识符
    Win32汇编
    Win32汇编
    C# 语言程序设计笔记
    鬼泣4:寻找无限生命/剑气/暴怒
  • 原文地址:https://www.cnblogs.com/AlvinLiang/p/15785285.html
Copyright © 2011-2022 走看看