1

我正在使用带有 MySQL 的 ASP.NET MVC 5(使用连接器/网络)。我可以连接到数据库并且一切正常......但是一旦服务器繁忙,我就会收到以下异常:

MySql.Data.MySqlClient.MySqlException (0x80004005):无法连接到任何指定的 MySQL 主机。

我正在使用 NinjectDbContext在 MVC中注入Controller

Bind<ApplicationDbContext>().ToSelf().InRequestScope();

我在 Galera 集群中有 3 个 MySQL 服务器实例,这是我的 ConnectionString:

<add name="MyDB" connectionString="Server=IP1,IP2,IP3; Port=3306; Database=dbname; Uid=u1; Pwd=pswd1;" providerName="MySql.Data.MySqlClient" />

当机器人开始抓取网站时,通常会发生此异常。

我见过类似的这个问题,但是问题是他们永远无法连接到 MySQL(我相信他们ConnectionString是不正确的)但是这个答案(在同一个问题上)似乎描述了我遇到的问题:

如果您的连接最初可以正常工作,但在多次成功连接后您开始看到此错误,则可能是这个问题

总之:如果您打开和关闭连接,Windows 会出于某些愚蠢的原因保留 TCP 端口以供将来使用。多次执行此操作后,它会耗尽可用端口。

答案完美地描述了这个问题,但是他们的解决方案并没有真正的帮助:

  1. 他们建议使用连接池(连接器/网络默认使用连接轮询- 所以这没有帮助)
  2. 他们建议更改 Windows 设置并分配更多端口:

netsh int ipv4 set dynamicport tcp start=10000 num=50000

本文档还解释了一个类似的错误。

但是,我不确定这个问题是否是因为 Windows 端口不足而引起的?

有没有人遇到过类似的问题?

这是我收到的错误的堆栈跟踪:

Exception: UserId: 0 Url: http://www.my-site.com/house-rental/display/109149 
UserAgent: facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php) 
Message: The underlying provider failed on Open. 
InnerException: MySql.Data.MySqlClient.MySqlException (0x80004005): Unable to connect to any of the specified MySQL hosts. 
    at MySql.Data.Failover.FailoverManager.AttemptConnection(MySqlConnection connection, String originalConnectionString, String& connectionString, Boolean mySqlPoolManager) 
    at MySql.Data.MySqlClient.MySqlConnection.Open() at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext](TTarget target, Action`2 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed) 
    at System.Data.Entity.Infrastructure.Interception.DbConnectionDispatcher.Open(DbConnection connection, DbInterceptionContext interceptionContext) 
    at System.Data.Entity.Core.EntityClient.EntityConnection.Open() Exception: System.Data.Entity.Core.EntityException: The underlying provider failed on Open. ---> MySql.Data.MySqlClient.MySqlException: Unable to connect to any of the specified MySQL hosts. 
    at MySql.Data.Failover.FailoverManager.AttemptConnection(MySqlConnection connection, String originalConnectionString, String& connectionString, Boolean mySqlPoolManager) 
    at MySql.Data.MySqlClient.MySqlConnection.Open() at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext](TTarget target, Action`2 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed) 
    at System.Data.Entity.Infrastructure.Interception.DbConnectionDispatcher.Open(DbConnection connection, DbInterceptionContext interceptionContext) 
    at System.Data.Entity.Core.EntityClient.EntityConnection.Open() --- End of inner exception stack trace --- 
    at System.Data.Entity.Core.EntityClient.EntityConnection.Open() at System.Data.Entity.Core.Objects.ObjectContext.EnsureConnection(Boolean shouldMonitorTransactions) 
    at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess) 
    at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass41_0.b__0() at System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption) 
    at System.Data.Entity.Core.Objects.ObjectQuery`1..GetEnumerator>b__31_0() at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext() 
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source) 
    at my-site.Infrastructure.Main.UmbrellaServices.AdPersister`1.GetActiveOrInactiveAd(Int64 adBaseId) 
    in C:\my-site\my-site.source\my-site.Infrastructure.Main\UmbrellaServices\AdPersister.cs:line 46 
        at my-site.Application.Main.Services.AdService`2.GetActiveOrInactiveAd(Int64 adBaseId) 

更新

正如@MarcAlff 所建议的,我运行了以下命令:

SELECT * from performance_schema.host_cache;

结果如下:

| IP      | HOST                                       | HOST_VALIDATED | SUM_CONNECT_ERRORS | COUNT_HOST_BLOCKED_ERRORS | COUNT_NAMEINFO_TRANSIENT_ERRORS | COUNT_NAMEINFO_PERMANENT_ERRORS | COUNT_FORMAT_ERRORS | COUNT_ADDRINFO_TRANSIENT_ERRORS | COUNT_ADDRINFO_PERMANENT_ERRORS | COUNT_FCRDNS_ERRORS | COUNT_HOST_ACL_ERRORS | COUNT_NO_AUTH_PLUGIN_ERRORS | COUNT_AUTH_PLUGIN_ERRORS | COUNT_HANDSHAKE_ERRORS | COUNT_PROXY_USER_ERRORS | COUNT_PROXY_USER_ACL_ERRORS | COUNT_AUTHENTICATION_ERRORS | COUNT_SSL_ERRORS | COUNT_MAX_USER_CONNECTIONS_ERRORS | COUNT_MAX_USER_CONNECTIONS_PER_HOUR_ERRORS | COUNT_DEFAULT_DATABASE_ERRORS | COUNT_INIT_CONNECT_ERRORS | COUNT_LOCAL_ERRORS | COUNT_UNKNOWN_ERRORS | FIRST_SEEN          | LAST_SEEN           | FIRST_ERROR_SEEN    | LAST_ERROR_SEEN     |
+--------------+-------------------------------------------------+----------------+--------------------+---------------------------+---------------------------------+---------------------------------+---------------------+---------------------------------+---------------------------------+---------------------+-----------------------+-----------------------------+--------------------------+------------------------+-------------------------+-----------------------------+-----------------------------+------------------+-----------------------------------+--------------------------------------------+-------------------------------+---------------------------+--------------------+----------------------+---------------------+---------------------+---------------------+---------------------+
| 1.2.3.4 | ip-1-2-3-4.ap-southeast-2.compute.internal | YES            |                  0 |                         0 |                               0 |                               0 |                   0 |                               0 |                               0 |                   0 |                     0 |                           0 |                       26 |                   4010 |                       0 |                           0 |                           8 |                0 |                                 0 |                                          0 |                             0 |                         0 |                  0 |                    0 | 2020-06-14 11:55:18 | 2022-02-15 07:00:13 | 2020-06-14 23:11:17 | 2022-02-15 01:00:02 |

这些是有错误的列:

COUNT_AUTH_PLUGIN_ERRORS: 26
COUNT_HANDSHAKE_ERRORS: 4010
COUNT_AUTHENTICATION_ERRORS: 8
4

3 回答 3

1

看到连接失败的客户端只是故事的一方面。

要解决这个问题,最好的办法是查看另一端,看看服务器对失败的连接说了什么:

SELECT * from performance_schema.host_cache;

特别是,此表将显示每个已知根本原因的统计信息。

请参阅参考手册: https ://dev.mysql.com/doc/refman/8.0/en/performance-schema-host-cache-table.html

于 2022-02-14T14:21:46.170 回答
0

我相信这个问题是由于MySQL 连接器/网络中的一个影响多主机连接字符串的错误引起的。

最好的解决方案是使用MySQLConnector,但是这个解决方案不支持 Entity Framework 6,这是我项目中的一个依赖项。

我解决问题的方法是使用 Amazon RDS 而不是 Galera Cluster ...不同之处在于使用 RDS 时,您将只有一台主机(RDS 负责后台冗余)...所以我不再需要使用多主机连接字符串。

于 2022-02-21T21:21:57.420 回答
0

首先我想说我觉得你已经彻底研究了你的案子。

关于保留端口的建议绝对是有道理的。当连接打开时,Windows 会保留端口以防同一客户端继续运行。Windows 无法判断交换是否完成。

如果我们在一个开源操作系统中,我们将试图找出端口预留机制是如何工作的。对于 Windows,我们对内部机制没有太多的了解。您可以尝试减少保留端口的时间。请看这个链接 https://support.solarwinds.com/SuccessCenter/s/article/Tweaking-Windows-Server-performance-to-prevent-port-exhaustion-when-using-Orion-modules?language=en_US

由于您已经搜索了所有其他途径并且没有其他任何工作,您应该尝试打开更多端口号。命令netsh int ipv4 show dynamicport tcp将显示当前保留的端口。似乎默认范围是 49152 到 65535。如果此范围被您的防火墙阻止,是否有任何限制?

以下 Microsoft Docs 指出 IPR 和 ip6 的动态端口分配不同:https://docs.microsoft.com/fr-fr/troubleshoot/windows-server/networking/default-dynamic-port-range-tcpip-chang. 您是否有可能使用 ip6 进行部分连接?

按照建议允许额外的 40 000 个开放端口听起来可能有些夸张,但您有什么损失呢?

  • 今天你面临一个问题,连接被拒绝。你有一个可能的解决方案。尝试打开端口10000-5000024 小时,看看会发生什么。您没有承担安全风险。它是完全可逆的。你有什么可失去的。
    如果这解决了问题,您可以尝试减小允许的范围,可能使用范围的较高端,但在谈论优化之前,您想知道这是否可以解决问题。
DYNAMIC PORTS

当客户端在端口 3306 上连接时,计算机会为该连接分配一个动态端口,该端口会传送给客户端。

动态端口(也称为专用端口)是在需要端口时分配给进程或服务的端口,通常是在进程或服务启动时。分配动态端口时,操作系统可以使用为此目的指定的端口范围内的任何可用端口。

我建议您阅读有关该主题的更多信息。我在这里找到了一个很好的解释https://www.techtarget.com/searchnetworking/definition/dynamic-port-numbers?amp=1

HARDWARE OR BROADBAND CAUSES 我知道这听起来很明显,您是否检查过您的服务器性能和宽带容量与高峰时间的使用情况?如果硬件或互联网是修改端口设置的限制因素,而 MYSQL 配置无法解决。

于 2022-02-21T01:21:05.520 回答