nodejs通过ssh连接mysql typescript

2023-07-18  本文已影响0人  一只yami

nodejs通过ssh连接mysql ts版本

核心讲解

  1. 通过ssh2建立连接
    首先是 client.connect(),在连接成功后的onready事件中,通过forwardOut创建一个流,连接到远程服务器上。
    示例:
    假设需要连接服务器 A上有一个3306的数据库,但是本机无法直接连接,只能通过服务器B作为跳板机再连接A。
    那么这里的步骤就是,client.connect(服务器B) => client.forwardOut(本地->服务器A)
    此时可以直接跟A通讯了
    使用fs-extra是为了加载证书文件

  2. 通过mysql2连接数据库
    mysql2有promise版本的我没用,可以自己看看文档。
    直接createConnection就连接上了,然后可以通过query查询数据。

  3. 如果是长期运行的项目,记得用完之后关闭连接,或者使用mysql的连接池管理。

import fse from 'fs-extra';
import mysql2 from 'mysql2';
import { Client } from 'ssh2';

const client = new Client();

let connection: mysql2.Connection;

let isConnected = false;

// ssh证书位置
const buffer: Buffer = fse.readFileSync(
    'C:/Users/13152/Downloads/aliyun_jcly.pem'
);

export async function loadIdByGuid(
    deviceGuids: Array<string>
): Promise<Map<string, number>> {
    const conn = await connectToMysql();
    const result: mysql2.RowDataPacket[] = await new Promise((resolve) => {
    // 由于要拼一个in参数有多个?需要手动生成多个?
        const defaultParams = deviceGuids
            .map(() => {
                return '?';
            })
            .join(',');

        conn.query(
            `SELECT id,device_guid,manufacturer_organization_id from device WHERE delete_flag=0 AND device_guid in (${defaultParams})`,
            deviceGuids,
            function (err, results: mysql2.RowDataPacket[], fields) {
                resolve(results);
            }
        );
    });
    const map = new Map<string, number>();
    result.forEach((element) => {
        map.set(element['device_guid'], element['id']);
    });
    return map;
}

async function connectToMysql(): Promise<mysql2.Connection> {
    return new Promise<mysql2.Connection>((resolve, reject) => {
        if (isConnected) {
            resolve(connection);
        } else {
            client
                .connect({
                    host: '输入远程服务器地址',
                    port: 22,
                    username: '服务器登录用户名',
                    privateKey: buffer,//这里是用的密钥登录,如果是密码可以改成password
                })
                .on('ready', () => {
                    client.forwardOut(
                        '0.0.0.0',//源地址(填本机地址 可以是本地ip)
                        10018,//源端口 任意一个未使用的端口都可以
                        '数据库主机所在地址可以是ip主机名等',//目的地址 (填需要连接的服务器地址)
                        3306,//目的端口
                        (err, stream) => {
                            connection = mysql2.createConnection({
                                port: 3306,
                                user: '数据库用户名',
                                password: '数据库密码',
                                database: '数据库名',
                                stream: stream,
                                host: '数据库主机名或者ip',
                            });
                            isConnected = true;
                            resolve(connection);
                        }
                    );
                });
        }
    });
}

/**
 * 关闭连接
 */
export function close(): void {
    if (isConnected) {
        connection.end();
        client.end();
    }
}

// loadIdByGuid(['90848425114210413044', '90872519116429488399']);

上一篇下一篇

猜你喜欢

热点阅读