您可以通过数据库名称而不是 Lambda 函数中的主机名连接到 Amazon RDS 实例吗?

Can you connect to an Amazon RDS Instance by Database Name instead of hostname in Lambda Function?

我喜欢 DynamoDB 的一个原因是您可以像这样连接它。

const params = {
      TableName: process.env.TWILIO_TABLE,
      Item: {
        callId: obj.CallSid,
        to: obj.To,
        from: obj.From,
        callerName: obj.CallerName,
        callerCity: obj.CallerCity,
        callStatus: obj.CallStatus,
        direction: obj.Direction,
        createdAt: new Date().getTime()
      }
    };

请注意,您只需要 TableName,它会根据您的 AWS 凭证知道您指的是什么 DynamoDB table。

我想以几乎相同的方式连接到 RDS。

我正在使用无服务器框架来创建如下资源。

resources:
  Resources:
    uploadBucket:
       Type: AWS::S3::Bucket
       Properties:
         BucketName: ${self:custom.uploadBucket}
    RDSDatabase:
      Type: AWS::RDS::DBInstance
      Properties:
        Engine : mysql
        DBInstanceIdentifier: ${self:custom.databaseName}
        MasterUsername: Test123
        MasterUserPassword: TestPass123
        DBInstanceClass : db.m1.small
        AllocatedStorage: '5'
        PubliclyAccessible: true
      DeletionPolicy: Snapshot

这又使用云形成为我创建数据库实例。特别是我正在动态创建数据库名称及其标识符 DBInstanceIdentifier: ${self:custom.databaseName}

该名称根据我在通过无服务器部署时使用的阶段参数(dev、beta、alpha、prod 等)而变化。

这个想法是,如果需要,开发人员可以根据阶段自动为他创建一个用于测试目的的数据库。假设他们创建了一个像 'joe' 这样的自定义阶段,以便在推送到 'staging'.

之前用真实资源进行测试

这样做的好处是真正的测试,并且很容易通过 sls remove --stage joe 删除资源,例如删除与该阶段相关的所有资源。

问题是连接到 RDS 需要用户名、密码和主机。创建资源后,它们位于控制台中,但我需要在无服务器脚本期间以某种方式访问​​它们,因此我可以将它们设置为环境变量,以便轻松连接到我所有脚本的正确数据库。

所以简而言之,DynamoDB 的工作方式是完美的,因为我只引用 table 名称,我不必担心主机名、用户名、密码等,它知道哪个 table 是什么。 如果可能的话,我需要为 RDS 做同样的事情或解决方法类型的解决方案。

有什么想法吗?

答案并不准确,但我创建了一个非常好的解决方法,只要您同意数据库可公开访问即可。

将您的资源文件修改成这样...

resources:
  Resources:
    uploadBucket:
       Type: AWS::S3::Bucket
       Properties:
         BucketName: ${self:custom.uploadBucket}
    RDSDatabase:
      Type: AWS::RDS::DBInstance
      Properties:
        Engine : mysql
        MasterUsername: ${env:RDS_USERNAME}
        MasterUserPassword: ${env:RDS_PASSWORD}
        DBInstanceClass : db.t2.micro
        AllocatedStorage: '5'
        PubliclyAccessible: true
        #TODO: The Value of Stage is also available as a TAG automatically which I may use to replace this manually being put here..
        Tags:
          -
            Key: "Name"
            Value: ${self:custom.databaseName}
      DeletionPolicy: Snapshot
    DNSRecordSet:
      Type: AWS::Route53::RecordSet
      Properties:
        HostedZoneName: yourdomain.com.
        Name: database-${self:custom.stage}.yourdomain.com
        Type: CNAME
        TTL: '300'
        ResourceRecords:
        - {"Fn::GetAtt": ["RDSDatabase","Endpoint.Address"]}
      DependsOn: RDSDatabase

我这里的策略是连接一条Route53记录,该记录采用无法预测的唯一端点ID,并使其成为您会理解的域名。在我的例子中,我使用阶段名称创建它,这样我的函数以后将始终知道数据库位于 database-dev.yourdomain.com

使用它,您现在基本上可以知道所有 lambda 和/或 nodejs 函数的主机 :)。

当然欢迎任何更好的解决方案,这只是我现在想到的。