

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 将 Amazon RDS DB 实例添加到 Java Elastic Beanstalk 环境
<a name="java-rds"></a>

本主题提供使用 Elastic Beanstalk 控制台创建 Amazon RDS 的说明。您可以使用 Amazon Relational Database Service (Amazon RDS) 数据库实例来存储应用程序收集和修改的数据。数据库可以附加到您的环境并由 Elastic Beanstalk 进行管理，也可以在外部创建和管理数据库。

如果您是首次使用 Amazon RDS，请使用 Elastic Beanstalk 控制台向测试环境中添加数据库实例，并验证您的应用程序是否可以连接到该实例。

**向环境添加数据库实例**

1. 打开 [Elastic Beanstalk](https://console.aws.amazon.com/elasticbeanstalk) 控制台，然后**在 “区域” 列表中，选择您**的。 AWS 区域

1. 在导航窗格中，选择 **Environments**（环境），然后从列表中选择环境的名称。

1. 在导航窗格中，选择 **Configuration (配置)**。

1. 在 **Database**（数据库）配置类别中，选择 **Edit**（编辑）。

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

1. 要保存更改，请选择页面底部的 **Apply**（应用）。

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


| 属性名称 | 描述 | 属性值 | 
| --- | --- | --- | 
|  `RDS_HOSTNAME`  |  数据库实例的主机名。  |  在 Amazon RDS 控制台的 **Connectivity & security**（连接和安全）选项卡上：**Endpoint**（端点）。  | 
|  `RDS_PORT`  |  数据库实例接受连接的端口。默认值因数据库引擎而异。  |  在 Amazon RDS 控制台的 **Connectivity & security**（连接和安全）选项卡上：**Port**（端口）。  | 
|  `RDS_DB_NAME`  |  数据库名称 **ebdb**。  |  在 Amazon RDS 控制台的 **Configuration**（配置）选项卡上：**DB Name**（数据库名称）。  | 
|  `RDS_USERNAME`  |  您为数据库配置的用户名。  |  在 Amazon RDS 控制台的 **Configuration**（配置）选项卡上：**Master username**（主用户名）。  | 
|  `RDS_PASSWORD`  |  您为数据库配置的密码。  |  在 Amazon RDS 控制台中不可供参考。  | 

有关配置内部数据库实例的更多信息，请参阅[将数据库添加到 Elastic Beanstalk 环境](using-features.managing.db.md)。有关配置外部数据库以用于 Elastic Beanstalk 的说明，请参阅[将 Elastic Beanstalk 和 Amazon RDS 结合使用](AWSHowTo.RDS.md)。

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

**Topics**
+ [下载 JDBC 驱动程序](#java-rds-drivers)
+ [连接数据库 (Java SE 平台)](#java-rds-javase)
+ [连接数据库 (Tomcat 平台)](#java-rds-tomcat)
+ [数据库连接问题排查](#create_deploy_Java.rds.troubleshooting)

## 下载 JDBC 驱动程序
<a name="java-rds-drivers"></a>

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

在以下位置可以找到数据库引擎的最新驱动程序：
+ **MySQL** – [MySQL Connector/J](https://dev.mysql.com/downloads/connector/j/)
+ **Oracle SE-1** – [Oracle JDBC Driver](http://www.oracle.com/technetwork/database/features/jdbc/index-091264.html)
+ **Postgres** – [PostgreSQL JDBC Driver](https://jdbc.postgresql.org/)
+ **SQL Server** – [Microsoft JDBC Driver](https://msdn.microsoft.com/en-us/sqlserver/aa937724.aspx)

要使用 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 平台)
<a name="java-rds-javase"></a>

在 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 平台)
<a name="java-rds-tomcat"></a>

在 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>
```

## 数据库连接问题排查
<a name="create_deploy_Java.rds.troubleshooting"></a>

**尝试使用 Amazon Q 开发者版 CLI 进行人工智能辅助故障排除**  
 Amazon Q 开发者版 CLI 可以帮助您针对环境问题快速进行故障排除。Q CLI 可通过检查环境状态、审核事件、分析日志和询问澄清问题来提供解决方案。有关更多信息和详细演练，请参阅博客中的使用 [Amazon Q Developer CLI 对 Elastic Beanstalk 环境进行故障排除](https://aws.amazon.com/blogs/devops/troubleshooting-elastic-beanstalk-environments-with-amazon-q-developer-cli/)。 AWS 

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

### 查看日志
<a name="create_deploy_Java.rds.troubleshooting.logs"></a>

您可以从 Eclipse 中查看 Elastic Beanstalk 环境中的所有日志。如果您没有打开 AWS 资源管理器视图，请选择工具栏中橙色 AWS 图标旁边的箭头，然后选择 “**显示 AWS 资源管理器视图**”。展开 **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 数据库实例
<a name="create_deploy_Java.rds.troubleshooting.connecting"></a>

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

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

1. 打开 [Elastic Beanstalk](https://console.aws.amazon.com/elasticbeanstalk) 控制台，然后**在 “区域” 列表中，选择您**的。 AWS 区域

1. 在导航窗格中，选择 **Environments**（环境），然后从列表中选择环境的名称。

1. 在导航窗格中，选择 **Configuration (配置)**。

1. 在 **Database (数据库)** 配置类别中，选择 **Edit (编辑)**。

1. 在 **Endpoint**（端点）旁边，选择 Amazon RDS 控制台链接。

1. 在 **RDS Dashboard**（RDS 控制面板）实例详细信息页面上的 **Security and Network**（安全与网络）下，选择 **Security Groups**（安全组）旁边的以 *rds-* 开头的安全组。
**注意**  
数据库可能有多个标记为 **Security Groups**（安全组）的条目。仅当您拥有不具有默认 [Amazon Virtual Private Cloud](https://docs.aws.amazon.com/vpc/latest/userguide/) (Amazon VPC) 的旧账户时，才应使用第一个条目（以 *awseb* 开头）。

1. 在 **Security group details**（安全组详细信息）中，选择 **Inbound**（入站）选项卡，然后选择 **Edit**（编辑）。

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

1. 选择 **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 -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)
```