尝试使用 Java 连接到 RDS PostgreSQL 数据库时,为什么会出现 SocketTimeoutException? [英] Why do I get a SocketTimeoutException when trying to connect to a RDS PostgreSQL DB in Java?

查看:41
本文介绍了尝试使用 Java 连接到 RDS PostgreSQL 数据库时,为什么会出现 SocketTimeoutException?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Spring 应用,我想在 AWS 上托管,但我已经在配置方面苦苦挣扎了几天.

我有一个 EC2 实例并且能够使用 SSH 连接到它.我还在 AWS 中设置了一个 Postgres RDS 数据库,但我无法在我的 IDE 中使用我的代码连接到它,所以我还没有将应用程序上传到 EC2 实例.

我认为问题出在我的安全组上,因为我的 application.properties 与 AWS 文档和其他指南建议的一样.

我一直试图了解安全组的来龙去脉,但一直很困难.我认为在实际生产环境中精确使用我的 SG 非常重要,但我试图将此应用程序仅用作演示.

任何允许连接到 RDS 数据库的松散配置现在都适合我.

application.properties

spring.datasource.url=jdbc:postgresql://myEndpoint:myPort/myAppNamespring.datasource.username=myDbUsernamespring.datasource.password=myDbPasswordspring.datasource.driver-class-name=org.postgresql.Driverspring.jpa.hibernate.ddl-auto=更新spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImplspring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgresPlusDialectspring.jpa.properties.hibernate.format_sql=truespring.jpa.show-sql=truespring.session.jdbc.initialize-schema=alwaysspring.session.store-type=jdbcspring.session.jdbc.table-name=spring_sessionserver.servlet.session.timeout=30m

我尝试了多个 SG 配置,这里有 2 个示例:


RDS 配置 1:

公共可访问性:是VPC 安全组:launch-wizard-1 (sg-id-1)/Active

sg-id-1

入站规则:规则 1 -- IP 版本:IPv4,类型:SSH,协议:TCP,端口范围:MySSHPort,来源:0.0.0.0/0规则 2 -- IP 版本:IPv4,类型:自定义 TCP,协议:TCP,端口范围:MyLocalPort,来源:0.0.0.0/0出站规则:规则 1 -- IP 版本:IPv4,类型:所有流量,协议:全部,端口范围:全部,目的地:0.0.0.0/0


RDS 配置 2:

公共可访问性:是VPC 安全组:默认 (sg-id-2)/活动

sg-id-2

入站规则:规则 1 -- 类型:PostgreSQL,协议:TCP,端口范围:5432,来源:sg-id规则 2 -- 类型:所有流量,协议:全部,端口范围:全部,来源:sg-id出站规则:规则 1 -- IP 版本:IPv4,类型:所有流量,协议:全部,端口范围:全部,目的地:0.0.0.0/0


当我尝试连接 RDS 上设置的任一安全组时,连接超时并出现 SocketTimeoutException.

这是什么原因?


它终于连接上了.最终允许访问的安全组配置是:

入站规则:规则 1 -- 类型:PostgreSQL,协议:TCP,端口范围:5432,来源:0.0.0.0/0出站规则:不适用

我还向 Internet 网关添加了一个子网路由表,我认为这是必要的,尽管它最初不允许访问,因为 SG 入站规则上的源仍然不正确.

解决方案

SocketTimeoutException 意味着您的应用程序无法从端点获得响应,在这种情况下是数据库.

您的 RDS 配置一定有问题,您可以检查以下几点.


1.安全组 (SG) 入站 &出站规则

就您的 SG 配置而言,安全组是有状态的.

这意味着,如果您创建允许流量进入的入站规则,则无论任何出站规则如何,都会自动允许该流量退出.

因此,公共 PostgreSQL RDS 数据库的最佳配置是:

入站规则:规则 1 -- 类型:PostgreSQL,协议:TCP,端口范围:5432,来源:0.0.0.0/0出站规则:不适用

如果您的入站规则不允许 PostgreSQL 流量通过,您的请求将永远不会到达数据库 - 安全组应用在实例级别.


2.公共可访问性"RDS 属性

如果安全组设置正确,请仔细检查 RDS 实例的公共可访问性"是否正确.网络"中的属性安全"设置为是".

这将为 RDS 实例分配一个公共 IP 地址以供外部访问 &公共 IP 地址是公共数据库的要求.


3.子网类型

如果您的 SGS 没问题&您的数据库有公共 IP,但没有

公共子网是公共数据库的另一个要求,因为这将确保通信可以在您的 VPC 和互联网.

没有互联网网关的私有子网将不允许外部访问.


4.DNS 主机名 &DNS 解析 VPC 属性

如果您仍然无法公开访问您的数据库,请确保 DNS 主机名 &为 RDS 实例所在的 VPC 启用了 DNS 解析 VPC 属性.


5.网络 ACL

检查您是否创建任何处于默认状态的网络 ACL 或具有阻止规则的 NACL,它们与子网关联.

默认创建的 NACL 会像防火墙一样阻止所有入站和出站流量,无论安全组设置如何,除非您添加明确允许它们的规则.

您的 VPC 将带有一个默认的 NACL,它允许所有入站和出站 IPv4 流量 - 使用那个.


6.身份验证

确保您的用户名 &密码/IAM 身份验证令牌/Kerberos 凭据 100% 正确.


以上是一个非常全面的列表,所以希望其中一个建议应该允许您从外部连接到数据库 &排除您的 Java 代码不正确.

然后您可以将 RDS 实例设为私有,仅接受来自您的 EC2 实例安全组的流量,以及从您的子网中删除 Internet 网关以将其设为私有,在所有层应用安全安全支柱的原则在 AWS 的架构完善的框架中.

I have a Spring app I'm trying to get hosted on AWS, and I've been struggling for a few days with the configuration.

I have an EC2 instance and have been able to connect to it with an SSH. I also have a Postgres RDS database set up in AWS, but I haven't been able to connect to it with my code in my IDE, so I haven't yet uploaded the app to the EC2 instance.

I believe the issue is with my security groups, as my application.properties appears the way the AWS docs and other guides suggest.

I've been trying to understand the ins and outs of the security group stuff, but it's been a struggle. I assume that it's extremely important to be precise with my SGs in an actual production environment, but I'm trying to use this app only as a demo.

Any loose configuration that allows connectivity to the RDS DB will work for me right now.

application.properties

spring.datasource.url=jdbc:postgresql://myEndpoint:myPort/myAppName
spring.datasource.username=myDbUsername
spring.datasource.password=myDbPassword
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgresPlusDialect
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.show-sql=true
spring.session.jdbc.initialize-schema=always
spring.session.store-type=jdbc
spring.session.jdbc.table-name=spring_session
server.servlet.session.timeout=30m

I've tried multiple SG configs, here are 2 examples:


RDS config 1:

Public accessibility: Yes
VPC Security Groups: launch-wizard-1 (sg-id-1) / Active

sg-id-1

Inbound rules:
rule 1 -- IP version: IPv4, Type: SSH, Protocol: TCP, Port range: MySSHPort, Source: 0.0.0.0/0
rule 2 -- IP version: IPv4, Type: Custom TCP, Protocol: TCP, Port range: MyLocalPort, Source: 0.0.0.0/0

Outbound rules:
rule 1 -- IP version: IPv4, Type: All traffic, Protocol: All, Port range: All, Destination: 0.0.0.0/0


RDS config 2:

Public accessibility: Yes
VPC Security Groups: default (sg-id-2) / Active

sg-id-2

Inbound rules:
rule 1 -- Type: PostgreSQL, Protocol: TCP, Port range: 5432, Source: sg-id
rule 2 -- Type: All traffic, Protocol: All, Port range: All, Source: sg-id

Outbound rules:
rule 1 -- IP version: IPv4, Type: All traffic, Protocol: All, Port range: All, Destination: 0.0.0.0/0


When I try to connect with either security group set on the RDS, the connection is timing out with a SocketTimeoutException.

What's causing this?


EDIT: It finally connected. The security group configuration that finally allowed access was:

Inbound rules:
rule 1 -- Type: PostgreSQL, Protocol: TCP, Port range: 5432, Source: 0.0.0.0/0

Outbound rules:
N/A

I also added a subnet route table to the internet gateway, which I believe was necessary, although it initially did not allow access because the source on the SG inbound rule was still incorrect.

解决方案

A SocketTimeoutException means that your application wasn't able to get a response back from the endpoint, which in this case is the database.

Something must be wrong with your RDS configuration, here are a few things you can check.


1. Security Group (SG) inbound & outbound rules

In terms of your SG configuration, security groups are stateful.

This means that if you create an inbound rule allowing in traffic, that traffic is automatically allowed back out regardless of any outbound rules.

As such, the optimal config for a public PostgreSQL RDS DB would be:

Inbound rules:
rule 1 -- Type: PostgreSQL, Protocol: TCP, Port range: 5432, Source: 0.0.0.0/0

Outbound rules:
N/A

If your inbound rules do not allow PostgreSQL traffic to flow through, your request will never be hitting the database - security groups are applied at the instance level.


2. "Public Accessibility" RDS attribute

If the security group is set up correctly, double-check that the RDS instance's "Public Accessibility" attribute in "Network & Security" is set to "Yes".

This will assign the RDS instance a public IP address for external access & a public IP address is a requirement for a public database.


3. Subnet type

If your SGS are fine & your database has a public IP but you don't have an Internet Gateway, it's as though you've bought broadband to connect to the internet but your network cable is unplugged (lack of an internet gateway).

For the RDS instance to be accessible publicly, you also need to create an Internet Gateway in your database's subnet. Once created, you will need to direct internet-bound traffic to the internet gateway.

To do so, set up your subnet's route table to route all data going to 0.0.0.0/0 (internet-bound IPv4 traffic as a destination) to the internet gateway ID (target).

This would make your subnet public, as the subnet is now associated with a routing table that has a route to an internet gateway.

A public subnet is another requirement for a public database, as this will ensure communication can flow between your VPC & the internet.

A private subnet without an internet gateway, will not allow external access.


4. DNS hostnames & DNS resolution VPC attributes

If you still cannot access your database publically, make sure that the DNS hostnames & DNS resolution VPC attributes are enabled for the VPC the RDS instance is in.


5. Network ACLs

Check that you haven't created any network ACLs in a default state or NACLs with blocking rules, which are associated with the subnet.

Default created NACLs block all inbound and outbound traffic like a firewall regardless of security group settings unless you add rules explicitly allowing them.

Your VPC will come with a default NACL which allows all inbound and outbound IPv4 traffic - use that one.


6. Authentication

Ensure your username & password / IAM authentication token / Kerberos credentials are 100% correct.


The above is a pretty comprehensive list so hopefully, one of the suggestions should allow you to connect to the database externally & rule out your Java code from being incorrect.

You can then make the RDS instance private, only accepting traffic from your EC2 instance(s) security group as well as removing the internet gateway from your subnet to make it private, applying the security at all layers principle of the security pillar in AWS's Well-Architected Framework.

这篇关于尝试使用 Java 连接到 RDS PostgreSQL 数据库时,为什么会出现 SocketTimeoutException?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆