一个与AWS(SNS,SQS,Lambda)的GO项目
#aws #lambda #go #sns

在这篇文章中,我们将探讨简单录制器项目,该项目旨在提供一种实用的方法来练习GO概念并与SNS,SQS和Lambda等AWS服务合作。该项目专注于以简单的方式加密和解密消息,作为学习练习而不是准备生产的解决方案。

项目概况

简单键盘项目由五个独立组成部分组成:

消费者 - 消费来自SQS的消息。
lambda(lambda_func) - 加密消息并将其发送到SQS。
生产者 - 将消息发送到SQ.
发布者 - 向SNS主题发布消息。
订户 - 订阅SNS主题(电子邮件类型)。

基本工作流程

以下工作流描述了组件如何相互作用:

发布者应用程序:

  • 读取终端的消息。
  • 将消息发布到SNS主题。

aws方面:

  • SNS主题具有SQS订阅。
  • SQS由Lambda功能消耗。
  • lambda函数加密消息并将加密消息发送到另一个SQS(加密消息)。

消费者应用程序:

  • 消耗SQS(加密消息)。
  • 将结果打印到终端。

代码

可以访问代码here

消费者

此代码定义订阅订阅Amazon简单队列服务(SQS)队列并连续接收和处理消息。

queueurl:是要订阅的SQS队列的URL。
取消:是用于信号取消订阅的通道。收到取消信号时,使用取消通道可优雅地退出订阅循环。

该函数进入一个循环,在其中使用 ceartivemessages 函数反复从队列接收消息。

它还通过调用 deetemessage 函数在单独的 goroutine 中调用 deetemessage

最后,订阅函数使用SELECT语句在取消频道上的取消信号听。如果收到取消信号,它将返回,有效地结束了订阅循环。否则,它在开始循环的下一次迭代之前等待100毫秒。

func subscribe(queueUrl string, cancel <-chan os.Signal) {
  awsSession := common.BuildSession()
  svc := sqs.New(awsSession, nil)

  for {
    messages := receiveMessages(svc, queueUrl)
    for _, msg := range messages {
      if msg == nil {
    continue
      }

      fmt.Println("Original: ", *msg.Body)
      fmt.Println("Decripted: ", decryptor.DecryptMessage(*msg.Body))
      go deleteMessage(svc, queueUrl, msg.ReceiptHandle)
    }

    select {
      case <-cancel:
        return
      case <-time.After(100 * time.Millisecond):
    }
  }
}

接收者构建 aceivemessageInput 带有各种配置。然后,它调用SQS服务客户端的 ceartivemessage 从队列接收消息。如果在接收操作期间存在错误,它将打印错误并返回零。否则,它检查是否收到任何消息并返回收到的消息列表。

func receiveMessages(svc *sqs.SQS, queueUrl string) []*sqs.Message {
  receiveMessagesInput := &sqs.ReceiveMessageInput{
    AttributeNames: []*string{           
      aws.String(sqs.MessageSystemAttributeNameSentTimestamp),
    },
    MessageAttributeNames: []*string{
      aws.String(sqs.QueueAttributeNameAll),
    },
    QueueUrl:            aws.String(queueUrl),
    MaxNumberOfMessages: aws.Int64(10),
    WaitTimeSeconds:     aws.Int64(3),
    VisibilityTimeout:   aws.Int64(20),
  }

  receiveMessageOutput, err := svc.ReceiveMessage(receiveMessagesInput)
  if err != nil {
    fmt.Println("Receive Error: ", err)
    return nil
  }

  if receiveMessageOutput == nil || len(receiveMessageOutput.Messages) == 0 {
    return nil
  }

  return receiveMessageOutput.Messages
}

deletemessage 构建 deetemessageInput 带有队列URL和收据手柄,然后将SQS服务客户端的 Deletemessage 称为从队列中删除消息。如果在删除操作期间存在错误,它将打印错误。

func deleteMessage(svc *sqs.SQS, queueUrl string, handle *string) {
  deleteInput := &sqs.DeleteMessageInput{
    QueueUrl:      aws.String(queueUrl),
    ReceiptHandle: handle,
  }
  _, err := svc.DeleteMessage(deleteInput)

  if err != nil {
    fmt.Println("Delete Error", err)
    return
  }
}

lambda(lambda_func)

主要功能是程序的入口点,并通过调用lambda启动 lambda 执行。从处理程序作为处理程序开始。

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

处理程序中,我们的触发源是一个SQS,这意味着该函数接收SQSEVENT。它读取来自SQS主体的消息,并将其解析为JSON格式。通过解析身体,我们可以访问消息的“消息”属性。

接下来, lambda 函数编码文本,并将“加密”消息发送到另一个SQS。此目标SQS(queueurl)的地址是从称为 aws_sqs_encrypted_queue 的环境变量获得的。此环境变量设置在AWS lambda配置中(请参见 STEP 6- env vars 有关更多详细信息)。

func Handler(ctx context.Context, sqsEvent events.SQSEvent) error {
  message, err := UnmarshalMessage(sqsEvent)
  if err != nil {
    return errors.New("the message is empty")
  } else {
    sess, _ := session.NewSession()
    svc := sqs.New(sess, nil)

    sendInput := &sqs.SendMessageInput{
      MessageBody: aws.String(encode(message)),
      QueueUrl:    aws.String(os.Getenv("AWS_SQS_ENCRYPTED_QUEUE")),
    }

    _, err := svc.SendMessage(sendInput)
    if err != nil {
      return err
    }

    return nil
  }
}

有关lambda的更多信息 步骤6:配置AWS lambda

制作人

此代码演示了如何使用AWS SDK直接将消息发送到SQS(简单队列服务)队列。

sendmessage 功能将队列URL作为输入,并提示用户从命令行输入消息。它使用 bufio.newreader os.stdin (标准输入)读取输入,并等待用户输入消息。

func sendMessage(queueURL string) error {
  reader := bufio.NewReader(os.Stdin)
  for {
    text, _ := reader.ReadString('\n')
    if text == "\n" {
      continue
    }
    sendSQS(queueURL, text[:len(text)-1])
  }
}

sendsqs 函数然后使用SQS客户端的 sendmessage 方法向SQS队列发送消息。该消息的延迟为10秒,其主体设置为用户输入的消息。排队设置为从函数参数获得的队列URL。

如果有错误发送消息,则使用fmt.println将其打印到控制台。否则,该功能将返回而无需任何进一步的操作。

func sendSQS(queueURL string, message string) {
  awsSession := common.BuildSession()
  svc := sqs.New(awsSession, nil)
  _, err := svc.SendMessage(&sqs.SendMessageInput{
    DelaySeconds: aws.Int64(10),
    MessageBody:  aws.String(message),
    QueueUrl:     aws.String(queueURL),
  })
  if err != nil {
    fmt.Println(err.Error())
    return
  }
}

出版商

PublishMessages 函数采用目标参数,这是SNS主题的ARN(Amazon Resource名称),并提示用户从命令行中输入消息。它使用 bufio.newreader os.stdin (标准输入)读取输入,并等待用户输入消息。它调用 sendsns 函数将文本作为消息发送到指定的SNS主题。

func publishMessages(destination string) {
  reader := bufio.NewReader(os.Stdin)
  for {
    text, _ := reader.ReadString('\n')
    if text == "\n" {
      continue
    }
    sendSNS(destination, text[:len(text)-1])
  }
}

sendsns 函数构建 PublishInput 带有消息和目的地,并致电SNS服务客户端的 Publish 将消息发布到指定的SNS主题。如果发布过程中存在错误,它将打印错误消息。

func sendSNS(destination string, message string) {
  awsSession := common.BuildSession()
  svc := sns.New(awsSession)
  pubInput := &sns.PublishInput{
    Message:  aws.String(message),
    TopicArn: aws.String(destination),
  }
  _, err := svc.Publish(pubInput)
  if err != nil {
    fmt.Println(err.Error())
    return
  }
}

总的来说,此代码提供了一个简单的交互式控制台界面,可以将消息发布到SNS主题。它不断读取用户的输入,丢弃空行,并将消息发送到指定的SNS主题。

订户

此代码提供了一种简单的方法来订阅SNS主题的电子邮件地址。它使用AWS SDK建立连接,启动订阅并在成功订阅后显示订阅。

订阅函数调用 supcribe SNS服务客户端的方法,通过 emagraDdress 通过a sisscribeinput ,协议设置为“电子邮件”和 topicarn 。这启动了订阅过程。如果在订阅期间存在错误,它将打印错误消息并返回。否则,它将打印订阅。

func subscribeTopic(emailAddress string, topicArn string) {
  awsSession := common.BuildSession()
  svc := sns.New(awsSession)
  result, err := svc.Subscribe(&sns.SubscribeInput{
    Endpoint: aws.String(emailAddress),
    Protocol: aws.String("email"),
    TopicArn: aws.String(topicArn),
  })
  if err != nil {
    fmt.Println("Got an error subscribing to the topic: ", err)
    fmt.Println()
    return
  }

  fmt.Println(*result.SubscriptionArn)
}

AWS

本节将指导您完成有关AWS和配置SNS(简单通知服务)和SQS(简单队列服务)的帐户的过程。

步骤1:创建一个AWS帐户

要开始,请访问aws.amazon.com,并在没有一个帐户的情况下创建一个新帐户。设置帐户后,您将可以访问AWS管理控制台。

步骤2:配置SNS(简单的通知服务)

SNS是一种发布/订阅消息服务,可启用应用程序,服务和设备发送和接收通知。请按照以下步骤配置SNS:

  1. 访问console.aws.amazon.com/sns的SNS控制台。
  2. 单击左菜单中的“主题”。
  3. 单击“创建主题”并提供以下详细信息:
    • 类型:标准
    • 名称:EncryptMessage(您可以选择您喜欢的任何名称)
    • 其他字段是可选的。
  4. 单击“创建主题”,然后保存ARN(Amazon资源名称):arn:aws:sns:us-east-1:000000000001:EncryptMessage

步骤3:配置SQS(简单的队列服务)

sqs是一项完全管理的消息排队服务,使您能够将微服务,分布式系统和无服务器应用程序缩放和扩展。请按照以下步骤配置SQ:

  1. 访问console.aws.amazon.com/sqs的SQS控制台。
  2. 单击左菜单中的“队列”。
  3. 单击“创建队列”,并提供以下详细信息:
    • 类型:标准
    • 名称:normalMessagequeue(您可以选择自己喜欢的任何名称)
    • 将其他字段留为默认。
  4. 单击“创建队列”,然后保存Arn:arn:aws:sqs:us-east-1:000000000001:NormalMessageQueue
  5. 保存URL:https://sqs.us-east-1.amazonaws.com/000000000001/NormalMessageQueue

重复上述过程,以创建另一个称为egenptedMessagequeue的队列。也将ARN和URL保存为此队列。

步骤4:订阅SNS主题

要从SNS主题中接收通知,您需要订阅它。按照以下步骤:

  1. 从SNS控制台中,单击“订阅”并填写所需字段,或单击“ EncryptMessage”主题,然后单击“创建订阅”。
  2. 将协议选择为Amazon SQ.
  3. 选择端点ARN作为arn:aws:sqs:us-east-1:000000000001:NormalMessageQueue。 在我们的情况下,最简单的方法是从SQS订阅:
    • 选择SQS normalMessagequeue。
    • 单击“订阅Amazon SNS主题。”
    • 选择SNS主题:EncryptMessage。
    • 保存订阅。

步骤5:测试订阅

现在,让我们测试订阅以确保其正常工作。按照以下步骤:

  1. 转到SNS控制台中的SNS主题“ EncryptMessage”。
  2. 单击“发布消息”。
  3. 在提供的字段中输入消息。
  4. 单击“发布消息。”

接下来,转到SQS控制台中的SQS normalMessagequeue:

  1. 单击“发送和接收消息”。
  2. 单击“邮件的民意调查”。
  3. 单击消息ID以读取消息。

步骤6:配置AWS Lambda

aws lambda是一款无服务器计算服务,可让您在不配置或管理服务器的情况下运行代码。请按照以下步骤配置lambda:

  1. 访问console.aws.amazon.com/lambda的Lambda控制台。
  2. 单击左菜单中的“功能”。
  3. 单击“创建功能”,然后选择“从头开始的作者”。
  4. 提供以下详细信息:
    • 函数名称:EncryptorMessage(您可以选择您喜欢的任何名称)
    • 运行时:GO 1.x
    • 将其他字段留为默认。
  5. 单击“创建功能”,然后保存ARN:arn:aws:lambda:us-east-1:000000000001:function:encryptorMessage

设置:
在运行时设置,将处理程序从“ Hello”编辑为“ MAIN”(因为我们将使用MAIM函数)。

权限:
为了避免创建触发器时的权限错误,我们需要为Lambda添加必要的权限,以在SQS上拨打接收。按照以下步骤:

  1. 单击lambda控制台中的“配置”。
  2. 单击“权限”。
  3. 单击角色名称:encryptorMessage-role-xyz。 这将打开IAM角色页面。

iam角色:

  1. 在IAM角色页面上,单击“权限”。
  2. 单击“添加权限”。
  3. 单击“附加政策”。
  4. 通过“ SQS”过滤,然后选择“ AmazonsqsfullaCcess”(注意:在生产环境中避免使用)。
  5. 单击“附加政策”。

触发:

触发器是您配置的资源,以允许在某些事件或条件发生时调用您的功能。您的功能可以具有多个触发器。每个触发器都充当客户端,独立调用您的功能,而Lambda传递给您功能的每个事件都只有一个触发器。

  1. 单击Lambda控制台中的“+添加触发器”。
  2. 选择源为“ SQS(Amazon简单队列服务)”。
  3. 输入SQS队列ARN:arn:aws:sqs:us-east-1:000000000001:NormalMessageQueue
  4. 将其他字段留为默认。
  5. 单击“添加”以添加触发器。

env vars:
要为Lambda功能提供必要的环境变量,请执行以下步骤:

  1. 转到lambda函数配置。
  2. 单击“环境变量”。
  3. 单击“编辑”,然后添加以下环境变量:
    • 键:aws_sqs_encrypted_queue(代码中使用的同名)
    • 值:https://sqs.us-east-1.amazonaws.com/000000000001/EncryptedMessageQueue(sqs的URL)
  4. 保存更改。 注意:您可以根据需要添加其他环境变量。

构建/部署:
要构建和部署lambda功能,请按照以下步骤:

  1. 在lambda文件夹(lambda_func)中,在命令提示符中运行以下命令:
$ go mod init github...
$ go mod tidy
$ GOOS=linux go build main.go
$ zip function.zip main
  1. 使用“ function.zip”文件将您的函数上传到AWS lambda。
    • 转到Lambda控制台。
    • 单击“代码”。
    • 选择“从”上传“然后选择“ .zip文件”。
    • 上传“ function.zip”文件。
    • 保存更改。

测试:
要测试lambda功能,请按照以下步骤:

  1. 转到Lambda控制台。
  2. 单击“测试”。
  3. 输入测试事件的以下详细信息:
    • 事件名称:testlambda01
    • 事件json:
{
  "Records": [
    {
      "messageId" : "MessageID_1",
      "receiptHandle" : "MessageReceiptHandle",
      "body": "{\"Type\": \"Notification\",\"MessageId\": \"af45217e-295b-5e93-9e1e-7d2bca04dc47\",\"TopicArn\": \"arn:aws:sns:us-east-1:000000000001:MyTopic\",\"Subject\": \"The subject\",\"Message\": \"Message from SNS\",\"Timestamp\": \"2023-02-02T16:13:19.477Z\",\"SignatureVersion\": \"1\",\"Signature\": \"V+/mFcQqIj1O8J0Af+fLx6CO\",\"SigningCertURL\": \"https://sns.us-east-1.amazonaws.com/SimpleNotificationService.pem\",\"UnsubscribeURL\": \"https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe\"}",
      "md5OfBody" : "fce0ea8dd236ccb3ed9b37dae260836f",
      "md5OfMessageAttributes" : "582c92c5c5b6ac403040a4f3ab3115c9",
      "eventSourceARN": "arn:aws:sqs:us-west-2:123456789012:SQSQueue",
      "eventSource": "aws:sqs",
      "awsRegion": "us-west-2",
      "attributes" : {
        "ApproximateReceiveCount" : "2",
        "SentTimestamp" : "1520621625029",
        "SenderId" : "AROAIWPX5BD2BHG722MW4:sender",
        "ApproximateFirstReceiveTimestamp" : "1520621634884"
      },
      "messageAttributes" : {}
    }
  ]
}
  • 单击“测试”。

在SQS EncryptedMessagequeue,您将可以从Lambda看到收到的消息。

您现在可以在应用程序之间的应用程序和可靠性之间发送并接收加密消息。

运行项目

步骤1:配置环境变量

要开始,请导航到项目目录中的.env.sample文件。制作此文件并将其重命名为.env。现在,是时候填写必要的环境变量了。这是您需要设置的变量:

AWS_REGION=us-east-1
AWS_ACCESS_KEY=XXXXXXXXXXXXXXXX //don't share this information
AWS_SECRET_KEY=XXXXXXXXXXXXXXXX //don't share this information
AWS_SNS_TOPIC_ARN=arn:aws:sns:us-east-1:000000000001:EncryptMessage
AWS_SQS_ENCRYPTED_QUEUE=https://sqs.us-east-1.amazonaws.com/000000000001/EncryptedMessageQueue
AWS_SQS_NORMAL_QUEUE=https://sqs.us-east-1.amazonaws.com/000000000001/NormalMessageQueue
EMAIL_ADDRESS_SUB=your@email.com

确保您用实际的AWS访问和秘密键替换AWS_ACCESS_KEYAWS_SECRET_KEYXXXXXXXXXXXXXXXX占位符。请记住,切勿与任何人分享此敏感信息。

步骤2:在端子中

在终端打开您的项目,并找到以下组件:producerconsumersubscriberpublisher。让我们一起运行所有这些项目。在您的终端中,执行以下命令:

$ go run main.go

步骤3:订阅SNS主题

现在,让我们设置订户以接收SNS主题的电子邮件通知。当您运行订户项目时,您将收到一封确认电子邮件,并带有“待处理确认”。按照电子邮件中提供的说明确认您的订阅。确认后,您将能够从SNS主题中接收名为“ EncryptMessage”的消息。

步骤4:发送加密消息

要发送加密消息,我们将使用producer项目。在您的终端中,执行以下步骤:

  • 在终端中输入您的消息:
$ H/3ll/0, /7h/1/5 /1/5 /0ur m/3/5/5/4/9/3
  • 按Enter。

步骤5:食用加密消息

consumer项目负责消费来自EncryptedMessagequeue(SQS)的消息。消费者启动并运行后,您将能够看到以下消息:

Original:  H/3ll/0, /7h/1/5 /1/5 /0ur m/3/5/5/4/9/3
Decrypted: Hello, this is our message

步骤6:向SNS主题发布消息

最后,我们将使用publisher项目将消息发布到SNS主题“ EncryptMessage”。按照以下步骤:

  • 在终端中输入您的消息:
$ Hello World!
  • 按Enter。

发布消息后,您将可以在consumer项目中看到它,并在电子邮件中接收它。

就是这样!现在,您可以充满信心地继续进行项目开发。如果您需要进一步的帮助或想深入研究主题,请务必查看以下参考文献。愉快的编码!

参考: