如何以无服务器方式运行 Go 应用程序

Go编程语言一直以来都对构建REST API提供了丰富的支持。这包括一个出色的标准库(net/HTTP),以及许多流行的包,如Gorilla mux、Gin、Negroni、Echo、Fiber等。使用AWS Lambda Go运行时,我们可以使用Go构建AWS Lambda函数。想象一下,一个Web应用程序需要对用户进行身份验证、存储用户数据和发送电子邮件。采用无服务器的方法,可以将每个功能/API实现为单独的Lambda函数。例如,我们可以有一个Lambda函数来处理用户注册,另一个来处理用户登录,依此类推。如果我们从头开始构建一切,这很好。但是,如果我们想将现有的Go REST API作为AWS Lambda函数运行,该怎么办呢?大体上来说,您需要进行以下操作:

  • 将现有的代码拆分为多个Lambda函数。

  • 重构每个函数以适配AWS Lambda Go运行时API。

不过使用AWS Lambda Go API Proxy,有一种更简单的方法。 接下来将演示如何使用AWS Lambda和Amazon API Gateway以无服务器方式运行基于Go框架的现有API。将通过简单的代码示例和框架来了解它们的工作原理,并使用AWS Serverless Application Model(SAM)部署它们。代码可在此GitHub存储库中找到。让我们从AWS Lambda Go API Proxy的简要介绍开始。

AWS Lambda Go API Proxy:它是如何工作的?

aws-lambda-go-api-proxy包使得使用框架(如Gin)编写的Go API能够轻松地在AWS Lambda和Amazon API Gateway上运行。除了适配器实现(针对Go标准库)和其他框架(如,,等)外,aws-lambda-go-api-proxy还声明了一个包,其中包含了将API Gateway代理事件转换为Go默认和对象的实用方法和接口,并允许您将任何框架适配到AWS Lambda Go运行时中。

下面是它的高级工作原理概述:

  • Lambda函数处理程序接收API Gateway的请求。

  • 函数处理程序将请求代理到与框架对应的适配器实现。

  • 最后,将API Gateway代理响应返回给客户端。

再让我们深入了解一下特定于框架的行为。

gorilla/mux库

gorilla/mux包实现了一个请求路由器和调度器,用于将传入的请求与其相应的处理程序进行匹配。与Go标准库中的类似,它将传入的请求与注册的路由列表进行匹配,并调用与URL或其他条件匹配的路由的处理程序。由于实现了接口与其他的兼容。下面有一个简单的Lambda函数示例,使用适配器实现与gorilla/mux包一起使用:

scss 复制代码
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)
}

在这个函数中:函数接收一个 http.Request 对象(其中定义了路由),并返回一个 http.Response 对象。在实现中:Handler 对象的 ServeHTTP 方法接收 http.Request 对象,将其转换为 http.ResponseWriter 对象,并将其发送到路由器进行路由处理。它将根据写入到响应写入器的数据生成一个代理响应对象(http.Response)。

Echo框架

Echo是另一个流行的Go Web框架,它既简约又高度可扩展。下面是一个简单的Lambda函数示例,使用适配器实现与Echo框架一起使用:

scss 复制代码
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)
}

该函数设置了一个路由器(echo.Echo),并将其传递给 echoadapter.New 函数,返回一个适配器实现(echoadapter.EchoLambda)。在函数中:Handler 对象的 ProxyWithContext 方法接收 events.APIGatewayProxyRequest 对象,并将其转换为 http.Request 对象,然后将其发送到 echo.Echo 进行路由处理。它将根据写入到响应写入器的数据生成一个代理响应对象(events.APIGatewayProxyResponse)。

net/http

对于net/http包,适配器实现的工作方式也是相同的。以下是代码片段的示例:

go 复制代码
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)
}

要与标准库一起使用,该函数接收一个 http.Handler 对象(其中定义了路由),并返回一个 httpadapter.HandlerAdapter 对象。然后,可以使用 ProxyWithContext 方法将其作为Lambda处理程序。


部署到AWS Lambda

使用SAM CLI将这些函数部署到AWS Lambda。

先决条件

需要安装了Go编程语言(v1.18或更高版本)和AWS SAM。克隆项目并切换到正确的目录。

bash 复制代码
git clone https://github.com/build-on-aws/golang-apis-on-aws-lambda
​
cd golang-apis-on-aws-lambda

基于gorilla和mux的Lambda函数

首先,将CodeUritemplate.yaml文件中更新为代码所在的本地文件夹路径。 构建函数:

yaml 复制代码
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的提示进行操作):

ini 复制代码
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控制台,检查已部署的堆栈和相关资源。这些资源包括Lambda函数、API Gateway(REST API)、IAM角色等。

可以在SAM CLI的输出中看到API Gateway的端点,或者在Outputs部分中找到它。

markdown 复制代码
-----------------------------------------------------------------------------------------------------
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 Gateway:

bash 复制代码
export API_ENDPOINT=<enter the API Gateway endpoint here>
​
curl $API_ENDPOINT

会得到类似以下的响应:

css 复制代码
{
  "from": "gorilla",
  "message": "Tue Jun 27 18:10:54 UTC 2023"
}

net/http和基于echo的Lambda函数

在部署这两个函数之前,请确保将CodeUri更新为代码所在的本地文件夹路径:- 对于net/http包,更新为http-stdlib/。- 对于echo框架,更新为echo/。构建并部署函数(按照之前的提示进行操作):

arduino 复制代码
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 Gateway端点来测试函数:

bash 复制代码
export API_ENDPOINT=<enter your API endpoint here>
​
curl $API_ENDPOINT

会得到下面的响应:

css 复制代码
{
  "from": "net/http",
  "message": "Tue Jun 27 18:20:42 UTC 2023"
}

对于框架的情况,会得到下面的响应(注意字段中的不同名称):

css 复制代码
{
  "from": "echo",
  "message": "Tue Jun 27 18:30:25 UTC 2023"
}

以上步骤已成功将Go API部署为AWS Lambda函数。完成后,请删除堆栈:

arduino 复制代码
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/mux、echo和net/http)特定的适配器实现,能够将现有的Go应用程序作为AWS Lambda函数运行,并由API Gateway提供前端服务。通过简单的代码示例学习了基本概念,使用AWS SAM CLI部署了这些函数,并通过调用API Gateway端点进行了验证。

作者:Abhishek Gupta

更多技术干货请关注公众号"云原生数据库"

squids.cn ,目前可体验全网zui低价RDS,免费的迁移工具DBMotion、SQL开发工具等

相关推荐
多多*2 小时前
OJ在线评测系统 登录页面开发 前端后端联调实现全栈开发
linux·服务器·前端·ubuntu·docker·前端框架
罗_三金2 小时前
前端框架对比和选择?
javascript·前端框架·vue·react·angular
程序员小羊!3 小时前
前端框架对比和选择
前端框架
凉风听雪3 小时前
百度营销转化追踪(网页JS布码)
百度·api·营销·网站统计·转化追踪·数据追踪
幂简集成4 小时前
如何免费调用GPT API进行自然语言处理
gpt·api
奶糖 肥晨1 天前
react是什么?
前端·react.js·前端框架
CyberMuse1 天前
ChatGPT 为何将前端框架从 Next.js 更换为 Remix以及框架的选择
前端框架
徊忆羽菲2 天前
学习使用在windows系统上安装vue前端框架以及环境配置图文教程
vue.js·学习·前端框架
WebGIS皮卡茂2 天前
【数据可视化】Arcgis api 4.x 专题图制作之分级色彩,采用自然间断法(使用simple-statistics JS数学统计库生成自然间断点)
javascript·arcgis·信息可视化·前端框架
蒙娜丽宁2 天前
Go语言错误处理详解
ios·golang·go·xcode·go1.19