在VPC内执行通过RDS Proxy访问MySQL的Lambda

首先

由于将Lambda用RDS Proxy访问MySQL在VPC中执行,特此整理以下步骤。

スクリーンショット 2022-06-23 22.00.58.png

创建RDS代理

请参考我们之前撰写的有关RDS Proxy的文章。

 

在私有子网中创建Lambda函数。

设置

IAMロール

AWSLambdaENIManagementAccessを付与します.これによってVPC上でLambdaが実行できます。

タイムアウト時間

30秒にします。実行に数秒かかります。

環境変数

RDS_HOSTNAME:proxyのライターエンドポイント
RDS_DB_NAME:データベース名
RDS_USERNAME:ユーザー名
RDS_PASSWORD:パスワード

VPC

private subnetに設置
sgの設定は以下の通り

設定タイプポートソースLambdaAllAll0.0.0.0/0ProxyMySQL/Aurora3306LambdaのSGAuroraMySQL/Aurora3306ProxyのSG

MySQL模块 (MySQL

Lambda使用Nodejs。

为了使用mysql模块,在本地安装mysql模块。

使用LambdaLayer进行上传。

$ mkdir nodejs
$ cd nodejs
$ tree
.nodejs
├── package-lock.json
└── package.json

// package name以外はデフォルトにしました
$  npm init -y

$ npm install mysql

$ tree
.nodejs
├── node_modules
├── package-lock.json
└── package.json

$ cd ..

$ zip -r nodejs.zip nodejs

将整个Node.js文件夹压缩成zip文件。

让我们将已压缩的nodejs.zip上传到LambdaLayer。

请参考之前创建的文章来了解具体的上传方法。

 

直接将文件上传到 Lambda。

如果不使用LambdaLayer,则按照以下方式创建。

$ mkdir nodejs
$ cd nodejs
$ tree
.nodejs
├── package-lock.json
└── package.json

// package name以外はデフォルトにしました
$  npm init -y

$ npm install mysql

$ touch index.js

$ tree
.nodejs
├── index.js
├── node_modules
├── package-lock.json
└── package.json

$ zip -r nodejs.zip *
スクリーンショット 2022-11-04 12.56.40.png

Lambda的代码

const hostname = process.env.RDS_HOSTNAME;
const databaseName = process.env.RDS_DB_NAME;
const password = process.env.RDS_PASSWORD;
const user_name= process.env.RDS_USERNAME;

const mysql = require('mysql');

const beginTransaction = (connection) => {
  return new Promise((resolve, reject) => {
    connection.beginTransaction((err) => {
      if (err) {
        reject(err);
      } else {
        resolve();
      }
    });
  });
};
const query = (connection, statement, params) => {
  return new Promise((resolve, reject) => {
    connection.query(statement, params, (err, results, fields) => {
      if (err) {
        reject(err);
      } else {
        resolve(results, fields);
      }
    });
  });
};
const commit = (connection) => {
  return new Promise((resolve, reject) => {
    connection.commit((err) => {
      if (err) {
        reject(err);
      } else {
        resolve(err);
      }
    });
  });
};
const rollback = (connection, err) => {
  return new Promise((resolve, reject) => {
    connection.rollback(() => {
      reject(err);
    });
  });
};

exports.handler = async (event) => {
  // console.log('event:', JSON.stringify(event, null, 2));

  const connection = mysql.createConnection({
    host: hostname,
    user: user_name,
    password: password,
    database: databaseName,
  });

  const now = new Date().toLocaleString('ja-JP', { timeZone: 'Asia/Tokyo' });
  const sql = 'INSERT INTO database_table (title, created_at) VALUES (?, ?);';
  const inserts = ['test', now];

  try {
    await beginTransaction(connection);

    const results = await query(connection, sql, inserts);
    console.log(results);

    await commit(connection);
  } catch (err) {

    await rollback(connection);
    throw err;
  }
};

这次我尝试将标题和创建日期存入database_table这个表中。
“INSERT INTO databaseTable (title, created_at) VALUES (?, ?);”

在中国,只需要一个选项的话,可以将”mysqlの使用メソッド”的原文简单翻译为”MySQL使用方法”。

createConnection

mysqlと接続します

beginTransaction

トランザクションを開始します

query

クエリを実行します

commit

トランザクション中のデータ処理を確定します

rollback

トランザクション中のデータ処理を取り消され、トランザクション実行前の状態に戻りトランザクションを終了します。

创建一个模块,并在Lambda层中将其转化为共享库。

可以将beginTransaction、query、commit、rollback这四个操作作为一个模块,并且可以在Lambda层将它们封装成一个共享库。

module.exports = (connection) => {
  return new Promise((resolve, reject) => {
    connection.beginTransaction((err) => {
      if (err) {
        reject(err);
      } else {
        resolve();
      }
    });
  });
};
module.exports = (connection, statement, params) => {
  return new Promise((resolve, reject) => {
    connection.query(statement, params, (err, results, fields) => {
      if (err) {
        reject(err);
      } else {
        resolve(results, fields);
      }
    });
  });
};
module.exports = (connection) => {
  return new Promise((resolve, reject) => {
    connection.commit((err) => {
      if (err) {
        reject(err);
      } else {
        resolve(err);
      }
    });
  });
};
module.exports = (connection, err) => {
  return new Promise((resolve, reject) => {
    connection.rollback(() => {
      reject(err);
    });
  });
};

我参考了这篇文章。

 

$ tree
.
└── node_modules
    ├── beginTransaction.js
    ├── commit.js
    ├── query.js
    ├── rollback.js
    ├── package-lock.json
    └── package.json

与先前相同,将Node.js进行压缩并上传。

Lambda的代码

const hostname = process.env.RDS_HOSTNAME;
const databaseName = process.env.RDS_DB_NAME;
const password = process.env.RDS_PASSWORD;
const user_name= process.env.RDS_USERNAME;

const mysql = require('mysql');
const beginTransaction = require('beginTransaction');
const commit = require('commit');
const query = require('query');
const rollback = require('rollback');

exports.handler = async (event) => {
  // console.log('event:', JSON.stringify(event, null, 2));

  const connection = mysql.createConnection({
    host: hostname,
    user: user_name,
    password: password,
    database: databaseName,
  });

  const now = new Date().toLocaleString('ja-JP', { timeZone: 'Asia/Tokyo' });
  const sql = 'INSERT INTO databaseTable (title, created_at) VALUES (?, ?);';
  const inserts = ['test', now];

  try {
    await beginTransaction(connection);

    const results = await query(connection, sql, inserts);
    console.log(results);

    await commit(connection);
  } catch (err) {

    await rollback(connection);
    throw err;
  }
};

MySQL2

2022年7月23日更新
由于mysql2模块的代码量较少,因此建议使用这个。

 

请提供以下内容的中文近义词:参考

 

广告
将在 10 秒后关闭
bannerAds