Javascript 如何从云函数连接Google Cloud SQL?

Javascript 如何从云函数连接Google Cloud SQL?,javascript,firebase,google-cloud-platform,google-cloud-sql,google-cloud-functions,Javascript,Firebase,Google Cloud Platform,Google Cloud Sql,Google Cloud Functions,我试图用它来构建一个API,该API与一个Google Cloud SQL(PostgreSQL)实例进行通信 我正在使用HTTP(S)触发器 当我白名单我的桌面的IP地址,我可以连接到云SQL与功能的node.js代码从我的本地机器。但当我部署时,我无法连接到白名单,也无法计算Firebase函数服务器的主机IP地址 您如何从Firebase的云函数与Google Cloud SQL对话 谢谢 // Code Sample, of what's working on Localhost. va

我试图用它来构建一个API,该API与一个Google Cloud SQL(PostgreSQL)实例进行通信

我正在使用HTTP(S)触发器

当我白名单我的桌面的IP地址,我可以连接到云SQL与功能的node.js代码从我的本地机器。但当我部署时,我无法连接到白名单,也无法计算Firebase函数服务器的主机IP地址

您如何从Firebase的云函数与Google Cloud SQL对话

谢谢

// Code Sample, of what's working on Localhost.
var functions = require('firebase-functions');

var pg = require('pg');
var pgConfig = {
  user: functions.config().pg.user,
  database: functions.config().pg.database,
  password: functions.config().pg.password,
  host: functions.config().pg.host
}

exports.helloSql = functions.https.onRequest((request, response) => {
  console.log('connecting...');
  try {
    client.connect(function(err) {
      if (err) throw err;

      console.log('connection success');
      console.log('querying...');

      client.query('SELECT * FROM guestbook;', function(err, result){
        if (err) throw err;

        console.log('querying success.');
        console.log('Results: ', result);
        console.log('Ending...');

        client.end(function(err){
          if (err) throw err;
          console.log('End success.');
          response.send(result);
        });
      });

    });
  } catch(er) {
    console.error(er.stack)
    response.status(500).send(er);
  }
});

-我在此列表中没有看到云SQL,因此可能它还不受支持。

新答案

参见其他答案,它现在得到了官方支持

旧答案

目前还不可能。但是,这是问题追踪器上的功能请求:

当前未从云函数连接到云SQL 受支持,因为UNIX套接字不存在(导致eNONT),并且 没有定义要列入白名单的IP范围(导致ETIMEDOUT)。一个 可能是从云SQL实例中白名单0.0.0.0/0,但是 出于安全原因,不建议这样做


如果这对您来说是一项重要功能,我建议您访问issuetracker并启动该功能请求,以帮助它获得普及。

我在进一步的讨论中找到了答案

免责声明:这似乎并没有正式宣布,所以可能会在以后更改。而且我只在mysql中测试。但这种解决方案的本质是,我认为应该以和pg模块相同的方式工作(似乎是作为主机参数)

编辑(2017/12/7):谷歌似乎提供了,同样的方法仍然有效。
编辑(2018/07/04):似乎有人只是复制并粘贴了我的示例代码,然后陷入了麻烦。作为google,您应该使用连接池来避免sql连接泄漏。(它会导致ECONREFUSE)所以我稍微更改了示例代码。 编辑(2019/04/04):在下面的示例中,使用$DBNAME作为扳手实例名称是令人困惑的,我修改了示例

在google中,guy说云函数实例可以通过特殊路径“/cloudsql/$PROJECT\u ID:$REGION:$DBNAME”中的域套接字与云sql对话

我实际上可以从下面的云函数代码连接和操作云SQL

const mysql = require('mysql');
const pool = mysql.createPool({
    connectionLimit : 1,
    socketPath: '/cloudsql/' + '$PROJECT_ID:$REGION:$SPANNER_INSTANCE_NAME',
    user: '$USER',
    password: '$PASS',
    database: '$DATABASE'
});
exports.handler = function handler(req, res) {
    //using pool instead of creating connection with function call
    pool.query(`SELECT * FROM table where id = ?`, 
                                req.body.id, function (e, results) {
        //made reply here
    });
};

我希望这将对那些迫不及待地等待谷歌正式宣布的人有所帮助。

在第页找到您的数据库区域和实例名称:

通过运行以下命令将数据库密码保存到中:

$ firebase functions:config:set \
    db.user="<username>" \
    db.password="<password>" \
    db.database="<database>"
someFunction.js

另请参见(通过Babel使用现代JavaScript语法)

您还可以授权Firebase IP地址范围,因为我们不知道Firebase在外部使用哪个IP地址

我已经试过了。谷歌云SQL不使用内部IP地址。因此,您不能使用
10.128.0.0/20
为您的Google Cloud SQL允许内部IP地址

回答

因此,从控制台转到
googlecloudsql>Instance>Authorization
,您可以添加:

151.101.0.0/17
这将允许您
151.101.0.0
151.101.127.255
IP地址范围,其中Firebase服务器域当前为
151.101.1.195
151.101.65.195

我不确定这个IP地址是否会改变


另外,请确保您的云SQL数据库使用的是
us central
zone。Firebase似乎可以在美国中央图书馆获得,现在有官方文档,但截至2018年7月仍处于测试阶段

使用TCP和UNIX域套接字2020从GOOGLE云功能连接到云SQL 1.创建一个新项目

gcloud projects create gcf-to-sql
gcloud config set project gcf-to-sql
gcloud projects describe gcf-to-sql
2.对您的项目启用计费:

3.设置计算项目信息元数据:

gcloud compute project-info describe --project gcf-to-sql
#Enable the Api, and you can check that default-region,google-compute-default-zone are not set. Set the metadata.
gcloud compute project-info add-metadata --metadata google-compute-default-region=europe-west2,google-compute-default-zone=europe-west2-b
4.启用服务网络Api:

gcloud services list --available
gcloud services enable servicenetworking.googleapis.com
5.创建2个云sql实例(一个具有内部ip,一个具有公共ip)-:

6.具有外部ip的云Sql实例:

#Create the sql instance in the 
gcloud --project=con-ae-to-sql beta sql instances create database-external --region=europe-west2
#Set the password for the "root@%" MySQL user:
gcloud sql users set-password root --host=% --instance database-external --password root 
#Create a user
gcloud sql users create user_name --host=% --instance=database-external  --password=user_password
#Create a database
gcloud sql databases create user_database --instance=database-external
gcloud sql databases list --instance=database-external
i.#Create a private connection to Google so that the VM instances in the default VPC network can use private services access to reach Google services that support it.

gcloud compute addresses create google-managed-services-my-network     --global  --purpose=VPC_PEERING --prefix-length=16  --description="peering range for Google"  --network=default --project=con-ae-to-sql
gcloud services vpc-peerings connect --service=servicenetworking.googleapis.com --ranges=google-managed-services-my-network  --network=default  --project=con-ae-to-sql
#Check whether the operation was successful.
gcloud services vpc-peerings operations describe     --name=operations/pssn.dacc3510-ebc6-40bd-a07b-8c79c1f4fa9a
#Listing private connections
gcloud services vpc-peerings list --network=default --project=con-ae-to-sql
 
ii.Create the instance:

gcloud --project=con-ae-to-sql beta sql instances create database-ipinternal --network=default --no-assign-ip  --region=europe-west2
#Set the password for the "root@%" MySQL user:
gcloud sql users set-password root --host=% --instance database-ipinternal --password root
#Create a user
gcloud sql users create user_name --host=% --instance=database-ipinternal  --password=user_password
#Create a database
gcloud sql databases create user_database --instance=database-ipinternal
gcloud sql databases list --instance=database-ipinternal 


gcloud sql instances list
gcloud sql instances describe database-external
gcloud sql instances describe database-ipinternal
#Remember the instances connectionName
6.具有内部ip的b云Sql实例:

#Create the sql instance in the 
gcloud --project=con-ae-to-sql beta sql instances create database-external --region=europe-west2
#Set the password for the "root@%" MySQL user:
gcloud sql users set-password root --host=% --instance database-external --password root 
#Create a user
gcloud sql users create user_name --host=% --instance=database-external  --password=user_password
#Create a database
gcloud sql databases create user_database --instance=database-external
gcloud sql databases list --instance=database-external
i.#Create a private connection to Google so that the VM instances in the default VPC network can use private services access to reach Google services that support it.

gcloud compute addresses create google-managed-services-my-network     --global  --purpose=VPC_PEERING --prefix-length=16  --description="peering range for Google"  --network=default --project=con-ae-to-sql
gcloud services vpc-peerings connect --service=servicenetworking.googleapis.com --ranges=google-managed-services-my-network  --network=default  --project=con-ae-to-sql
#Check whether the operation was successful.
gcloud services vpc-peerings operations describe     --name=operations/pssn.dacc3510-ebc6-40bd-a07b-8c79c1f4fa9a
#Listing private connections
gcloud services vpc-peerings list --network=default --project=con-ae-to-sql
 
ii.Create the instance:

gcloud --project=con-ae-to-sql beta sql instances create database-ipinternal --network=default --no-assign-ip  --region=europe-west2
#Set the password for the "root@%" MySQL user:
gcloud sql users set-password root --host=% --instance database-ipinternal --password root
#Create a user
gcloud sql users create user_name --host=% --instance=database-ipinternal  --password=user_password
#Create a database
gcloud sql databases create user_database --instance=database-ipinternal
gcloud sql databases list --instance=database-ipinternal 


gcloud sql instances list
gcloud sql instances describe database-external
gcloud sql instances describe database-ipinternal
#Remember the instances connectionName
好的,我们有两个mysql实例,我们将使用无服务器访问和TCP从Google云函数连接到数据库iInternal,并使用unix域套接字从Google云函数连接到数据库外部

7.启用云SQL管理API

gcloud services list --available
gcloud services enable sqladmin.googleapis.com
注意:默认情况下,云函数不支持使用TCP连接到云SQL实例。除非已配置无服务器VPC访问,否则代码不应尝试使用IP地址(如127.0.0.1或172.17.0.1)访问实例

8.a确保为您的项目启用了无服务器VPC访问API:

gcloud services enable vpcaccess.googleapis.com
8.b创建一个连接器:

gcloud compute networks vpc-access connectors create serverless-connector --network default --region europe-west2 --range 10.10.0.0/28
#Verify that your connector is in the READY state before using it
gcloud compute networks vpc-access connectors describe serverless-connector --region europe-west2
9.为您的云功能创建服务帐户。确保您的服务的服务帐户具有以下IAM角色:云SQL客户端,要在内部ip上从App Engine Standard连接到云SQL,我们还需要角色Compute Network User

gcloud iam service-accounts create cloud-function-to-sql
gcloud projects add-iam-policy-binding gcf-to-sql --member serviceAccount:cloud-function-to-sql@gcf-to-sql.iam.gserviceaccount.com   --role roles/cloudsql.client
gcloud projects add-iam-policy-binding gcf-to-sql --member serviceAccount:cloud-function-to-sql@gcf-to-sql.iam.gserviceaccount.com  --role roles/compute.networkUser
现在我配置了设置

1。使用Tcp和unix domanin套接字从Google云函数连接到云Sql

cd app-engine-standard/
ls
#main.py requirements.txt

cat requirements.txt
sqlalchemy
pymysql
      
cat main.py 
import pymysql
from sqlalchemy import create_engine


 def gcf_to_sql(request):

    engine_tcp = create_engine('mysql+pymysql://user_name:user_password@10.36.0.3:3306')
    existing_databases_tcp = engine_tcp.execute("SHOW DATABASES;")
    con_tcp = "Connecting from Google Cloud Functions to Cloud SQL using TCP: databases => " + str([d[0] for d in existing_databases_tcp]).strip('[]') + "\n"
    engine_unix_socket = create_engine('mysql+pymysql://user_name:user_password@/user_database?unix_socket=/cloudsql/gcf-to-sql:europe-west2:database-external')
    existing_databases_unix_socket = engine_unix_socket.execute("SHOW DATABASES;")
    con_unix_socket = "Connecting from Google Cloud Function  to Cloud SQL using Unix Sockets: tables in sys database:  => " + str([d[0] for d in existing_databases_unix_socket]).strip('[]') + "\n"
    return con_tcp + con_unix_socket
     
2.部署云功能:

gcloud beta functions deploy gcf_to_sql --runtime python37 --region europe-west2 --vpc-connector projects/gcf-to-sql/locations/europe-west2/connectors/serverless-connector  --trigger-http
 
3.进入云功能,选择gcf to sql,测试,测试功能:

#Connecting from Google Cloud Functions to Cloud SQL using TCP: databases => 'information_schema', 'mysql', 'performance_schema', 'sys', 'user_database'
#Connecting from Google Cloud Function  to Cloud SQL using Unix Sockets: tables in sys database:  => 'information_schema', 'mysql', 'performance_schema', 'sys', 'user_database'

成功

这确实奏效了。套接字路径与实例属性中的“实例连接名称”相同。这是否适用于第一代云SQL server?我注意到实例连接名称没有适用于我的第一代服务器的区域。@rudolph1024谢谢您的报告,但很抱歉在此声明。也许这就是谷歌似乎还没有宣布的原因。@rudolph1024仅供参考,如果您仍然有兴趣从cloud Functions连接第一代云SQL,官方文档()说可以使用实例连接名称,如:“如果您需要从另一个google云平台项目连接,将
@appspot.gserviceaccount.com
添加到您的IAM并提供云SQL客户端角色。当前可以从云服务器连接到云SQL