【Azure 应用服务】App Service/Azure Function的出站连接过多而引起了SNAT端口耗尽,导致一些新的请求出现超时错误(Timeout)
问题描述
当需要在应用中有大量的出站连接时候,就会涉及到SNAT(源地址网络转换)耗尽的问题。而通过Azure App Service/Function的默认监控指标图表中,却没有可以直接查看到SNAT是否耗尽的问题(可以间接参考App Service Plan级中Metrics的 Socket Outbound All指标,但是由于它是整个Plan下所有App Service的汇总数据,不能直接表明SNAT是否超过128的限制)。
这里所说的出站连接如:SQL数据库, Redis缓存以及其他的Restful API等等需要从App Service中向外发出的请求。当SNAT耗尽后,会出现以下一种或多种问题:
- App Service的响应速度缓慢。
- 间歇性 5xx 错误或“错误的网关”错误
- 超时错误消息
- 无法连接到外部终结点(例如 SQL DB,Redis,及其他API等)
问题分析
因为App Service是部署在云服务中,所以它也遵循着一个集群中很多实例(VM)通过负载均衡器的前端 IP 建立出站连接,所以出站的端口就成了用于维护不同流的唯一标识符。 因为在网络流量的五元组中
- 目标 IP
- 目标端口
- 源 IP
- 源端口
- 协议
如访问Redis服务(redistest01.redis.cache.chinacloudapi.cn 6380),目标IP为固定不变为RedisHost,而端口则固定为6380,源IP为当前App Service的出站IP,协议方式为Redis的序列化协议(RESP)。以上1,2,3,5都不可变的情况下,只有4 源端口可以改变,所以这里就需要使用SNAT。 负载均衡器的前端 IP 分配的每个公共 IP 都会为其后端池成员分配 64,000 个 SNAT 端口,后端池中大约有400多个实例,所以大约分配到每个实例的SNAT端口为64,000/400 =160(最大), 但是实际上分配的个数为128个。
间歇性连接问题的主要原因是在建立新的出站连接时遇到限制。 可以命中的限制包括:
- TCP 连接数:可以建立的出站连接数有限制。 对出站连接的限制与使用的辅助角色的大小关联。
- SNAT 端口: Azure 使用源网络地址转换 (SNAT) 和负载均衡器 (不向客户公开,) 与公共 IP 地址进行通信。 最初为 Azure 应用服务中的每个实例预分配了 128 个 SNAT 端口。 SNAT 端口限制会影响与相同地址和端口组合的打开连接。 如果应用与混合的地址/端口组合建立了连接,则不会用尽 SNAT 端口。 重复调用同一个地址/端口组合时,会用尽 SNAT 端口。 释放某个端口以后,即可根据需要重复使用该端口。 只有在等待 4 分钟后,Azure 网络负载均衡器才会从关闭的连接回收 SNAT 端口。
当应用程序或功能快速打开新的连接时,它们可能很快就会耗尽预分配的配额(128 个端口)。 然后,应用程序或功能会一直受到阻止,直到通过动态分配额外的 SNAT 端口或者通过重复使用回收的 SNAT 端口提供了新的 SNAT 端口为止。 如果你的应用程序用完了 SNAT 端口,则会出现间歇性的出站连接问题。
解决办法
避免 SNAT 端口问题意味着需要避免对同一主机和端口反复创建新连接。 连接池是解决该问题的更显而易见的方法之一。
如短时间无法修改代码,基于App Service, Azure Function的易扩展的特性,可以增加实例个数来及时缓解SNAT的受限问题。当每增加一个实例,SNAT端口即可增加128个。
建立连接池的方式一:HttpClientFactory 建立 HTTP 连接池
尽管 HttpClient 实现了 IDisposable 接口,但它是为重复使用而设计的。 关闭 HttpClient 的实例使套接字在 TIME_WAIT 一小段时间内处于打开状态。 如果经常使用创建和处置对象的代码路径 HttpClient ,应用可能会耗尽可用的套接字。 ASP.NET Core 2.1 中引入了HttpClientFactory作为此问题的解决方案。 它处理池 HTTP 连接以优化性能和可靠性。
建议:
- 不要 直接创建和释放
HttpClient实例。 - 请 使用 HttpClientFactory 来检索
HttpClient实例。
示例部分
1)以下代码即可复现SNAT快速耗尽的情况(没有及时释放Response资源)
public string Index(string url)
{
var request = HttpWebRequest.Create(url);
request.GetResponse(); return "OK";
}
可以修改为:
public string Fin(string url)
{
var request = HttpWebRequest.Create(url);
var response = request.GetResponse();
response.Close(); return "OK";
}
2)下面使用Using来释放httpclient对象,但是也是用以导致SNAT耗尽的问题。
public async Task<string> Client(string url)
{
using (var client = new HttpClient())
{
await client.GetAsync(url);
} return "OK";
}
可以考虑重用HttpClient来缓解SNAT耗尽问题
private static Lazy<HttpClient> _client = new Lazy<HttpClient>(); public async Task<string> ReuseClient(string url)
{
var client = _client.Value;
await client.GetAsync(url);
return "OK";
}
参考资料
使用 SNAT 进行出站连接(负载均衡器默认端口分配) : https://docs.microsoft.com/zh-cn/azure/load-balancer/load-balancer-outbound-connections#default-port-allocation
排查 Azure 应用服务中的间歇性出站连接错误:https://docs.microsoft.com/zh-cn/azure/app-service/troubleshoot-intermittent-outbound-connection-errors#avoiding-the-problem
SNAT with App Service,介绍Azure App Service中SNAT的原理,问题,及如何避免?:https://www.cnblogs.com/lulight/articles/13543209.html
【Azure 应用服务】App Service/Azure Function的出站连接过多而引起了SNAT端口耗尽,导致一些新的请求出现超时错误(Timeout)的更多相关文章
- 【应用服务 App Service】快速获取DUMP文件(App Service for Windows(.NET/.NET Core))
问题情形 当应用在Azure 应用服务App Service中运行时,有时候出现CPU,Memory很高,但是没有明显的5XX错误和异常日志,有时就是有异常但是也不能明确的指出具体的代码错误.当面临这 ...
- 【应用服务 App Service】Azure 应用服务测试网络访问其他域名及请求超时限制(4分钟 ≈ 230秒)
测试App Service是否可以访问其他DNS 当应用服务(Azure App Service)创建完成后,想通过ping命令来查看是否可以访问其他站点或解析DNS,但是发现ping命令无法使用.这 ...
- 【应用服务 App Service】App Service中抓取网络日志
问题描述 众所周知,Azure App Service是一种PaaS服务,也就是说,IaaS层面的所有内容都由平台维护,所以使用App Service的我们根本无法触碰到远行程序的虚拟机(VM), 所 ...
- 【应用服务 App Service】解决无法从Azure门户SSH登录问题
问题描述 中国区的Azure App Service(应用服务)已经支持创建Docker并选择Linux环境.在使用中,我们可以继续通过kudu站点的方式登录查看站点的一些日志及部署文件.它的登录方式 ...
- 【应用服务 App Service】Azure App Service 中如何安装mcrypt - PHP
问题描述 Azure App Service (应用服务)如何安装PHP的扩展 mcrypt(mcrypt 是php里面重要的加密支持扩展库) 准备条件 创建App Service, Runtime ...
- 【应用服务 App Service】在Azure App Service中使用WebSocket - PHP的问题 - 如何使用和调用
问题描述 在Azure App Service中,有对.Net,Java的WebSocket支持的示例代码,但是没有成功的PHP代码. 以下的步骤则是如何基于Azure App Service实现PH ...
- 【应用服务 App Service】发布到Azure上的应用显示时间不是本地时间的问题,修改应用服务的默认时区
问题情形 应用程序发布到App Service后,时间显示不是北京时间,默认情况为UTC时间,比中国时间晚 8 个小时. 详细日志 无 问题原因 Azure 上所有的服务时间都采用了 UTC 时间. ...
- 【应用服务 App Service】当遇见某些域名在Azure App Service中无法解析的错误,可以通过设置指定DNS解析服务器来解决
问题情形 当访问部署在Azure App Service中的应用返回 "The remote name could not be resolved: ''xxxxxx.com'" ...
- 【应用服务 App Service】当使用EntityFrameWorkCore访问Sql Server数据库时,在Azure App Service会出现Cannot create a DbSet for ** because this type is not included in the model for the context的错误
问题情形 使用EF Core访问数据库,在本地运行正常,发布到App Service后,偶尔出现了Cannot create a DbSet for ** because this type is n ...
随机推荐
- 自己写的一个抢票加速的Python小程序源码分享-----纯属娱乐
最近这段时间频频看到微信群里发什么 抢票加速,智行.携程.飞猪.美团,对于我这能坐客车就不坐火车的人来说,无所谓靠谱不靠谱 突发奇想的整理了下整个抢票加速的逻辑,写了这个小程序,代码很low,拒绝批评 ...
- Hbase ——Not only SQL
HBase -- NoSQL_Not Only SQL NoSQL数据库: 不遵循传统的RDBMS模型 解决数据库的可伸缩性和可用性(多机器) 数据是非关系的(可切分),不使用sql语句 不针对原子性 ...
- C#语言特性及发展史
本文按照C#语言的发展历史,介绍C#每个版本的新增特性,主要参考微软官方文档.了解这些语言特性可以帮助我们更高效的编写C#代码. C# 1.0 与Visual Studio .NET 2002一起发布 ...
- web前端学习笔记(python)(一)
瞎JB搞]感觉自己全栈了,又要把数据库里面的内容,以web形式展示出来,并支持数据操作.占了好多坑.....慢慢填(主要参考廖雪峰的官网,不懂的再百度) 一.web概念 Client/Server模式 ...
- 使用pycallgraph分析python代码函数调用流程以及框架
技术背景 在上一篇博客中,我们介绍了使用量子计算模拟器ProjectQ去生成一个随机数,也介绍了随机数的应用场景等.但是有些时候我们希望可以打开这里面实现的原理,去看看在产生随机数的过程中经历了哪些运 ...
- springboot源码(4)
我们上3个篇章写了springboot的自动装配.servlet组件的注入以及web容器实现内嵌的原理,现在我们来看springboot启动过程中到底做了些什么,也就是打开我们的run方法: 这里我们 ...
- pytorch(09)transform模块(基础)
transforms transforms运行机制 torchvision.transforms:常用的图像预处理方法 torchvision.datasets:常用数据及的dataset实现,mni ...
- [通达OA] RCE + Getshell
跟着大佬轻松复现:https://github.com/jas502n/OA-tongda-RCE 通达OA下载:https://www.tongda2000.com/download/2019.ph ...
- golang——net/rpc/jsonrpc包学习
1.jsonrpc包 该实现了JSON-RPC的ClientCodec和ServerCodec接口,可用于rpc包. 可用于跨语言使用go rpc服务. 2.常用方法 (1)func Dial(net ...
- SpringMVC-05 Json交互处理
SpringMVC-05 Json交互处理 Json 1.什么是JSON? JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式,目前使用特别 ...