如何以无服务器方式运行我的GO应用程序 - 第1部分
#编程 #serverless #云 #go

使用AWS lambda go api代理学习如何运行go rest apis作为lambda函数。

Go编程语言一直对构建REST API有丰富的支持。其中包括一个excellent standard library (net/http)以及许多受欢迎的套餐,例如gorilla muxGinnegroniechofiber等。

感谢AWS Lambda Go runtime,您可以使用Go构建AWS lambda函数。想象一个Web应用程序,需要对用户进行身份验证,存储用户数据并发送电子邮件。无服务器的方法将将每个功能/API作为单独的lambda函数实现。例如,您可以具有lambda功能来处理用户注册,另一个用于处理用户登录等等。

如果您从头开始构建所有内容,这是很棒的。但是,如果您想作为AWS lambda函数运行现有的Go Rest API怎么办?
从广义上讲,您需要:

  1. 将现有代码分为多个lambda函数。
  2. 重构每个人都可以与AWS Lambda Go Runtime Apis一起工作。

使用 aws lambda go api代理,有一种更简单的方法!

此博客将通过AWS Lambda和Amazon API网关以无服务器方式演示如何以无服务器方式运行现有的API。您将详细介绍net/http软件包,gorillaecho框架的简单代码示例,以了解它们如何使用AWS Serverless Application Model

该代码可在此GitHub repository

中找到

让我们从简要介绍AWS Lambda Go API代理。

AWS Lambda Go API代理:它如何工作?

aws-lambda-go-api-proxy软件包使使用AWS Lambda和Amazon API Gateway的Frameworks(例如杜松子酒)编写的API轻松运行API。除了用于net/http(GO标准库)和其他框架(例如gorilla/muxecho等)的适配器实现外,aws-lambda-go-api-proxy还宣布了一个core软件包,该软件包包含实用程序方法和接口,将API Gateway Proxy Proxy Events转换为GO的default http.Requesthttp.Requesthttp.Requesthttp.ResponseWriter对象并允许您将任何任何框架适应AWS lambda go Runtime。

How does the AWS Lambda Go API Proxy work

这是关于它如何在高级别上工作的要点:

  1. API网关请求被Lambda功能处理程序接受。
  2. 函数处理程序将请求代理到与框架相对应的适配器实现。
  3. 最后,API网关代理响应返回给客户端。

让我们研究特定框架的行为。

大猩猩/Mux图书馆

软件包gorilla/mux实现了请求路由器和调度程序,以将传入请求与其各自的处理程序匹配。就像GO标准库中的http.ServeMux一样,mux.Router将传入的请求与注册路线列表匹配,并呼叫与与URL或其他条件相匹配的路线的处理程序。因为gorilla/mux实现了http.Handler接口,所以它与http.ServeMux兼容。

这是使用适配器实现与gorilla/mux软件包合作的lambda函数的简单示例:

var gorillaLambda *gorillamux.GorillaMuxAdapter

func init() {
    r := mux.NewRouter()

    r.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) {
        json.NewEncoder(w).Encode(Response{From: "gorilla", Message: time.Now().Format(time.UnixDate)})
    })

    gorillaLambda = gorillamux.New(r)
}

func Handler(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    r, err := gorillaLambda.ProxyWithContext(ctx, *core.NewSwitchableAPIGatewayRequestV1(&req))
    return *r.Version1(), err
}

func main() {
    lambda.Start(Handler)
}
  • init函数中:gorillamux.New函数接收到mux.Router(已定义了HTTP GET路线)并返回gorillamux.GorillaMuxAdapter
  • Handler实施中:
    • gorillamux.GorillaMuxAdapter对象的Proxy(或ProxyWithContext)接收events.APIGatewayProxyRequest,将其转换为http.Request对象,然后将其发送到mux.Router进行路由。
    • 它返回从写入响应作者(http.ResponseWriter)的数据生成的代理响应对象(events.APIGatewayProxyResponse)。

回声框架

回应另一个流行的GO Web框架,它是极简主义的,但高度可扩展的。

这是Lambda函数的简单示例,该函数使用适配器实现来与echo框架合作:

var echoLambda *echoadapter.EchoLambda

func init() {
    e := echo.New()

    e.Use(middleware.Logger())
    e.Use(middleware.Recover())

    e.GET("/ping", func(c echo.Context) error {
        return c.JSON(http.StatusOK, Response{From: "echo", Message: time.Now().Format(time.UnixDate)})
    })

    echoLambda = echoadapter.New(e)
}

func Handler(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    return echoLambda.ProxyWithContext(ctx, req)
}

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

该概念类似于上一个示例。

  • init函数设置了路由器(echo.Echo)并将其传递到echoadapter.New thar返回echoadapter.EchoLambda(适配器实现)。
  • Handler函数中:
    • echoadapter.EchoLambda对象的ProxyWithContext方法接收events.APIGatewayProxyRequest对象并将其转换为http.Request对象并将其发送到echo.Echo以进行路由。
    • 它返回从写入响应作者(http.ResponseWriter)的数据生成的代理响应对象(events.APIGatewayProxyResponse)。

NET/HTTP软件包

net/http的适配器实现也以相同的方式工作。这是代码段:

var httpLambda *httpadapter.HandlerAdapter

func init() {
    http.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) {
        json.NewEncoder(w).Encode(Response{From: "net/http", Message: time.Now().Format(time.UnixDate)})
    })

    httpLambda = httpadapter.New(http.DefaultServeMux)
}

func Handler(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {

    return httpLambda.ProxyWithContext(ctx, req)
}

func main() {
    lambda.Start(Handler)
}
  • 要与标准库一起使用,httpadapter.New函数将带有http.Handler(已定义路由)并返回httpadapter.HandlerAdapter对象。
  • httpadapter.HandlerAdapter上的ProxyWithContent方法然后可以用作lambda处理程序。

让我们看看这在实践中的工作方式。

部署到AWS Lambda

让我们使用Sam Cli。

先决条件

在继续之前,请确保已安装Go programming language v1.18 或更高)和AWS SAM

克隆项目并更改为正确的目录:

git clone https://github.com/build-on-aws/golang-apis-on-aws-lambda

cd golang-apis-on-aws-lambda

大猩猩/基于Mux的Lambda功能

首先,将template.yaml中的CodeUri更新为gorilla/(这是代码所在的本地文件夹)。

构建功能:

sam build

#expected output

Building codeuri: <path>/lambda-go-api-proxy-getting-started/gorilla runtime: go1.x metadata: {} architecture: x86_64 functions: DemoFunction
Running GoModulesBuilder:Build

Build Succeeded
....

部署功能(遵循SAM CLI提示):

export STACK_NAME=lambda-go-gorilla

sam deploy --stack-name $STACK_NAME --guided

# response to the prompts

Stack Name [lambda-go-gorilla]: <press enter>
AWS Region [us-east-1]: <enter alternate region or press enter>
#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
Confirm changes before deploy [y/N]: n
#SAM needs permission to be able to create roles to connect to the resources in your template
Allow SAM CLI IAM role creation [Y/n]: y
#Preserves the state of previously provisioned resources when an operation fails
Disable rollback [y/N]: n
DemoFunction may not have authorization defined, Is this okay? [y/N]: y
Save arguments to configuration file [Y/n]: y
SAM configuration file [samconfig.toml]: <press enter>
SAM configuration environment [default]: <press enter>

部署完成后,请导航到AWS CloudFormation控制台检查已部署的堆栈和相关资源。其中包括lambda功能,API Gateway (REST API),IAM角色等。

AWS CloudFormation stack

您应该将API网关端点视为SAM CLI输出(在您的情况下会有所不同)或CloudFormation outputs 部分。

-----------------------------------------------------------------------------------------------------
CloudFormation outputs from deployed stack
--------------------------------------------------------------------------------------------------------
Outputs                                                                                                
--------------------------------------------------------------------------------------------------------
Key                 APIGWEndpoint                                                                   
Description         API Gateway Endpoint                                                                                                
Value               https://whrd2yy3ug.execute-api.us-east-1.amazonaws.com/dev/ping                    
--------------------------------------------------------------------------------------------------------

Successfully created/updated stack - lambda-go-gorilla in us-east-1

要测试该功能,请使用以下命令调用API网关:

export API_ENDPOINT=<enter the API Gateway endpoint here>

curl $API_ENDPOINT

您应该得到类似于以下内容的JSON响应:

{
  "from": "gorilla",
  "message": "Tue Jun 27 18:10:54 UTC 2023"
}

NET/HTTP和基于回声的Lambda功能

在部署任何一个之前,请确保更新template.yaml中的CodeUri以参考代码所在的本地文件夹:

  • http-stdlib/net/http套件的情况下。
  • echo/echo框架的情况下。

构建和部署函数(就像以前一样响应提示):

sam build

# change the stack name to lambda-go-echo in case of "echo" framework
export STACK_NAME=lambda-go-nethttp

sam deploy --stack-name $STACK_NAME --guided

您可以通过调用API网关端点来测试功能:

export API_ENDPOINT=<enter your API endpoint here>

curl $API_ENDPOINT

您应该得到类似于以下内容的JSON响应:

{
  "from": "net/http",
  "message": "Tue Jun 27 18:20:42 UTC 2023"
}

echo框架的情况下,您应该得到类似于以下的JSON响应(请注意from字段中的不同名称):

{
  "from": "echo",
  "message": "Tue Jun 27 18:30:25 UTC 2023"
}

就是这样!您已成功部署了GO API作为AWS lambda函数。

清理

完成后,删除堆栈:

sam delete --stack-name lambda-go-gorilla
sam delete --stack-name lambda-go-nethttp
sam delete --stack-name lambda-go-echo

结论

这篇博客文章向您介绍了AWS lambda Go API代理,以及它的框架/软件包(对于gorilla/muxechonet/http)如何使用特定的适配器实现,允许您在AWS Lambda函数上运行现有的GO应用程序。您通过简单的代码示例学习了基本概念,使用AWS SAM CLI部署了这些功能,并通过调用API网关端点进行了验证。

AWS Lambda Go API代理还支持Gin,这是最受欢迎的Go Web框架之一!该博客的第二部分将演示如何在AWS Lambda函数的借助简单(但实用的)URL Shortener Service函数时运行现有的Gin框架应用程序。

请继续关注!