AWS Lambda连接ClickHouse突然超时,求助故障排查方案
排查Lambda连接ClickHouse超时问题的方法
以下是针对你遇到的Lambda连接ClickHouse超时问题的具体排查步骤:
1. 验证Lambda的VPC网络配置
- 检查私有子网的出站路由:你的Lambda使用
PRIVATE_WITH_EGRESS子网,需确认这些子网的路由表中存在指向NAT网关/实例的0.0.0.0/0路由。如果NAT网关故障或路由缺失,Lambda无法发起跨子网或外部的网络请求。 - 安全组规则校验:
- Lambda的安全组需允许出站访问ClickHouse的8123端口(TCP协议)。
- ClickHouse所在的安全组需允许入站来自Lambda安全组的8123端口流量。
- 子网IP可用性:确认Lambda所在私有子网有剩余可用IP地址,若IP耗尽,无法创建弹性网络接口(ENI)导致无法联网。
2. 检查Lambda执行角色权限
确保Lambda的执行角色拥有以下VPC相关权限(缺失会导致ENI创建失败):
ec2:DescribeNetworkInterfacesec2:CreateNetworkInterfaceec2:DeleteNetworkInterfaceec2:DescribeInstancesec2:AttachNetworkInterface
可通过IAM控制台查看角色的权限策略,确认近期无权限变更操作。
3. 测试Lambda子网到ClickHouse的连通性
- 在Lambda中添加网络测试代码,验证DNS解析和端口可达性:
const { exec } = require('child_process'); exports.handler = async () => { exec('nslookup your-clickhouse-url', (error, stdout) => console.log(stdout)); exec('telnet your-clickhouse-url 8123', (error, stdout) => console.log(stdout)); }; - 在Lambda所在的私有子网和安全组下启动EC2实例,直接测试到ClickHouse的连接,排除Lambda自身的网络异常。
4. 检查ENI资源限制
Lambda在VPC中运行时会创建ENI,若账户或区域的ENI数量达到上限,会导致无法创建新的网络接口,进而无法连接外部服务。可通过EC2控制台的网络接口页面查看是否有失败的创建请求,或联系AWS支持调整配额。
5. ClickHouse服务器状态排查
- 查看ClickHouse的连接限制配置,执行以下SQL确认是否达到连接上限:
SELECT max_connections, current_connections FROM system.settings WHERE name IN ('max_connections', 'current_connections'); - 检查ClickHouse服务器的资源使用情况(CPU、内存、磁盘IO),若服务器负载过高,可能无法及时响应新连接请求。
- 确认ClickHouse的监听地址为
0.0.0.0(允许所有IP访问),而非仅绑定本地IP。
6. Lambda运行时与依赖问题
- 启用ClickHouse客户端的调试模式(将
debug: true),查看连接过程的详细日志,定位是否为客户端库的问题。 - 检查Node.js 18.x runtime是否有版本更新,或ClickHouse客户端包是否有版本变更,尝试回滚到之前正常工作的版本。
7. DNS解析问题
- 确认VPC的DNS服务器(默认VPC DNS或自定义DNS)能正确解析ClickHouse的URL。若使用私有DNS,需检查Route 53私有托管区是否与VPC正确关联。
8. AWS服务状态检查
查看AWS Health Dashboard,确认所在区域的Lambda、VPC或托管ClickHouse服务是否存在故障或性能波动。
你的部署与代码参考
Lambda CDK部署代码
const test = new NodejsFunction(this, 'commonTest', { environment: { }, vpc, vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS, }, securityGroups: [securityGroup], memorySize: 512, timeout: Duration.seconds(60), runtime: lambda.Runtime.NODEJS_18_X, entry: path.join(__dirname, `../resources/test/test.ts`), handler: 'handler' });
Lambda内ClickHouse客户端代码
const clickhouse = new ClickHouse({ url, port: 8123, debug: false, basicAuth: { username: "", password: "", }, isUseGzip: false, trimQuery: false, usePost: false, format: "json", // "json" || "csv" || "tsv" config: { database: 'default', }, }); const a = await clickhouse.query(" select * from Record order by createdAt DESC LIMIT 1").toPromise();
内容的提问来源于stack exchange,提问作者Rami Dridi
相关产品推荐
相关产品推荐

