使用Golang实现RDS Postgres的Lambda函数

使用Golang实现RDS Postgres的Lambda函数 你好,

我是Go和AWS的新手。 我正在寻求关于编写一个用于连接Postgres数据库的Lambda解析器的帮助。我还想为该数据库使用GraphQL模式。 任何方向/指导都将很有帮助。请告诉我。

此致, Roshan

3 回复

感谢克里斯蒂安, 我会研究一下,如果取得任何进展也会更新。

更多关于使用Golang实现RDS Postgres的Lambda函数的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我从未在AWS上使用过Lambda或GraphQL,但这是您想要实现的目标吗?https://aws.amazon.com/blogs/mobile/building-real-time-serverless-apis-with-postgres-cdk-typescript-and-aws-appsync/ —— 虽然不是用Go语言编写的,但只是为了了解您所谈论的内容。

以下是一个使用Go语言实现连接RDS PostgreSQL的Lambda函数示例,包含GraphQL集成:

package main

import (
    "context"
    "database/sql"
    "encoding/json"
    "fmt"
    "log"
    
    "github.com/aws/aws-lambda-go/lambda"
    "github.com/graphql-go/graphql"
    _ "github.com/lib/pq"
)

var db *sql.DB

// 数据库连接配置
const (
    host     = "your-rds-endpoint.rds.amazonaws.com"
    port     = 5432
    user     = "your-username"
    password = "your-password"
    dbname   = "your-database"
)

// 用户模型
type User struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

// GraphQL类型定义
var userType = graphql.NewObject(graphql.ObjectConfig{
    Name: "User",
    Fields: graphql.Fields{
        "id": &graphql.Field{
            Type: graphql.Int,
        },
        "name": &graphql.Field{
            Type: graphql.String,
        },
        "email": &graphql.Field{
            Type: graphql.String,
        },
    },
})

// GraphQL查询定义
var rootQuery = graphql.NewObject(graphql.ObjectConfig{
    Name: "Query",
    Fields: graphql.Fields{
        "user": &graphql.Field{
            Type: userType,
            Args: graphql.FieldConfigArgument{
                "id": &graphql.ArgumentConfig{
                    Type: graphql.Int,
                },
            },
            Resolve: func(p graphql.ResolveParams) (interface{}, error) {
                id, ok := p.Args["id"].(int)
                if !ok {
                    return nil, fmt.Errorf("id参数错误")
                }
                
                var user User
                query := `SELECT id, name, email FROM users WHERE id = $1`
                err := db.QueryRow(query, id).Scan(&user.ID, &user.Name, &user.Email)
                if err != nil {
                    return nil, err
                }
                
                return user, nil
            },
        },
        "users": &graphql.Field{
            Type: graphql.NewList(userType),
            Resolve: func(p graphql.ResolveParams) (interface{}, error) {
                rows, err := db.Query("SELECT id, name, email FROM users")
                if err != nil {
                    return nil, err
                }
                defer rows.Close()
                
                var users []User
                for rows.Next() {
                    var user User
                    err := rows.Scan(&user.ID, &user.Name, &user.Email)
                    if err != nil {
                        return nil, err
                    }
                    users = append(users, user)
                }
                
                return users, nil
            },
        },
    },
})

// GraphQL变更定义
var rootMutation = graphql.NewObject(graphql.ObjectConfig{
    Name: "Mutation",
    Fields: graphql.Fields{
        "createUser": &graphql.Field{
            Type: userType,
            Args: graphql.FieldConfigArgument{
                "name": &graphql.ArgumentConfig{
                    Type: graphql.NewNonNull(graphql.String),
                },
                "email": &graphql.ArgumentConfig{
                    Type: graphql.NewNonNull(graphql.String),
                },
            },
            Resolve: func(p graphql.ResolveParams) (interface{}, error) {
                name := p.Args["name"].(string)
                email := p.Args["email"].(string)
                
                var user User
                query := `INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id, name, email`
                err := db.QueryRow(query, name, email).Scan(&user.ID, &user.Name, &user.Email)
                if err != nil {
                    return nil, err
                }
                
                return user, nil
            },
        },
    },
})

// Lambda事件结构
type GraphQLRequest struct {
    Query     string                 `json:"query"`
    Variables map[string]interface{} `json:"variables"`
}

// Lambda处理器
func handler(ctx context.Context, request GraphQLRequest) (map[string]interface{}, error) {
    // 初始化数据库连接
    if db == nil {
        psqlInfo := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=require",
            host, port, user, password, dbname)
        
        var err error
        db, err = sql.Open("postgres", psqlInfo)
        if err != nil {
            return nil, fmt.Errorf("数据库连接失败: %v", err)
        }
        
        db.SetMaxOpenConns(5)
        db.SetMaxIdleConns(2)
    }
    
    // 创建GraphQL Schema
    schema, err := graphql.NewSchema(graphql.SchemaConfig{
        Query:    rootQuery,
        Mutation: rootMutation,
    })
    if err != nil {
        return nil, fmt.Errorf("GraphQL Schema创建失败: %v", err)
    }
    
    // 执行GraphQL查询
    params := graphql.Params{
        Schema:         schema,
        RequestString:  request.Query,
        VariableValues: request.Variables,
        Context:        ctx,
    }
    
    result := graphql.Do(params)
    if len(result.Errors) > 0 {
        return nil, fmt.Errorf("GraphQL执行错误: %v", result.Errors)
    }
    
    return map[string]interface{}{
        "data": result.Data,
    }, nil
}

func main() {
    lambda.Start(handler)
}

需要安装的依赖:

go get github.com/aws/aws-lambda-go/lambda
go get github.com/graphql-go/graphql
go get github.com/lib/pq

部署配置文件 serverless.yml

service: go-postgres-graphql

provider:
  name: aws
  runtime: go1.x
  region: us-east-1
  environment:
    DB_HOST: ${env:DB_HOST}
    DB_PORT: ${env:DB_PORT}
    DB_USER: ${env:DB_USER}
    DB_PASSWORD: ${env:DB_PASSWORD}
    DB_NAME: ${env:DB_NAME}

functions:
  graphql:
    handler: bin/main
    events:
      - http:
          path: graphql
          method: post
          cors: true

plugins:
  - serverless-offline

custom:
  serverless-offline:
    httpPort: 4000

数据库表结构:

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

这个示例展示了如何创建连接PostgreSQL的Lambda函数,并实现基本的GraphQL查询和变更操作。确保在RDS安全组中允许Lambda函数的访问。

回到顶部