千家信息网

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

发表于:2025-01-20 作者:千家信息网编辑
千家信息网最后更新 2025年01月20日,这篇文章将为大家详细讲解有关如何解决.NET Core中GetHostAddressesAsync引起的EnyimMemcached死锁问题,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这
千家信息网最后更新 2025年01月20日如何解决.NET Core中GetHostAddressesAsync引起的EnyimMemcached死锁问题

这篇文章将为大家详细讲解有关如何解决.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 GetHostAddressesAsync(string hostNameOrAddress){  NameResolutionPal.EnsureSocketsAreInitialized();  return Task.Factory.FromAsync(    (arg, requestCallback, stateObject) => BeginGetHostAddresses(arg, requestCallback, stateObject),    asyncResult => EndGetHostAddresses(asyncResult),    hostNameOrAddress,    null);}

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

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

Task 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 包都发布出来。

关于"如何解决.NET Core中GetHostAddressesAsync引起的EnyimMemcached死锁问题"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

方法 问题 代码 死锁 同步 就是 源代码 地方 篇文章 最大 诧异 不用 办法 只是 命令 更多 服务器 流氓 访问量 障碍 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 明日之后新服务器营地推荐 服务器怎么提高数据 青岛鑫企点网络技术 迷你世界的服务器地址是多少 hana中用什么数据库 华为手机网络安全权识别怎么解除 深圳尚睿达科技互联网公司 软件开发文档和使用指南 抚顺软件开发公司排名 网络安全教育观后感作文交警 河北大秦网络技术有限公司 云桌面管理服务器如何实现 深圳千阳网络技术有限公司官网 安邦护卫网络安全招标 数据库附加错误823 属于外国数据库的是 网络安全 东南大学 六盘水服务器云存储供应商 查询选修数据库的学生学号姓名 软件开发和移动技术哪个难 博途怎样连接数据库 数据库事务教程 pg数据库前100条数据 网络技术大咖 数据库审计工作复杂吗 金牛区零点软件开发有限公司 常州机电计算机网络技术 谷歌服务器什么时候出的 数据库查询一个时间段内的 哈工大网络安全就业
0