管理连接

要针对 Snowflake 执行语句,首先需要建立连接。Snowflake Node.js 驱动程序允许按如下方式建立连接:

重要

从 Snowflake 8.24 版开始,网络管理员可以选择要求对所有与 Snowflake 的连接进行多因素身份验证 (MFA)。如果您的管理员决定启用此功能,则您必须将您的客户端或驱动程序配置为在连接到 Snowflake 时使用 MFA。有关更多信息,请参阅以下资源:

  • 8.24 版本说明

  • MFA(多重身份验证)

  • 使用 Snowflake MFA 排查服务用户身份验证问题 (https://community.snowflake.com/s/article/Troubleshooting-service-users-authentication-issues-with-Snowflake-MFA) 知识文库文章

创建单个连接

要创建与 Snowflake 的单一连接,请执行以下操作:

  1. 调用 snowflake.createConnection 创建一个新的 Connection 对象,并传入一个指定 :ref:` 连接选项 <label-nodejs_connection_options>` 的 JavaScript 对象。

  2. 使用 Connection 对象,调用 connect 方法建立连接。

    备注

    如果将 authenticator 选项设置为 EXTERNALBROWSER (以便使用 :ref:` 基于浏览器的 SSO <label-nodejs_sso>`)或 :code:` https:// (https://) <okta_account_name> .okta.com ` (以便 :ref:` 通过 Okta 使用本机 SSO <label-nodejs_native_sso>`),请调用 connectAsync 方法,而不是 connect 方法。

    要处理连接错误,请传入具有以下签名的回调函数:

    function(err, conn)
    
    Copy

    其中:

    • err 是一个 JavaScript Error 对象。

    • conn 是当前的 Connection 对象。

    如果在连接过程中出现错误, connect 方法会将一个 Error 对象传递给回调函数。可以在回调函数中使用此对象来获取有关错误的详细信息。如果需要有关当前 Connection 对象的信息,可以使用传递给回调函数的 conn 实参。

以下示例建立连接并使用密码进行身份验证。要使用其他身份验证方法,请参阅 身份验证选项

// Load the Snowflake Node.js driver.
var snowflake = require('snowflake-sdk');
Copy
// Create a Connection object that we can use later to connect.
var connection = snowflake.createConnection({
    account: account,
    username: user,
    password: password,
    application: application
  });
Copy
// Try to connect to Snowflake, and check whether the connection was successful.
connection.connect( 
    function(err, conn) {
        if (err) {
            console.error('Unable to connect: ' + err.message);
            } 
        else {
            console.log('Successfully connected to Snowflake.');
            // Optional: store the connection ID.
            connection_ID = conn.getId();
            }
    }
);
Copy

创建连接时,可以按照 :ref:` 选项参考 <label-nodejs_connection_options>` 中的描述设置连接选项。

验证连接是否已准备好接收查询

在提交 Snowflake 查询之前,可以使用 connection.isValidAsync() 方法(在版本 1.6.23 和更高版本中)来确保连接已启动并准备好在 Snowflake 上执行请求。如果连接已准备就绪,该方法返回 true,否则返回 false

// Create a Connection object and connect to Snowflake
// ..

// Verify if connection is still valid for sending queries over it
const isConnectionValid = await connection.isValidAsync();

// Do further actions based on the value (true or false) of isConnectionValid
Copy

创建连接池

可以定义 Snowflake 连接的缓存,以便根据需要重复使用,而不必在客户端应用程序每次需要访问 Snowflake 时都创建连接。连接池通常可减少建立连接的滞后时间。但是,如果出现 DNS 问题,连接池可能会减慢将客户端故障转移到备选 DNS 的速度。

要创建连接池,请执行以下操作:

  1. 调用 snowflake.createPool(connectionOptions, poolOptions) 创建一个新的 ConnectionPool 对象,并传入两个指定 连接选项 和池选项的 JavaScript 对象。

    备注

    Snowflake Node.js 驱动程序使用开源的 node-pool 库来实施连接池。有关支持的 poolOptions 的信息,请参阅 node-pool 库文档中对 opts 实参的描述。

  2. 使用 ConnectionPool 对象,调用 use 函数为连接池中的单个连接执行语句。

    要处理连接错误,请传入具有以下签名的回调函数:

    function(err, stmt, rows)
    
    Copy

    其中:

    • err 是一个 JavaScript Error 对象。

    • stmt 是一个包含被执行的 SQL 语句信息的对象,包括语句的字面量文本。

    • rows 是一个包含语句“结果集”的数组。


    如果在执行语句时出错, connect 方法会将一个 Error 对象传递给回调函数。可以在回调函数中使用此对象来获取有关错误的详细信息。

以下示例创建一个支持最多十个活动连接的连接池。它使用密码进行身份验证。要使用其他身份验证方法,请参阅 身份验证选项

// Create the connection pool instance
const connectionPool = snowflake.createPool(
    // connection options
    {
      account: account,
      username: user,
      password: password
    },
    // pool options
    {
      max: 10, // specifies the maximum number of connections in the pool
      min: 0   // specifies the minimum number of connections in the pool
    }
);
  
Copy

以下示例使用 connectionPool.use 方法通过池中的连接执行 SQL 语句。clientConnection.execute 方法指定要执行的 SQL 语句并定义回调函数。

// Use the connection pool and execute a statement
connectionPool.use(async (clientConnection) =>
{
    const statement = await clientConnection.execute({
        sqlText: 'select 1;',
        complete: function (err, stmt, rows)
        {
            var stream = stmt.streamRows();
            stream.on('data', function (row)
            {
                console.log(row);
            });
            stream.on('end', function (row)
            {
                console.log('All rows consumed');
            });
        }
    });
});
Copy

创建连接池时,可以按照 :ref:` 选项参考 <label-nodejs_connection_options>` 中所述设置连接选项。

处理空闲连接

如果节点池 evictionRunIntervalMillis 选项的默认设置为 0,则不运行空闲连接驱逐检查。如果您的应用程序运行时间更长,这种行为可能会导致终止的连接滞留在连接池中,而当驱动程序获取这些连接并尝试通过它们向 Snowflake 发送查询时,会导致错误。

要在长时间运行的应用程序中解决这种行为,您可以考虑以下处理方法:

  • 创建带已启用的驱逐程序的 Snowflake ConnectionPool

    您可以将 evictionRunIntervalMillis 选项添加到池选项,如以下示例所示:

    const pool = snowflake.createPool(
        {
          account: account,
          username: username,
    
          //rest of the connection options
    
        },
        {
          evictionRunIntervalMillis: 60000 // default = 0, off
          idleTimeoutMillis: 60000, // default = 30000
          max: 2,
          min: 0,
        },
    );
    
    Copy

    此示例每分钟运行一次驱逐程序,并驱逐空闲时间超过一分钟的所有连接。您可以调整 :codenowrap:`numTestsPerEvictionRun`(默认值:3),更改每次驱逐运行期间检查的资源数量。

    请参阅节点池库 文档 < https://github.com/coopernurse/node-pool/blob/master/README.md>,了解详细信息和更多选项。

  • 确保现有连接在池中处于活动状态

    如果您需要确保连接处于活动状态的频率超过每小时一次,则可以在池选项中添加以下内容:

    • clientSessionKeepAlive: true

    • clientSessionKeepAliveHeartbeatFrequency: n,其中 n 介于 900 秒(15 分钟)与 3600 秒(1 小时)之间(默认值:3600)。

    以下示例每 15 分钟发送一次“保持活动”检测信号,以确保连接处于活动状态,即使没有发生其他活动(例如来自客户端的查询)也会如此。

    const pool = snowflake.createPool(
        {
          account: account,
          username: username,
    
          // rest of the connection options
    
          clientSessionKeepAlive: true,  // default = false
          clientSessionKeepAliveHeartbeatFrequency: 900 // default = 3600
        },
        {
          max: 2,
          min: 0,
        },
    );
    
    Copy

    您还可以在不使用池中连接的情况下使用 clientSessionKeepAlive 选项。

    有关会话保持活动状态的更多信息,请参阅 Node.js 选项参考

通过代理连接

您可以在创建 Connection 对象时将详细信息作为连接选项提供,通过代理连接到 Snowflake。

以下示例显示如何使用 HTTP 连接到代理:

var connection = snowflake.createConnection({
      account: "account",
      username: "user",
      password: "password",
      proxyHost: "localhost",
      proxyPort: 3128,
});
Copy

从版本 1.15.0 开始,Snowflake Node.js 驱动程序完全支持 HTTP_PROXYHTTPS_PROXYNO_PROXY 环境变量,但它们对应的连接参数除外。

默认情况下,新的 useEnvProxy 全局配置设置为 true,这将启用对环境变量的支持。

由于能够在 Connection 对象和环境变量中设置这些代理,驱动程序使用以下层次结构来确定要使用哪些值:

  • 如果 Connection 中定义了代理,则该值优先。驱动程序会忽略 HTTP_PROXYHTTPS_PROXY 环境变量。

  • 如果 Connection 没有设置代理值,则驱动程序会使用 HTTP_PROXYHTTPS_PROXY 环境变量中的值(如果已定义)。

  • 如果 useEnvProxy 连接设置为 false,则驱动程序会忽略 HTTP_PROXYHTTPS_PROXY 环境变量(如果已定义)。

如果要禁用对代理环境变量的支持,您必须在全局配置中将其禁用,如下所示:

const snowflake=require('snowflake-sdk');
snowflake.configure({ useEnvProxy: false });
Copy

备注

在 Linux 和 MacOS 上,环境变量区分大小写。在 Windows 上,它们不区分大小写。

  • 如果为相同的环境变量同时定义了小写 (https_proxy) 和大写 (HTTPS_PROXY) 变体,则驱动程序会使用小写 (https_proxy) 变量中的值。

  • 如果仅存在大写 (HTTPS_PROXY) 变体,则驱动程序会使用大写变量的值。

通过经过身份验证的代理进行连接

创建 Connection 对象时,通过提供身份验证凭据作为连接选项,可以通过经过身份验证的代理连接到 Snowflake。

备注

从 Snowflake Node.js 驱动程序版本 1.6.4 开始支持通过经过身份验证的代理服务器进行连接。

以下示例显示如何使用 HTTP 连接到经过身份验证的代理:

var connection = snowflake.createConnection({
      account: "account",
      username: "user",
      password: "password",
      proxyHost: "localhost",
      proxyPort: 3128,
      proxyUser: "myname",
      proxyPassword: "mypass"
});
Copy

要使用 HTTPS 连接到经过身份验证的代理,还必须提供 proxyProtocol 连接属性,如下所示:

var connection = snowflake.createConnection({
      account: "account",
      username: "user",
      password: "password",
      proxyHost: "localhost",
      proxyPort: 3128,
      proxyUser: "myname",
      proxyPassword: "mypass",
      proxyProtocol: "https"
});
Copy

使用 SnowCD 验证与 Snowflake 的网络连接

配置驱动程序后,可以使用 SnowCD 评估与 Snowflake 的网络连接并进行故障排除。

可以在初始配置过程中使用 SnowCD,也可以根据需要随时使用,以评估与 Snowflake 的网络连接并进行故障排除。

OCSP(在线证书状态协议)

当驱动程序发起连接时,Snowflake 会发送一个证书,确认其要连接的是 Snowflake 而不是冒充 Snowflake 的主机。驱动程序将该证书发送到 OCSP(在线证书状态协议)服务器,验证该证书是否被撤消。

如果驱动程序无法访问 OCSP 服务器来验证证书,则驱动程序可以 “故障打开”或“故障关闭”

终止连接

通过调用 connection.destroy() 方法可以终止连接。这将立即结束与连接关联的会话,而无需等待运行语句完成:

connection.destroy(function(err, conn) {
  if (err) {
    console.error('Unable to disconnect: ' + err.message);
  } else {
    console.log('Disconnected connection with id: ' + connection.getId());
  }
});
Copy
语言: 中文