AWS Elastic Beanstalk
开发人员指南
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

向 Java 应用程序环境中添加 Amazon RDS 数据库实例

您可以使用 Amazon Relational Database Service (Amazon RDS) 数据库实例存储应用程序收集和修改的数据。数据库可以附加到您的环境由 Elastic Beanstalk 托管,也可以在外部创建和托管。

如果您是初次使用 Amazon RDS,请使用 Elastic Beanstalk 控制台向测试环境添加一个数据库实例,并验证您的应用程序是否可以与其连接。

向环境添加数据库实例

  1. 打开 Elastic Beanstalk 控制台

  2. 导航到您的环境的管理页

  3. 选择 Configuration

  4. 数据库配置卡上,选择修改

  5. 选择数据库引擎,然后输入用户名和密码。

  6. 选择 Apply

添加一个数据库实例大约需要 10 分钟。环境更新完成后,您的应用程序就可以通过以下环境属性访问数据库实例的主机名和其他连接信息:

  • RDS_HOSTNAME – 数据库实例的主机名。

    Amazon RDS 控制台标签 – 终端节点(这是主机名)

  • RDS_PORT – 数据库实例接受连接的端口。默认值因数据库引擎而异。

    Amazon RDS 控制台标签 – 端口

  • RDS_DB_NAME – 数据库名称,ebdb

    Amazon RDS 控制台标签 – 数据库名称

  • RDS_USERNAME – 您为数据库配置的用户名。

    Amazon RDS 控制台标签 – 用户名

  • RDS_PASSWORD – 您为数据库配置的密码。

有关配置内部数据库实例的更多信息,请参阅向 Elastic Beanstalk 环境中添加数据库。如需了解如何配置外部数据库以便用于 Elastic Beanstalk,请参阅将 Elastic Beanstalk 用于 Amazon Relational Database Service

要连接到数据库,请为您的应用程序添加适当的驱动程序 JAR 文件,在代码中加载驱动程序类,并使用 Elastic Beanstalk 提供的环境属性创建连接对象。

下载 JDBC 驱动程序

您需要所选数据库引擎的 JDBC 驱动程序 JAR 文件。将 JAR 文件保存在源代码中,并在编译用于创建数据库连接的类时将该文件包含在类路径中。

在以下位置可以找到数据库引擎的最新驱动程序:

要使用 JDBC 驱动程序,请在用 Class.forName() 创建连接之前在代码中调用 DriverManager.getConnection() 加载该驱动程序。

JDBC 使用以下格式的连接字符串:

jdbc:driver://hostname:port/dbName?user=userName&password=password

您可以从 Elastic Beanstalk 提供给您应用程序的环境变量中检索主机名、端口、数据库名称、用户名和密码。驱动程序名称特定于您的数据库类型和驱动程序版本。以下是驱动程序名称示例:

  • mysql for MySQL

  • postgresql 适用于 PostgreSQL

  • oracle:thin 适用于 Oracle Thin

  • oracle:oci 适用于 Oracle OCI

  • oracle:oci8 适用于 Oracle OCI 8

  • oracle:kprb 适用于 Oracle KPRB

  • sqlserver 适用于 SQL Server

连接数据库 (Java SE 平台)

在 Java SE 环境中,可以使用 System.getenv() 从环境中读取连接变量。下面的示例代码介绍用于创建 PostgreSQL 数据库连接的类。

private static Connection getRemoteConnection() { if (System.getenv("RDS_HOSTNAME") != null) { try { Class.forName("org.postgresql.Driver"); String dbName = System.getenv("RDS_DB_NAME"); String userName = System.getenv("RDS_USERNAME"); String password = System.getenv("RDS_PASSWORD"); String hostname = System.getenv("RDS_HOSTNAME"); String port = System.getenv("RDS_PORT"); String jdbcUrl = "jdbc:postgresql://" + hostname + ":" + port + "/" + dbName + "?user=" + userName + "&password=" + password; logger.trace("Getting remote connection with connection string from environment variables."); Connection con = DriverManager.getConnection(jdbcUrl); logger.info("Remote connection successful."); return con; } catch (ClassNotFoundException e) { logger.warn(e.toString());} catch (SQLException e) { logger.warn(e.toString());} } return null; }

连接数据库 (Tomcat 平台)

在 Tomcat 环境中,环境属性是以 System.getProperty() 可访问的系统属性的形式提供的。

下面的示例代码介绍用于创建 PostgreSQL 数据库连接的类。

private static Connection getRemoteConnection() { if (System.getProperty("RDS_HOSTNAME") != null) { try { Class.forName("org.postgresql.Driver"); String dbName = System.getProperty("RDS_DB_NAME"); String userName = System.getProperty("RDS_USERNAME"); String password = System.getProperty("RDS_PASSWORD"); String hostname = System.getProperty("RDS_HOSTNAME"); String port = System.getProperty("RDS_PORT"); String jdbcUrl = "jdbc:postgresql://" + hostname + ":" + port + "/" + dbName + "?user=" + userName + "&password=" + password; logger.trace("Getting remote connection with connection string from environment variables."); Connection con = DriverManager.getConnection(jdbcUrl); logger.info("Remote connection successful."); return con; } catch (ClassNotFoundException e) { logger.warn(e.toString());} catch (SQLException e) { logger.warn(e.toString());} } return null; }

如果您无法获取连接或运行 SQL 语句,请尝试将以下代码放入 JSP 文件中。此代码连接数据库实例,创建一个表并向表中写入。

<%@ page import="java.sql.*" %> <% // Read RDS connection information from the environment String dbName = System.getProperty("RDS_DB_NAME"); String userName = System.getProperty("RDS_USERNAME"); String password = System.getProperty("RDS_PASSWORD"); String hostname = System.getProperty("RDS_HOSTNAME"); String port = System.getProperty("RDS_PORT"); String jdbcUrl = "jdbc:mysql://" + hostname + ":" + port + "/" + dbName + "?user=" + userName + "&password=" + password; // Load the JDBC driver try { System.out.println("Loading driver..."); Class.forName("com.mysql.jdbc.Driver"); System.out.println("Driver loaded!"); } catch (ClassNotFoundException e) { throw new RuntimeException("Cannot find the driver in the classpath!", e); } Connection conn = null; Statement setupStatement = null; Statement readStatement = null; ResultSet resultSet = null; String results = ""; int numresults = 0; String statement = null; try { // Create connection to RDS DB instance conn = DriverManager.getConnection(jdbcUrl); // Create a table and write two rows setupStatement = conn.createStatement(); String createTable = "CREATE TABLE Beanstalk (Resource char(50));"; String insertRow1 = "INSERT INTO Beanstalk (Resource) VALUES ('EC2 Instance');"; String insertRow2 = "INSERT INTO Beanstalk (Resource) VALUES ('RDS Instance');"; setupStatement.addBatch(createTable); setupStatement.addBatch(insertRow1); setupStatement.addBatch(insertRow2); setupStatement.executeBatch(); setupStatement.close(); } catch (SQLException ex) { // Handle any errors System.out.println("SQLException: " + ex.getMessage()); System.out.println("SQLState: " + ex.getSQLState()); System.out.println("VendorError: " + ex.getErrorCode()); } finally { System.out.println("Closing the connection."); if (conn != null) try { conn.close(); } catch (SQLException ignore) {} } try { conn = DriverManager.getConnection(jdbcUrl); readStatement = conn.createStatement(); resultSet = readStatement.executeQuery("SELECT Resource FROM Beanstalk;"); resultSet.first(); results = resultSet.getString("Resource"); resultSet.next(); results += ", " + resultSet.getString("Resource"); resultSet.close(); readStatement.close(); conn.close(); } catch (SQLException ex) { // Handle any errors System.out.println("SQLException: " + ex.getMessage()); System.out.println("SQLState: " + ex.getSQLState()); System.out.println("VendorError: " + ex.getErrorCode()); } finally { System.out.println("Closing the connection."); if (conn != null) try { conn.close(); } catch (SQLException ignore) {} } %>

要显示结果,请将以下代码放入 JSP 文件 HTML 部分的正文中。

<p>Established connection to RDS. Read first two rows: <%= results %></p>

数据库连接问题排查

如果您从应用程序中连接数据库时遇到问题,请查看 Web 容器日志和数据库。

查看日志

您可以查看 Eclipse 中的 Elastic Beanstalk 环境中的所有日志。如果未打开 AWS Explorer 视图,请选择工具栏中的橙色 AWS 图标旁边的箭头,然后选择 Show AWS Explorer View (显示 AWS Explorer 视图)。展开 AWS Elastic Beanstalk 和您的环境名称,然后打开服务器的上下文(右键单击)菜单。选择 Open in WTP Server Editor (在 WTP Server Editor 中打开)

选择 Server (服务器) 视图的 Log (日志) 选项卡以查看环境中的聚合日志。要打开最新日志,请选择页面右上角的 Refresh (刷新) 按钮。

向下滚动以在 /var/log/tomcat7/catalina.out 中找到 Tomcat 日志。如果您已在前面的示例中多次加载网页,可能会看到以下内容。

------------------------------------- /var/log/tomcat7/catalina.out ------------------------------------- INFO: Server startup in 9285 ms Loading driver... Driver loaded! SQLException: Table 'Beanstalk' already exists SQLState: 42S01 VendorError: 1050 Closing the connection. Closing the connection.

Web 应用程序发送到标准输出的所有信息都会显示在 Web 容器日志中。在上一示例中,每次加载页面时,应用程序都会尝试创建表。这导致在第一次页面加载后,每次页面加载时都会捕获 SQL 异常。

作为示例,上述行为是可接受的。但在实际应用程序中,应将数据库定义保留在架构对象中,从模型类中执行事务并与控制器 servlet 协调请求。

连接到 RDS 数据库实例

您可以使用 MySQL 客户端应用程序直接连接到 Elastic Beanstalk 环境中的 RDS 数据库实例。

您首先需要对 RDS 数据库实例开放安全组以允许来自计算机的流量。

  1. 打开 Elastic Beanstalk 控制台

  2. 导航到您的环境的管理页

  3. 选择 Configuration

  4. 数据库配置卡上,选择修改

  5. Endpoint (终端节点) 旁边,选择 Amazon RDS 控制台链接。

  6. RDS Dashboard (RDS 控制面板) 实例详细信息页面上的 Security and Network (安全与网络) 下,选择 Security Groups (安全组) 旁边的以 rds- 开头的安全组。

    注意

    数据库可能有多个标记为 Security Groups (安全组) 的条目。仅当您拥有不具有默认 Amazon Virtual Private Cloud (Amazon VPC) 的旧账户时才应使用第一个条目(以 awseb 开头)。

  7. Security group details (安全组详细信息) 中,选择 Inbound (入站) 选项卡,然后选择 Edit (编辑)

  8. 为 MySQL (端口 3306) 添加一个允许来自 IP 地址 (以 CIDR 格式指定) 的流量的规则。

  9. 选择 Save。更改将立即生效。

返回到环境的 Elastic Beanstalk 配置详细信息并记下终端节点。您将使用域名连接到 RDS 数据库实例。

安装 MySQL 客户端并在端口 3306 上发起与数据库的连接。在 Windows 上,从 MySQL 主页安装 MySQL Workbench 并按照提示操作。

在 Linux 上,使用适用于您的分发版的程序包管理器安装 MySQL 客户端。以下示例对 Ubuntu 和其他 Debian 衍生物有效。

// Install MySQL client $ sudo apt-get install mysql-client-5.5 ... // Connect to database $ mysql -h aas839jo2vwhwb.cnubrrfwfka8.us-west-2.rds.amazonaws.com.cn -u username -ppassword ebdb Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 117 Server version: 5.5.40-log Source distribution ...

连接之后,您可以运行 SQL 命令以查看数据库状态,了解是否已创建表和行及其他信息。

mysql> SELECT Resource from Beanstalk; +--------------+ | Resource | +--------------+ | EC2 Instance | | RDS Instance | +--------------+ 2 rows in set (0.01 sec)