解决 .NET Core 中 GetHostAddressesAsync 引起的 EnyimMemcached 死锁问题

 更新时间:2016年09月22日 09:43:38   作者:dudu  
这篇文章主要介绍了解决 .NET Core 中 GetHostAddressesAsync 引起的 EnyimMemcached 死锁问题的相关资料,需要的朋友可以参考下

在我们将站点从 ASP.NET + Windows 迁移至 ASP.NET Core + Linux 的过程中,目前遇到的最大障碍就是 —— 没有可用的支持 .NET Core 的 memcached 客户端。

我们一直用的是 EnyimMemcached ,在没有其它选择的情况下,我们自己尝试着将 EnyimMemcached 迁移至 .NET Core。。。基于 .NET Core 修改好了代码,在开发环境下测试通过,在 Linux 服务器上自己访问很正常(没有并发访问量),但是只要接入一定的访问量就会发生死锁(deadlock),浏览器请求卡死。

这个问题困扰了我们很长时间,昨天才定位到是发生在将 memcached 服务器名称解析为 IP 地址的时候。

var addresses = System.Net.Dns.GetHostAddressesAsync(host).Result;

这是我们在将 EnyimMemcached 迁移至 .NET Core 时修改过的代码,之前调用的是同步方法:

var addresses = System.Net.Dns.GetHostEntry(host);

由于在 .NET Core Framework 的 System.Net.Dns 中没有同步方法,只有异步方法,所以我们只能这样调用异步方法。

看到上面的代码,你也许会诧异:怎么用 .Result ,为什么不用 await ?不死锁才怪呢。。。

你的诧异非常正确。我们也深知 .Result 的危害,在平时的代码中坚决不用。但当时在修改 EnyimMemcached 的代码时,由于这个方法是在 MemcachedClient 的构造函数中调用的,没法改为 await 调用,被迫用了 .Result ,然后又把这个地方的修改给忘了。。。昨天才刚刚发现,立马意识到罪魁祸首非常有可能就是这里的 .Result ,于是以此为突破口,想尽一切办法实现在同步方法中调用异步办法,并且在博问中寻求支援 —— 在同步方法中调用异步方法时如何避免死锁问题 。

结果,用尽一切能想到与能找到的同步方法调用异步方法的方法,都没能解决死锁问题。如果实在找不到解决方法,我们准备采用最后一招也是最丑陋的一招 —— 不用 Dns.GetHostAddressesAsync() ,用 ProcessStartInfo 调用命令行命令解析 IP ,比如在 Linux 上用 getent hosts 主机名 。

在准备放弃之前,今天又想了想还有哪些可能带来线索的地方漏掉了呢?突然想到有个重要地方竟然忘了,还没看 Dns.GetHostAddressesAsync() 的源代码实现。虽然不报太大希望,不就是个异步方法吗,但还是要看一下。

于是从 github 上签出 corefx 的源代码,打开 Dns.GetHostAddressesAsync() 源代码一看,感觉有点怪怪的,怎么用了 Task.Factory.FromAsync() ?

public static Task<IPAddress[]> GetHostAddressesAsync(string hostNameOrAddress)
{
  NameResolutionPal.EnsureSocketsAreInitialized();
  return Task<IPAddress[]>.Factory.FromAsync(
    (arg, requestCallback, stateObject) => BeginGetHostAddresses(arg, requestCallback, stateObject),
    asyncResult => EndGetHostAddresses(asyncResult),
    hostNameOrAddress,
    null);
}

开始没反应过来,只是把这段代码贴到博问的补充问题中,在贴完后突然反应过来了,咦,怎么没有 async 关键字?方法名最后是 Async,我们一直以为是 async 方法,而且丝毫没有怀疑过。。。

没有 async ,只是返回参数是 Task 类型,那在同步方法中调用完全没问题,只要在访问 .Result 之前调用一下 .Wait() 方法就行了,于是改为下面的代码:

Task<IPAddress[]> task = System.Net.Dns.GetHostAddressesAsync(host);
task.Wait();
var addresses = task.Result;

死锁问题立马解决!

方法名以 Async 结尾,却不是 async 方法,当时的感想就是 —— 你的眼睛背叛你的心。如果不是我自己的误解(只要以 Async 结尾,就应该是 async 方法),那就是一种流氓行为,就如 HttpClient 的流氓 —— 实现了 IDispose 接口,却没真正 Dispose 。

不管怎么样,这个影响我们迁移至 .NET Core 的最大障碍终于消除了,值得庆祝!

支持 .NET Core 的 EnyimMemcached 的代码还需要一些修改与完善,等修改好了,我们会把源代码与 NuGet 包都发布出来。

通过此文希望能帮助到你解决这种问题,谢谢大家对本站的支持!

相关文章

  • asp.net core集成ElasticSearch实现全文检索功能

    asp.net core集成ElasticSearch实现全文检索功能

    索引是Elasticsearch中用于存储文档的容器,你可以使用Elasticsearch的REST API、官方客户端库(如NEST)或Kibana等工具来创建和管理索引,本文给大家介绍asp.net core集成ElasticSearch实现全文检索功能,感兴趣的朋友一起看看吧
    2024-08-08
  • 对GridView的行加颜色并弹出Kindeditor的实现思路

    对GridView的行加颜色并弹出Kindeditor的实现思路

    本文主要详细介绍下对GridView的行加颜色并弹出Kindeditor,感兴趣的朋友可以了解下,希望可以帮助到你
    2013-04-04
  • asp.net利用Ajax和Jquery在前台向后台传参数并返回值的实例

    asp.net利用Ajax和Jquery在前台向后台传参数并返回值的实例

    asp.net利用Ajax和Jquery在前台向后台传参数并返回值的实例,需要的朋友可以参考一下
    2013-05-05
  • 在SQL Server中使用CLR调用.NET方法实现思路

    在SQL Server中使用CLR调用.NET方法实现思路

    在.NET中新建一个类,并在这个类里新建一个方法,然后在SQL Server中调用这个方法,接下来我们将实现这个功能做了以下几个步骤,详细看下本文,感兴趣的你可不要错过了哈
    2013-02-02
  • .NET 6开发TodoList应用之实现全局异常处理

    .NET 6开发TodoList应用之实现全局异常处理

    因为在项目中,会有各种各样的领域异常或系统异常被抛出来,那么在Controller里就需要进行完整的try-catch捕获,并根据是否有异常抛出重新包装返回值。有没有办法让框架自己去做这件事呢?本文将为大家介绍如何实现全局异常处理,需要的可以参考一下
    2021-12-12
  • System.Web.Routing入门及进阶

    System.Web.Routing入门及进阶

    上面介绍的是最简单的一种定义方式。当然我们可以建立更复杂的规则。其中就包括设定规则的默认值以及设定规则的正则表达式
    2011-12-12
  • VS2010新建站点发布并访问步骤详解

    VS2010新建站点发布并访问步骤详解

    这篇文章主要介绍了VS2010新建站点发布并访问详细步骤,主要以具体每个步骤截图的形式从站点新建,配置IIS再到发布和访问网站进行讲解,需要的朋友可以参考下
    2015-08-08
  • ASP.NET Core中如何实现重定向详解

    ASP.NET Core中如何实现重定向详解

    这篇文章主要给大家介绍了关于ASP.NET Core中如何实现重定向的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • WPF常用控件用法及介绍

    WPF常用控件用法及介绍

    本文详细讲解了WPF常用控件用法及介绍,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-01-01
  • ASP.NET Core MVC 过滤器的使用方法介绍

    ASP.NET Core MVC 过滤器的使用方法介绍

    本篇文章主要介绍了ASP.NET Core MVC 过滤器的使用方法介绍,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09

最新评论