Windows Azure 辅助角色未通过第一行代码

发布于 2025-01-08 18:31:18 字数 7146 浏览 3 评论 0原文

我有一个工作者角色,在开发中完美运行,但在部署时不起作用。 “不起作用”是相当模糊的,但这确实是我必须继续的,因为我没有看到任何错误或任何东西(无论如何在事件日志中 - 也许还有其他地方我可以查看)。我在代码中添加了一些跟踪语句,我看到第一个语句出现,但其他语句都没有出现。

WorkerRole 代码:

public class WorkerRole : RoleEntryPoint
{
    #region Member variables

    private IWindsorContainer _container;

    private IJob[] _jobs;

    #endregion

    #region Methods

    public override bool OnStart()
    {
        ConfigureDiagnostics();

        Trace.WriteLine("WorkerRole.OnStart()");

        try
        {
            Initialize();

            Trace.WriteLine("Resolving jobs...");
            _jobs = _container.ResolveAll<IJob>();

            StartJobs();

            return base.OnStart();
        }
        catch (Exception ex)
        {
            TraceUtil.TraceException(ex);
            throw;
        }
        finally
        {
            Trace.WriteLine("WorkerRole.OnStart - Complete");
            Trace.Flush();
        }
    }

    /// <summary>
    /// Sets up diagnostics.
    /// </summary>
    private void ConfigureDiagnostics()
    {
        DiagnosticMonitorConfiguration dmc =
            DiagnosticMonitor.GetDefaultInitialConfiguration();

        dmc.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(1);
        dmc.Logs.ScheduledTransferLogLevelFilter = LogLevel.Verbose;

        DiagnosticMonitor.Start(Constants.DiagnosticsConnectionString, dmc);
    }

    /// <summary>
    /// Sets up the IoC container etc.
    /// </summary>
    private void Initialize()
    {
        Trace.WriteLine("WorkerRole.Initialize()");

        try
        {
            Trace.WriteLine("Configuring AutoMapper...");
            AutoMapperConfiguration.Configure();

            Trace.WriteLine("Configuring Windsor...");
            _container = new WindsorContainer();

            Trace.WriteLine(string.Format("Installing assemblies from directory...{0}", 
                Path.Combine(Environment.GetEnvironmentVariable(Constants.RoleRoot), Constants.AppRoot)));

            _container.Install(FromAssembly.InDirectory(
                new AssemblyFilter(Path.Combine(Environment.GetEnvironmentVariable(Constants.RoleRoot), Constants.AppRoot))));

            Trace.WriteLine(string.Format("Setting the default connection limit..."));
            ServicePointManager.DefaultConnectionLimit = 12;
        }
        finally
        {
            Trace.WriteLine("WorkerRole.Initialize - Complete");
        }
    }

    /// <summary>
    /// Starts all of the jobs.
    /// </summary>
    private void StartJobs()
    {
        Trace.WriteLine("WorkerRole.StartJobs()");

        try
        {
            foreach (IJob job in _jobs)
            {
                job.Start();
            }
        }
        finally
        {
            Trace.WriteLine("WorkerRole.StartJobs - Complete");
        }
    }

    public override void OnStop()
    {
        Trace.WriteLine("WorkerRole.OnStop()");

        try
        {
            foreach (IJob job in _jobs)
            {
                job.Stop();
            }
            _container.Dispose();
        }
        finally
        {
            Trace.WriteLine("WorkerRole.OnStop - Complete");
        }
    }

    #endregion

    #region Private util classes

    public static class AutoMapperConfiguration
    {
        public static void Configure()
        {
            Mapper.Initialize(x => x.AddProfile<ModelProfile>());
        }
    }

    #endregion
}

TraceUtil 代码:

public static class TraceUtil
{
    public static void TraceException(Exception ex)
    {
        StringBuilder buffer = new StringBuilder();

        while (ex != null)
        {
            buffer.AppendFormat("{0} : ", ex.GetType());
            buffer.AppendLine(ex.Message);
            buffer.AppendLine(ex.StackTrace);

            ex = ex.InnerException;
        }
        Trace.TraceError(buffer.ToString());
    }
}

配置:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  ...
  <system.diagnostics>
    <trace autoflush="true">
      <listeners>
        <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
             name="AzureDiagnostics">
          <filter type="" />
        </add>
      </listeners>
    </trace>
  </system.diagnostics>
</configuration>

一旦工作进程启动,如果我查看 WADLogsTable,我看到的只是“WorkerRole.OnStart” ()”,没有别的!

任何有关问题可能是什么或如何解决此问题的想法将不胜感激。

更新:如果我停止该角色,我也不会看到 OnStop() 方法中的任何调试语句。

更新:一定的诊断配置有误。我以为在本地调试时我看到调试结果正确,但事实证明并非如此。我在输出窗口中看到了所有内容,但在存储表中看不到所有内容。我在开发中看到以下条目:

WorkerRole.OnStart()
WorkerRole.Initialize()
Configuring AutoMapper...

我意识到跟踪输出只是定期上传,但我已经等待了 5 分钟左右,所以我认为这应该足够长,因为我将其设置为 1 分钟。

更新:按照@kwill在评论部分中的建议,我尝试添加文件跟踪侦听器,如下所示:

  <system.diagnostics>
    <trace autoflush="true">
      <listeners>
        <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
             name="AzureDiagnostics">
        </add>
        <add name="File" type="System.Diagnostics.TextWriterTraceListener" initializeData="C:\TextWriterOutput.log" />
      </listeners>
    </trace>
  </system.diagnostics>

这在我的开发环境中工作正常,并且看起来更可靠,并且我得到了所有调试信息这是我所期望的。然而,当我将其部署到暂存时,甚至没有创建 TextWriterOutput.log 文件!

我真的需要一种可靠的方法来从我的工作者角色中进行调试,以便我可以解决最终的问题,即我的工作无法正常工作 - 此时我仍然不知道他们在尝试做什么,因为我无法进行任何调试!

更新:我很确定大多数人建议的缺少 dll 的想法不是问题。为了希望证明这一点,我已经重写了运行方法,如下所示,我看到“心跳...”调试出来了。在我看来,诊断功能或至少我配置它的方式是不可靠的,这使我无法调查我的作业到底为何没有运行。

    public override void Run()
    {
        Trace.WriteLine("LearningMiles.JobProcessor.WorkerRole.Run()", "Information");

        try
        {
            while (true)
            {
                Thread.Sleep(10000);
                Trace.WriteLine("Heartbeat...", "Verbose");
            }
        }
        catch (Exception ex)
        {
            TraceUtil.TraceException(ex);
            throw;
        }
        finally
        {
            Trace.WriteLine("LearningMiles.JobProcessor.WorkerRole.Run() - Complete", "Information");
        }
    }

更新:我现在已将此问题交叉发布到 Windows Azure MSDN 论坛

更新:根据评论中的建议,我现在已尝试删除所有“有用”代码。在开发过程中,这导致所有调试都被输出。然后我尝试只是删除对AutomapperConfiguration.Configure()的调用,因为之前我在该调用之后没有看到任何结果。这导致一些跟踪语句不再出现。但重要的是,我看到了我放入“作业”中的跟踪语句。由于我最终想要解决的是未运行的作业,因此我将该版本的代码部署到暂存,但在那里我只看到 OnStart() 跟踪和“心跳”跟踪。我不认为这真的有帮助,但也许它会给某人一些想法。

I have a worker role that works perfectly in development but doesn't work when deployed. "Doesn't work" is rather vague, but that's really all I have to go on as I'm not seeing any errors or anything (in the event log anyway - maybe there is somewhere else I can look). I have added some trace statements to my code and I'm seeing the first one come out, but none of the others.

WorkerRole Code:

public class WorkerRole : RoleEntryPoint
{
    #region Member variables

    private IWindsorContainer _container;

    private IJob[] _jobs;

    #endregion

    #region Methods

    public override bool OnStart()
    {
        ConfigureDiagnostics();

        Trace.WriteLine("WorkerRole.OnStart()");

        try
        {
            Initialize();

            Trace.WriteLine("Resolving jobs...");
            _jobs = _container.ResolveAll<IJob>();

            StartJobs();

            return base.OnStart();
        }
        catch (Exception ex)
        {
            TraceUtil.TraceException(ex);
            throw;
        }
        finally
        {
            Trace.WriteLine("WorkerRole.OnStart - Complete");
            Trace.Flush();
        }
    }

    /// <summary>
    /// Sets up diagnostics.
    /// </summary>
    private void ConfigureDiagnostics()
    {
        DiagnosticMonitorConfiguration dmc =
            DiagnosticMonitor.GetDefaultInitialConfiguration();

        dmc.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(1);
        dmc.Logs.ScheduledTransferLogLevelFilter = LogLevel.Verbose;

        DiagnosticMonitor.Start(Constants.DiagnosticsConnectionString, dmc);
    }

    /// <summary>
    /// Sets up the IoC container etc.
    /// </summary>
    private void Initialize()
    {
        Trace.WriteLine("WorkerRole.Initialize()");

        try
        {
            Trace.WriteLine("Configuring AutoMapper...");
            AutoMapperConfiguration.Configure();

            Trace.WriteLine("Configuring Windsor...");
            _container = new WindsorContainer();

            Trace.WriteLine(string.Format("Installing assemblies from directory...{0}", 
                Path.Combine(Environment.GetEnvironmentVariable(Constants.RoleRoot), Constants.AppRoot)));

            _container.Install(FromAssembly.InDirectory(
                new AssemblyFilter(Path.Combine(Environment.GetEnvironmentVariable(Constants.RoleRoot), Constants.AppRoot))));

            Trace.WriteLine(string.Format("Setting the default connection limit..."));
            ServicePointManager.DefaultConnectionLimit = 12;
        }
        finally
        {
            Trace.WriteLine("WorkerRole.Initialize - Complete");
        }
    }

    /// <summary>
    /// Starts all of the jobs.
    /// </summary>
    private void StartJobs()
    {
        Trace.WriteLine("WorkerRole.StartJobs()");

        try
        {
            foreach (IJob job in _jobs)
            {
                job.Start();
            }
        }
        finally
        {
            Trace.WriteLine("WorkerRole.StartJobs - Complete");
        }
    }

    public override void OnStop()
    {
        Trace.WriteLine("WorkerRole.OnStop()");

        try
        {
            foreach (IJob job in _jobs)
            {
                job.Stop();
            }
            _container.Dispose();
        }
        finally
        {
            Trace.WriteLine("WorkerRole.OnStop - Complete");
        }
    }

    #endregion

    #region Private util classes

    public static class AutoMapperConfiguration
    {
        public static void Configure()
        {
            Mapper.Initialize(x => x.AddProfile<ModelProfile>());
        }
    }

    #endregion
}

TraceUtil Code:

public static class TraceUtil
{
    public static void TraceException(Exception ex)
    {
        StringBuilder buffer = new StringBuilder();

        while (ex != null)
        {
            buffer.AppendFormat("{0} : ", ex.GetType());
            buffer.AppendLine(ex.Message);
            buffer.AppendLine(ex.StackTrace);

            ex = ex.InnerException;
        }
        Trace.TraceError(buffer.ToString());
    }
}

Config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  ...
  <system.diagnostics>
    <trace autoflush="true">
      <listeners>
        <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
             name="AzureDiagnostics">
          <filter type="" />
        </add>
      </listeners>
    </trace>
  </system.diagnostics>
</configuration>

Once the worker has started, if I look in the WADLogsTable, all I see is "WorkerRole.OnStart()" and nothing else!

Any ideas on what the problem could be or how to troubleshoot this would be appreciated.

Update: If I stop the role, I don't see any of the debug statements from the OnStop() method either.

Update: I must have something configured incorrectly with my diagnostics. I thought I was seeing my debug come out correctly when debugging locally, but it turns out I'm not. I see everything in the output window, but I don't see everything in the storage table. I am seeing the following entries in development:

WorkerRole.OnStart()
WorkerRole.Initialize()
Configuring AutoMapper...

I realize that the trace output is only periodically uploaded, but I've waited 5 minutes or so, so I think this should be long enough, since I have it set to 1 minute.

Update: As suggested by @kwill in the comments section I have tried adding a file trace listener as follows:

  <system.diagnostics>
    <trace autoflush="true">
      <listeners>
        <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
             name="AzureDiagnostics">
        </add>
        <add name="File" type="System.Diagnostics.TextWriterTraceListener" initializeData="C:\TextWriterOutput.log" />
      </listeners>
    </trace>
  </system.diagnostics>

This works fine in my development environment and seems more reliable as well as I get all of the debug out that I would expect. When I deploy it to staging however, the TextWriterOutput.log file isn't even created!

I really need a reliable way of getting debug out of my worker role so that I can troubleshoot the ultimate problem, which is that my jobs aren't working - at this point I still have no idea what they are even trying to do as I can't get any debug out!

Update: I am pretty sure that the missing dll idea suggested by most people is not the problem. To hopefully prove this, I have overridden the run method as shown below and I am seeing the "Heartbeat..." debug come out. It seems to me that either the diagnostics functionality or at least the way I have it configured is unreliable, which is preventing me from investigating why on earth my jobs aren't running.

    public override void Run()
    {
        Trace.WriteLine("LearningMiles.JobProcessor.WorkerRole.Run()", "Information");

        try
        {
            while (true)
            {
                Thread.Sleep(10000);
                Trace.WriteLine("Heartbeat...", "Verbose");
            }
        }
        catch (Exception ex)
        {
            TraceUtil.TraceException(ex);
            throw;
        }
        finally
        {
            Trace.WriteLine("LearningMiles.JobProcessor.WorkerRole.Run() - Complete", "Information");
        }
    }

Update: I have now cross posted this problem on the Windows Azure MSDN forum.

Update: As suggested in the comments, I have now tried removing all 'useful' code. In development this resulted in all of the debug being output. I then tried just removing the call to AutomapperConfiguration.Configure() since previously I was seeing nothing come out after that call. This resulted in some of the trace statements not coming out again. Importantly however, I was seeing the trace statements that I have put in the "jobs". Since it's the jobs not running that I ultimately want to resolve, I deployed that version of the code to staging, but there I just see the OnStart() trace and the "heartbeat" trace. I don't think this really helps, but maybe it will give someone some ideas.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

雪若未夕 2025-01-15 18:31:18

鉴于调用了 OnStart() 跟踪,但没有调用 Initialize(),我的猜测是,Initialize() 中的代码引用的程序集之一没有被复制到部署中。请记住,.Net JIT 一次编译一个方法,并且由于这种行为,显示 OnStart 跟踪消息是有意义的(因为到目前为止,除了 Windows Azure 和标准 .Net 框架程序集之外,几乎没有其他内容引用) 。但是,当 CLR 进入 JIT Initialize 方法时,它会尝试加载多个第三方程序集(AutoMapper 和 Windsor),这些程序集可能未正确打包,但可能已被 GACced 或在模拟器运行时在本地可用。

可以尝试以下几件事:

  1. 从 Visual Studio 手动“打包”您的部署,并仔细查看构建输出。很多时候,VS 会捕获丢失的程序集并告诉您(不幸的是作为警告,而不是错误)您丢失了某些内容。
  2. 如果您在输出中没有看到任何明显的内容,请查看 cspkg 文件本身(记住它只是一个 ZIP 文件,其中包含更多 ZIP 文件)并确保您的应用程序/角色需要的任何引用程序集都在其中。或者,连接到 VM 并检查这些程序集的 approot。
  3. 您也许能够在虚拟机的事件日志中找到一个条目,显示您的应用程序无法加载程序集。

Given the OnStart() trace is called, but not the Initialize(), my guess is that one of the assemblies referenced by the code in Initialize() is not being copied to the deployment. Remember that .Net JIT-compiles one method at a time, and because of that behavior it would make sense that the OnStart trace message shows up (as there's little other than the Windows Azure and standard .Net framework assemblies referenced up to that point). However, when the CLR goes to JIT the Initialize method, it then tries to load several third-party assemblies (AutoMapper and Windsor) that may not be packaged correctly, but could be GACced or otherwise available locally when the emulator runs.

A couple of things to try:

  1. Manually "Package" your deployment from Visual Studio and take a careful look at the build output. Many times, VS will catch your missing assemblies and tell you (unfortunately as a warning, not an error) that you're missing something.
  2. If you don't see anything in the output that looks obvious, take a look at the cspkg file itself (remember it's just a ZIP file with more ZIP files in it) and make sure any referenced assemblies your application/role needs are in there. Alternately, connect to the VM and check the approot for those assemblies.
  3. You may be able to find an entry in the VM's event log that shows that your application failed to load an assembly.
锦欢 2025-01-15 18:31:18

通常,此类问题的根本原因是缺少依赖项。之前的回答已经在这方面提出了很好的建议。

根据您的配置,跟踪日志每分钟传输到 Azure 存储一次。如果您的工作进程崩溃,您可能会丢失一些最后的跟踪消息。要解决此问题,请尝试在异常处理程序中添加 Thread.Sleep(TimeSpan.FromMinutes(2)) 以确保异常日志刷新到存储。

最后,如果其他一切都失败了,我建议您尝试使用 WinDbg 调试您的角色。为您的角色启用远程桌面。登录角色并关闭 IE 安全浏览,以便您可以安装东西。然后从 http:// 下载并安装 Windows 调试工具www.microsoft.com/download/en/details.aspx?displaylang=en&id=8279。该软件包包含整个 Windows SDK,但您可以选择仅安装适用于 Windows 的调试工具。

然后运行 ​​WinDbg 并附加到 WaWorkerHost.exe。在 WinDbg 中,

.loadby sos clr   // load the SOS extension that allows you to do managed debugging
sxe clr           // break on CLR exceptions
g                 // continue

当出现 CLR 异常时,WinDbg 现在应该中断执行。当它中断时,执行

!PrintException

以查看异常详细信息。您可能需要在角色启动中添加另一个 Thread.Sleep 调用,以便您有时间在进程退出之前附加调试器。

More often than not, the root cause of problems like this is missing dependencies. There are already good suggestions on this front in previous answers.

The trace logs are transferred to Azure storage once per minute as per your configuration. If your worker process crashes, you might lose some of the last trace messages. To work around this, try adding a Thread.Sleep(TimeSpan.FromMinutes(2)) in your exception handlers to ensure that the exception log gets flushed to storage.

Finally, if everything else fails, I suggest you try debugging your role with WinDbg. Enable Remote Desktop for your role. Log in to the role and switch off IE safe browsing so that you can install stuff. Then download and install Debugging Tools for Windows from http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=8279 . This package contains the entire Windows SDK, but you can select to install the Debugging Tools for Windows only.

Then run WinDbg and attach to WaWorkerHost.exe. In WinDbg, do

.loadby sos clr   // load the SOS extension that allows you to do managed debugging
sxe clr           // break on CLR exceptions
g                 // continue

WinDbg should now break execution when there is an CLR exception. When it breaks, execute

!PrintException

to see exception details. You may want to add another Thread.Sleep call in your role startup to give you time to attach the debugger before the process exits.

扛起拖把扫天下 2025-01-15 18:31:18

感谢 MSDN 论坛,我已经能够排查并解决我的问题。

我的作业未执行的原因是以下行:

_container.Install(FromAssembly.InDirectory(
                    new AssemblyFilter(Path.Combine(Environment.GetEnvironmentVariable(Constants.RoleRoot), Constants.AppRoot))));

登台的角色根是 E:。 Path.Combine() 有一个晦涩的实现,您可以在 这个答案。这意味着 Castle 正在 E:approot 中搜索程序集,而不是像我预期的那样在 E:\approot 中搜索。我现在正在使用以下方法构建 approot 路径:

    private string GetAppRoot()
    {
        string root = Environment.GetEnvironmentVariable(Constants.RoleRoot);

        if (root.EndsWith(Path.VolumeSeparatorChar.ToString()))
            root += Path.DirectorySeparatorChar;

        return Path.Combine(root, Constants.AppRoot);
    }

这已经解决了我的主要问题,我现在看到作业按预期执行。

我只能通过在提升的执行上下文中运行辅助角色来解决此问题,以便我的跟踪数据可以写入文件。我仍然不知道为什么,并且想听听为什么跟踪语句没有正确传输到存储的任何想法。

Thanks to an answer on the MSDN forum, I have been able to troubleshoot and resolve my problem.

The reason why my jobs were not being executed was due to the line below:

_container.Install(FromAssembly.InDirectory(
                    new AssemblyFilter(Path.Combine(Environment.GetEnvironmentVariable(Constants.RoleRoot), Constants.AppRoot))));

The role root on staging is E:. Path.Combine() has an obscure implementation which you can read more about in this SO answer. What this meant was that Castle was searching for assemblies in E:approot rather than E:\approot as I expected. I am now constructing the approot path with the method below:

    private string GetAppRoot()
    {
        string root = Environment.GetEnvironmentVariable(Constants.RoleRoot);

        if (root.EndsWith(Path.VolumeSeparatorChar.ToString()))
            root += Path.DirectorySeparatorChar;

        return Path.Combine(root, Constants.AppRoot);
    }

That has resolved my main issue and I am now seeing the jobs execute as expected.

I was only able to troubleshoot this issue by running the worker role in an elevated execution context so that my trace data could be written to a file. I still don't know why, and would like to hear of any ideas why, the trace statements were not being transferred to storage correctly.

我早已燃尽 2025-01-15 18:31:18

您是说您得到了跟踪

   "WorkerRole.OnStart()"

,但没有得到跟踪吗?

   "WorkerRole.Initialize()"

这似乎不太可能,因为两个跟踪语句一个接一个地执行。

您是否尝试通过 RDP 连接到虚拟机以查看 WaWorkerHost.exe 进程是否崩溃?

Are you saying that you get the trace

   "WorkerRole.OnStart()"

but not the trace

   "WorkerRole.Initialize()"

That seems highly unlikely since the two trace statements execute one right after the other.

Have you tried to RDP to the VM to see if the WaWorkerHost.exe process is crashing?

深居我梦 2025-01-15 18:31:18

我相信道格·罗勒有正确的答案。项目中很有可能缺少 DLL,可以通过检查包来验证。请注意,如果您使用 1.6 SDK 之前的版本,则需要以未加密的方式创建包。

我想补充两点。

  1. 在某些情况下,将“复制本地”设置为 true 仅在以下情况下才有效:
    项目文件是手动编辑的,并明确给出程序集的完整路径。 (当程序集也存在于本地计算机的 GAC 中时,就会发生这种情况)。

  2. 如果引用的依赖项位于程序集中,则位于
    由 Azure 角色程序集引用,依赖项执行
    没有得到副本。在这种情况下,这些依赖项也需要
    被添加到角色组件中,即使它们不被角色组件使用。 (这有点难以置信,但我确实遇到了这个问题)。

I believe that Doug Rohrer has the right answer. There is a high chance that you have missing DLLs in the project which can be verified by examining the package. Be aware that the package needs to be created unencrypted if you are using a version earlier that the 1.6 SDK.

I would like to add two points.

  1. Setting “Copy Local” to true, in some cases, only works if the
    project file is edited manually and explicitly given the full path of the assembly. (This occurs when the assembly is also present in the GAC of the local machine).

  2. If the dependencies referenced are in an assembly which, is in
    turned referenced by the Azure role assembly, the dependencies do
    not get copies over. In which case these dependencies also need to
    be added to the role assembly even though they are not used by it. (This is kind of difficult to believe but I did run into this issue).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文