Google App Engine Golang连接到Cloud SQL Postgres Unix拨号没有这样的文件或目录

时间:2019-03-17 01:43:55

标签: postgresql google-app-engine go google-cloud-sql

大家好,我无法将golang应用程序连接到Cloud sql postgres实例。我刚刚按照他们在Google Cloud Platform中的教程和示例代码进行了跟踪,但似乎无法正常工作。我只有两个文件app.yaml和main.go来测试连接:

app.yaml

runtime: go api_version: go1 env: standard

env_variables:   CLOUDSQL_CONNECTION_NAME: bxustl2019proj:asia-east1:sqlstlbxu   CLOUDSQL_USER: ustldbbxu   CLOUDSQL_PASSWORD: bxuuserstldb   CLOUDSQL_DB: stlbxudbs

beta_settings:
      cloud_sql_instances: bxustl2019proj:asia-east1:sqlstlbxu

handlers:

- url: /(.*\.(gif|png|jpg))$   static_files: static/\1   upload: static/.*\.(gif|png|jpg)

- url: /.*   script: _go_app

main.go

package dptest

import (
    _"bytes"
    "database/sql"
    "fmt"
    "log"
    "net/http"
    "os"

     _ "github.com/lib/pq"
)

var db *sql.DB

func init() {
    db = DB()

    http.HandleFunc("/", indexHandler)
}

// DB gets a connection to the database.
// This can panic for malformed database connection strings, invalid credentials, or non-existance database instance.
func DB() *sql.DB {
    /*
    var (
        connectionName = mustGetenv("CLOUDSQL_CONNECTION_NAME")
        user           = mustGetenv("CLOUDSQL_USER")
        dbname           = mustGetenv("CLOUDSQL_DB")
        password       = os.Getenv("CLOUDSQL_PASSWORD") // NOTE: password may be empty
        socket         = os.Getenv("CLOUDSQL_SOCKET_PREFIX")
    )

    //cloudsql is used on App Engine.
    if socket == "" {
        socket = "/cloudsql"
    }
    */
    // PostgreSQL Connection, uncomment to use.
    // connection string format: user=USER password=PASSWORD host=/cloudsql/PROJECT_ID:REGION_ID:INSTANCE_ID/[ dbname=DB_NAME]
    //dbURI := fmt.Sprintf("user=%s password=%s host=/cloudsql/%s database=%s", user, password, connectionName, dbname)
    dbURI := fmt.Sprintf("user=ustldbbxu password=bxuuserstldb host=/cloudsql/bxustl2019proj:asia-east1:sqlstlbxu/stlbxudbs")

    conn, err := sql.Open("postgres", dbURI)
    log.Printf("CONNECTION: %v", conn)
    if err != nil {
        panic(fmt.Sprintf("DB: %v", err))
    }

    rows, err := conn.Query("SELECT * FROM GAMES")
    log.Printf("ROW: %v", rows)
    if err != nil {
        log.Printf("Could not query db: %v", err)
    }
    defer rows.Close()

    return conn
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
    if r.URL.Path != "/" {
        http.NotFound(w, r)
        return
    }

    w.Header().Set("Content-Type", "text/plain")

    log.Printf("CONNECTION: %v", db)
    rows, err := db.Query("SELECT * FROM GAMES")
    log.Printf("ROW: %v", rows)
    if err != nil {
        log.Printf("Could not query db: %v", err)
        http.Error(w, "Internal Error", 500)
        return
    }
    defer rows.Close()
}

func mustGetenv(k string) string {
    v := os.Getenv(k)
    if v == "" {
        log.Panicf("%s environment variable not set.", k)
    }
    return v
}

我尝试使用go run。和goapp服务。我也尝试添加了appengine导入,但是似乎都无法正常工作,并且不断出现错误:

  

无法查询数据库:拨打unix   /cloudsql/bxustl2019proj:asia-east1:sqlstlbxu/stlbxudbs/.s.PGSQL.5432:   连接:没有这样的文件或目录

还启用了Cloud SQL Admin。我只是注释掉了env,以便于运行,无论硬编码查询路径还是从yaml导入,错误似乎都是相同的。

我希望有人能对此有所帮助。谢谢。

2 个答案:

答案 0 :(得分:0)

您似乎正在与App Engine连接(但您未指定标准或灵活环境)。

如果您使用的是标准版,则可以在/cloudsql/<INSTANCE_CONNECTION_NAME>上自动使用unix套接字。

如果使用的是Flexible,则需要在app.yaml中指定要连接的实例,这将需要在/cloudsql/<INSTANCE_CONNECTION_NAME>处创建unix套接字。

这些Unix套接字仅在运行时本身提供 。如果要在本地运行并要连接,则需要使用Cloud SQL proxy/cloudsql/<INSTANCE_CONNECTION_NAME>处创建unix套接字(或更新连接字符串以使用Public IP并以其他方式进行身份验证)。 / p>

答案 1 :(得分:0)

任何使用此设置的人。 我有一个类似的布局。

  • 使用 Docker 的 GCR。
  • Golang 1.15 版
  • ORM sqlboiler
  • golang dbapi
  • CloudSQL 使用带有公共 IP 的 postgresql,您只能使用 cloudsql 代理访问,但 GCR 之间的连接 -> CloudSQL 被拒绝 模型:无法插入用户:拨号 tcp cloudsql-ip:5432:连接:连接超时

第一步

部署实例时

gcloud run deploy foo --add-cloudsql-instances the-literal-instance-connection-name --update-env-vars INSTANCE_CONNECTION_NAME="the-literal-instance-connection-name" --image your-image-name --region $REGION --project your-project-id --service-account=the-service-account-you-run-your-things --platform managed --no-allow-unauthenticated

运行该容器的服务帐户具有 IAM 角色 Cloud SQL 客户端

sqlboiler 的 Toml 格式

  • host = "/cloudsql/the-literal-instance-connection-name/"

Golang lib/pq + golang db API 使用命名 unix sock 连接

  • host=/cloudsql/the-literal-instance-connection-name/

什么是-literal-instance-connection-name ?

转到您的 CloudSQL 实例并查看列实例连接名称并将其用作值。

来源

谷歌云文档中的python示例

query_string = dict({"unix_sock": "/cloudsql/{}/.s.PGSQL.5432".format(connection_name)})

如果你在 Golang 中使用类似的格式,它将无法工作,经过多次试验和错误,我得到了正确的版本。

例如,在两个连接中添加 .s.PGSQL.5432 最终会出现这样的错误

 unable to insert into user: dial unix /cloudsql/the-literal-instance-connection-name/.s.PGSQL.5432/.s.PGSQL.5432: connect: not a directory