我有一个用C#编写的Azure AppService,它使用NHibernate连接到Azure之外托管的Server数据库。连接字符串如下所示:
Data Source=tcp:SQL1234.3rdpartyserver.net;MultipleActiveResultSets=true;Initial Catalog=DB_SQL1234;User Id=****;Password=****;大多数情况下,一切正常,但偶尔我的AppService会失去连接,我得到了以下异常:
System.Data.SqlClient.SqlException: A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: TCP Provider, error: 0 - A connection
attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.) ---> System.ComponentModel.Win32Exception: A connection
attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond --- End of inner exception stack trace
---
at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, Boolean applyTransientFaultHandling, String accessToken)
at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
at System.Data.SqlClient.SqlConnection.Open()
at NHibernate.Connection.DriverConnectionProvider.GetConnection()
at NHibernate.Tool.hbm2ddl.SuppliedConnectionProviderConnectionHelper.Prepare()
at NHibernate.Tool.hbm2ddl.SchemaMetadataUpdater.GetReservedWords(Dialect dialect, IConnectionHelper connectionHelper)
at NHibernate.Tool.hbm2ddl.SchemaMetadataUpdater.Update(ISessionFactoryImplementor sessionFactory)
at NHibernate.Impl.SessionFactoryImpl..ctor(Configuration cfg, IMapping mapping, Settings settings, EventListeners listeners)
at NHibernate.Cfg.Configuration.BuildSessionFactory()
at FluentNHibernate.Cfg.FluentConfiguration.BuildSessionFactory() --- End of inner exception stack trace这是不知道怎么发生的:我没有更新任何连接字符串,也没有重新启动我的AppService等等。应用程序只能从Azure连接到数据库。如果我在本地启动应用程序,那么使用相同的连接字符串,一切都可以正常工作。此外,我还可以从SSMS连接到DB罚款。
有时候,重新启动我的AppService会有所帮助,重新启动之后连接就会恢复。但有时也没什么用。
我怀疑这个连接可能被Azure的防火墙阻塞了,但是我不知道如何检查这个。我的应用程序正在使用B1应用程序服务计划,而且我还没有在我的Azure中创建任何自定义防火墙或负载平衡器。实际上,这个AppService是我目前拥有的唯一资源。
有什么可能导致这种情况的原因,以及如何解决这个问题?
发布于 2020-07-31 04:32:10
你很有可能会精疲力竭。在“诊断和解决问题”项下,Blade搜索"TCP连接“,这将显示您的应用程序正在建立多少TCP连接。如果有大量连接到SQL (~128+),那么您的应用程序处于一种很可能会遇到超时异常的状态。

App服务运行在201-400范围内,用于多租户应用程序服务,因此一旦应用程序对特定的目的地IP/端口进行了128个单独的TCP连接,您可能会看到这些问题。https://learn.microsoft.com/en-us/azure/load-balancer/load-balancer-outbound-connections
我的建议如下:
发布于 2020-07-19 15:43:00
这是一个非常普遍和频繁的问题,它的发生是由于网络不稳定。解决方法是使用重试模式包装代码块。
https://learn.microsoft.com/en-us/azure/architecture/patterns/retry
发布于 2020-07-19 16:34:49
在Server防火墙中,可以配置/允许应用程序服务的出站IP地址。您可以从App的属性部分或通过使用CLI获取这些IP。
https://stackoverflow.com/questions/62980100
复制相似问题