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() ?? "";
                    }
                }
            }
        }
  • 相关阅读:
    0309. Best Time to Buy and Sell Stock with Cooldown (M)
    0621. Task Scheduler (M)
    0106. Construct Binary Tree from Inorder and Postorder Traversal (M)
    0258. Add Digits (E)
    0154. Find Minimum in Rotated Sorted Array II (H)
    0797. All Paths From Source to Target (M)
    0260. Single Number III (M)
    0072. Edit Distance (H)
    0103. Binary Tree Zigzag Level Order Traversal (M)
    0312. Burst Balloons (H)
  • 原文地址:https://www.cnblogs.com/AlvinLiang/p/15785285.html
Copyright © 2011-2022 走看看