
# 连接DDS实例的常用方式
本节介绍了四种连接DDS实例的方式：
- mongo shell连接
- python mongo客户端
- java mongo客户端
- 基于Spring MongoTemplate操作MongoDB
#### mongo shell连接
- **前提条件**
  1. 连接数据库的弹性云服务器必须和DDS实例之间网络互通，可以使用**curl** 命令连接DDS实例服务端的IP和端口号，测试网络连通性。
     **curl** *ip:port*
     返回"It looks like you are trying to access MongoDB over HTTP on the native driver port."，说明网络互通。
     
  
  2. 在[MongoDB官网](https://www.mongodb.com/download-center#community)，下载mongo shell安装包。解压后获取其中的"mongosh"文件，并上传到弹性云服务器。
  
  3. 如果开启SSL，需要在界面上下载根证书，并上传到弹性云服务器。
   

- **连接命令**
  - SSL开启 **方式一 ：./mongosh** *ip:port* **--authenticationDatabase admin -u** *username* **-p** *password* **--ssl --sslCAFile $** *path to certificate authority file* **--sslAllowInvalidHostnames**
    **方式二** ：./mongosh "mongodb://*\<username* \>:\<password\>@*ip:port* /test?authSource=admin" **--ssl --sslCAFile $** *path to certificate authority file* **--sslAllowInvalidHostnames**
    
  
  - SSL关闭 **方式一：./mongosh** *ip:port* **--authenticationDatabase admin -u** *username* **-p** *password*
    **方式二：** ./mongosh "mongodb://*\<username* \>:\<password\>@*ip:port*/test?authSource=admin"
    表1参数说明 
    | 参数                                   | 说明                                                                              |
    |:---|:---|
    | *ip*                                 | 如果通过弹性云服务器连接，***"ip"***是主机IP，即"基本信息"页面该实例的"内网地址"。                               |
    | *ip*                                 | 如果通过连接了公网的设备访问，***"ip"***为该实例已绑定的"弹性公网IP"。                                      |
    | *port*                               | 端口，默认8635，当前端口，参考"基本信息"页面该实例的"数据库端口"。                                           |
    | *username*                           | 当前用户名。                                                                          |
    | *password*                           | 当前用户的密码。连接方式二中，需要分别将'@'、'%'和'!'字符进行转义，替换为对应的十六进制的URL编码（ASCII码）"%40"、"%25"和"%21" |
    | *path to certificate authority file* | SSL证书的路径。                                                                       |
       
    
   

- **注意事项**
  1. 如果开启SSL，连接命令中必须包含"--ssl"和"--sslCAFile"选项。
  
  2. 数据库认证"--authenticationDatabase"必须为"admin"，rwuser用户必须要在admin上认证。
   
更多信息，请参见《文档数据库服务用户指南》中各实例类型下"[连接实例](https://support.huaweicloud.com/usermanual-dds/dds_03_0308.html)"的内容。
#### python mongo客户端
- **前提条件**
  1. 连接数据库的弹性云服务器必须和DDS实例之间网络互通，可以使用curl命令连接DDS实例服务端的IP和端口号，测试网络连通性。 **curl** *ip:port*
     返回"It looks like you are trying to access MongoDB over HTTP on the native driver port."，说明网络互通。
     
  
  2. 在弹性云服务器上安装Python以及第三方安装包[pymongo](https://pypi.python.org/pypi/pymongo/2.7#downloads)。推荐使用pymongo2.8版本。
  
  3. 如果开启SSL，需要在界面上下载根证书，并上传到弹性云服务器。
   
- **连接代码**
  - SSL开启
    ```
    import ssl
    import os
    from pymongo import MongoClient
    # 认证用的用户名和密码直接写到代码中有很大的安全风险，建议在配置文件或者环境变量中存放(密码应密文存放、使用时解密)，确保安全
    # 本示例以用户名和密码保存在环境变量中为例，运行本示例前请先在本地环境中设置环境变量(环境变量名称请根据自身情况进行设置)EXAMPLE_USERNAME_ENV和EXAMPLE_PASSWORD_ENV
    rwuser = os.getenv('EXAMPLE_USERNAME_ENV')
    password = os.getenv('EXAMPLE_PASSWORD_ENV')
    conn_urls="mongodb://%s:%s@ip:port/{mydb}?authSource=admin"
    connection = MongoClient(conn_urls % (rwuser, password),connectTimeoutMS=5000,ssl=True, ssl_cert_reqs=ssl.CERT_REQUIRED,ssl_match_hostname=False,ssl_ca_certs=${path to certificate authority file})
    dbs = connection.database_names()
    print "connect database success! database names is %s" % dbs
    ```
    
  
  - SSL关闭
    ```
    import ssl
    import os
    from pymongo import MongoClient
    # 认证用的用户名和密码直接写到代码中有很大的安全风险，建议在配置文件或者环境变量中存放(密码应密文存放、使用时解密)，确保安全
    # 本示例以用户名和密码保存在环境变量中为例，运行本示例前请先在本地环境中设置环境变量(环境变量名称请根据自身情况进行设置)EXAMPLE_USERNAME_ENV和EXAMPLE_PASSWORD_ENV
    rwuser = os.getenv('EXAMPLE_USERNAME_ENV')
    password = os.getenv('EXAMPLE_PASSWORD_ENV')
    conn_urls="mongodb://%s:%s@ip:port/{mydb}?authSource=admin"
    connection = MongoClient(conn_urls % (rwuser, password),connectTimeoutMS=5000)
    dbs = connection.database_names()
    print "connect database success! database names is %s" % dbs
    ```
    
   
- **注意事项**
  1. {mydb}代表要连接数据库的名称。
  
  2. URL中的认证数据库必须为"admin"，即"authSource=admin"。
   
 
#### java mongo客户端
- **使用介绍**
  通过Java连接实例的方式有无需下载SSL证书连接和用户下载SSL证书连接两种，其中使用SSL证书连接通过了加密功能，具有更高的安全性。DDS新实例默认关闭SSL数据加密，开启SSL请参考[设置SSL数据加密](https://support.huaweicloud.com/usermanual-dds/dds_03_0074.html)。SSL连接实现了数据加密功能，但同时也会增加网络连接响应时间和CPU消耗，不建议开启SSL数据加密。
  
- **前提条件**
  用户需要具备以下技能：
  - 熟悉计算机基础知识。
  
  - 了解Java编程语言。
   
- **驱动获取及使用**
  - Jar驱动下载地址：<https://repo1.maven.org/maven2/org/mongodb/mongo-java-driver/3.0.4/>
  
  - 使用指南请参考：<https://mongodb.github.io/mongo-java-driver/4.2/driver/getting-started/installation/>
   
- **使用SSL证书连接**
  ![](https://support.huaweicloud.com/bestpractice-dds/public_sys-resources/note_3.0-zh-cn.png)
  - 该方式属于SSL连接模式，需要下载SSL证书，通过证书校验并连接数据库。
  
  - 您可以在"实例管理"页面，单击实例名称进入"基本信息"页面，单击"数据库信息"模块"SSL"处的![](https://support.huaweicloud.com/bestpractice-dds/zh-cn_image_0000001952023897.png)，下载根证书或捆绑包。
  
  - SSL连接指南请参考：MongoDB Java Driver官方文档：<https://www.mongodb.com/docs/drivers/java/sync/current/security/tls/>。
  
  - Java 8之前的Java运行时环境(JRE)仅在更新版本中启用TLS 1.2协议。如果您的JRE尚未启用TLS 1.2协议，请升级到更高版本以使用TLS 1.2进行连接。
   
  通过Java连接集群实例时，代码中的Java链接格式如下：
  ```
  mongodb://<username>:<password>@<instance_ip>:<instance_port>/<database_name>?authSource=admin&ssl=true
  ```
  表2参数说明 
  | 参数                                                 | 说明                                                                                                                                                                                                          |
  |:---|:---|
  | \<username\>                                       | 当前用户名。                                                                                                                                                                                                      |
  | \<password\>                                       | 当前用户的密码。                                                                                                                                                                                                    |
  | \<instance_ip\>  | 如果通过弹性云服务器连接，"instance_ip"是主机IP，即"基本信息"页面该实例的"内网地址"。                                                                                                                                                        |
  | \<instance_ip\>  | 如果通过连接了公网的设备访问，"instance_ip"为该实例已绑定的"弹性公网IP"。                                                                                                                                                               |
  | \<instance_ip\>  | 如果需要配置多个主机地址，按照\<instance_ip1\>:\<instance_port1\>,\<instance_ip2\>:\<instance_port2\>......列出所需主机地址即可。例如：mongodb://username:\*\*\*\*\*@127.\*\*\*.\*\*\*.1:8635,127.\*\*\*.\*\*\*.2:8635/?authSource=admin |
  | \<instance_port\>                                  | 端口，默认8635，当前端口，参考"基本信息"页面该实例的"数据库端口"。                                                                                                                                                                       |
  | \<database_name\>                                  | 数据库名，即需要连接的数据库名。                                                                                                                                                                                            |
  | authSource                                         | 鉴权用户数据库，取值为admin。                                                                                                                                                                                           |
  | ssl                                                | 连接模式，值为true代表是使用ssl连接模式。                                                                                                                                                                                    |
     
  使用keytool工具配置CA证书，参数请参见[表3]:
  ```
  keytool -importcert -trustcacerts -file <path to certificate authority file> -keystore <path to trust store> -storepass <password>
  ```
   表3参数说明 
  | 参数                                     | 说明                                       |
  |:---|:---|
  | \<path to certificate authority file\> | ssl证书的存放地址。                              |
  | \<path to trust store\>                | 信任库的存放地址。自定义即可，例如：./trust/certs.keystore |
  | \<password\>                           | 自定义密码。                                   |
     
  在程序中设置JVM系统属性以指向正确的信任库和密钥库：
  - System.setProperty("javax.net.ssl.trustStore","\<path to trust store\>");
  
  - System.setProperty("javax.net.ssl.trustStorePassword","\<password\>");
   
  可参考以下示例：
  ```
  public class Connector {
      public static void main(String[] args) {
          try {
              System.setProperty("javax.net.ssl.trustStore", "./trust/certs.keystore");
              System.setProperty("javax.net.ssl.trustStorePassword", "123456");
              ConnectionString connString = new ConnectionString("mongodb://<username>:<password>@<instance_ip>:<instance_port>/<database_name>?authSource=admin&ssl=true");
              MongoClientSettings settings = MongoClientSettings.builder()
                      .applyConnectionString(connString)
                      .applyToSslSettings(builder -> builder.enabled(true))
                      .applyToSslSettings(builder -> builder.invalidHostNameAllowed(true))
                      .build();
              MongoClient mongoClient = MongoClients.create(settings);
              MongoDatabase database = mongoClient.getDatabase("admin");
              //ping数据库，如果失败抛出异常
              BsonDocument command = new BsonDocument("ping", new BsonInt64(1));
              Document commandResult = database.runCommand(command);
              System.out.println("Connect to database successfully");
          } catch (Exception e) {
              e.printStackTrace();
              System.out.println("Test failed");
          }
      }
  }
  ```
  
- **无证书连接**
  ![](https://support.huaweicloud.com/bestpractice-dds/public_sys-resources/note_3.0-zh-cn.png)
  该方式属于非SSL连接模式，不对服务端进行证书校验，用户无需下载SSL证书。
  通过Java连接集群实例时，代码中的Java链接格式如下：
  ```
  mongodb://<username>:<password>@<instance_ip>:<instance_port>/<database_name>?authSource=admin
  ```
  表4参数说明 
  | 参数                                                | 说明                                                                                                                                                                                                          |
  |:---|:---|
  | \<username\>                                      | 当前用户名。                                                                                                                                                                                                      |
  | \<password\>                                      | 当前用户的密码。                                                                                                                                                                                                    |
  | \<instance_ip\>  | 如果通过弹性云服务器连接，"instance_ip"是主机IP，即"基本信息"页面该实例的"内网地址"。                                                                                                                                                        |
  | \<instance_ip\>  | 如果通过连接了公网的设备访问，"instance_ip"为该实例已绑定的"弹性公网IP"。                                                                                                                                                               |
  | \<instance_ip\>  | 如果需要配置多个主机地址，按照\<instance_ip1\>:\<instance_port1\>,\<instance_ip2\>:\<instance_port2\>......列出所需主机地址即可。例如：mongodb://username:\*\*\*\*\*@127.\*\*\*.\*\*\*.1:8635,127.\*\*\*.\*\*\*.2:8635/?authSource=admin |
  | \<instance_port\>                                 | 端口，默认8635，当前端口，参考"基本信息"页面该实例的"数据库端口"。                                                                                                                                                                       |
  | \<database_name\>                                 | 数据库名，即需要连接的数据库名。                                                                                                                                                                                            |
  | authSource                                        | 鉴权用户数据库，取值为admin。                                                                                                                                                                                           |
     
  可参考以下示例：
  ```
  public class Connector {
      public static void main(String[] args) {
          try {
              ConnectionString connString = new ConnectionString("mongodb://<username>:<password>@<instance_ip>:<instance_port>/<database_name>?authSource=admin");
              MongoClientSettings settings = MongoClientSettings.builder()
                      .applyConnectionString(connString)
                      .retryWrites(true)
                      .build();
              MongoClient mongoClient = MongoClients.create(settings);
              MongoDatabase database = mongoClient.getDatabase("admin");
              //ping数据库，如果失败抛出异常
              BsonDocument command = new BsonDocument("ping", new BsonInt64(1));
              Document commandResult = database.runCommand(command);
              System.out.println("Connect to database successfully");
          } catch (Exception e) {
              e.printStackTrace();
              System.out.println("Test failed");
          }
      }
  }
  ```
  
 
#### 基于Spring MongoTemplate操作MongoDB
- **使用介绍**
  本章节介绍如何使用Spring集成的MongoDB，使用MongoTemplate操作MongoDB。详情请参考[mongo官网](https://www.mongodb.com/compatibility/spring-boot)。
  
- **前提条件**
  ```
  <dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-mongodb</artifactId>
  <exclusions>
  <exclusion>
  <artifactId>spring-boot-starter-logging</artifactId>
  <groupId>org.springframework.boot</groupId>
  </exclusion>
  </exclusions>
  </dependency>
  ```
  
- **配置指导**
  ```
  spring:
    data:
      mongodb:           #MongoDB配置，作为参考
        // 认证用的用户名和密码直接写到代码中有很大的安全风险，建议在配置文件或者环境变量中存放(密码应密文存放、使用时解密)，确保安全；
        // 本示例以用户名和密码保存在环境变量中为例，运行本示例前请先在本地环境中设置环境变量(环境变量名称请根据自身情况进行设置)EXAMPLE_USERNAME_ENV和EXAMPLE_PASSWORD_ENV。
        String userName = System.getenv("EXAMPLE_USERNAME_ENV");
        String rwuserPassword = System.getenv("EXAMPLE_PASSWORD_ENV");
        uri: mongodb://" + userName + ":" + rwuserPassword + "@192.***.***.***:8635,192.***.***.***:8635/${mongodb.database}
        database: ${mongodb.database}
  ```
  
- **开发指导**
  ```
  /**
   * mongoDB执行
   */
  @Autowired
  private MongoTemplate template;
  /**
   * 日志配置
   */
  @Autowired
  private LoggingProperties properties;
  @Override
  public void write(BaseLog businessLog, LoggingOption option) {
      if (template != null) {
          LoggingConfig config = properties.getBusinessConfig(businessLog.getCategory());
          String collection = config.getMeta().get("collection");
          if (StringUtils.isNotEmpty(collection)) {
              Object data = mapping(businessLog, config);
              template.save(data, collection);
              if (log.isDebugEnabled()) {
                  log.debug("save audit log to mongodb successfully!, message: {}",
                          StringEscapeUtils.escapeJava(TransformUtil.toJsonByJackson(businessLog)));
              }
          } else {
              log.warn("mongo log write log failed, mongoconfig is null");
          }
      } else {
          log.warn("mongo log write log failed, mongoTemplate is null");
      }
  }
  ```
  
 
- **注意事项**
  1. SSL方式连接，需要手动生成trustStore文件。
  
  2. 认证数据库必须为"admin"，之后再切换至业务数据库。
   
 
