前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Go API 开发实战 5】基础1:启动一个最简单的 RESTful API 服务器

【Go API 开发实战 5】基础1:启动一个最简单的 RESTful API 服务器

作者头像
腾讯技术工程官方号
修改2019-05-17 18:15:39
2.2K0
修改2019-05-17 18:15:39
举报

本节核心内容

  • 启动一个最简单的 RESTful API 服务器
  • 设置 HTTP Header
  • API 服务器健康检查和状态查询
  • 编译并测试 API

本小节源码下载路径:demo01 可先下载源码到本地,结合源码理解后续内容,边学边练。

代码语言:javascript
复制
如无特别说明,本教程的操作和编译目录均是 API 源码的根目录,并且本 API 服务器名字(也是二进制命令的名字)教程中统一叫作 apiserver。

REST Web 框架选择

要编写一个 RESTful 风格的 API 服务器,首先需要一个 RESTful Web 框架,笔者经过调研选择了 GitHub star 数最多的 Gin。采用轻量级的 Gin 框架,具有如下优点:高性能、扩展性强、稳定性强、相对而言比较简洁(查看 性能对比)。关于 Gin 的更多介绍可以参考 Golang 微框架 Gin 简介。

加载路由,并启动 HTTP 服务

main.go 中的main()函数是 Go 程序的入口函数,在main()函数中主要做一些配置文件解析、程序初始化和路由加载之类的事情,最终调用http.ListenAndServe()在指定端口启动一个 HTTP 服务器。本小节是一个简单的 HTTP 服务器,仅初始化一个 Gin 实例,加载路由并启动 HTTP 服务器。

编写入口函数

编写main()函数,main.go 代码:

代码语言:javascript
复制
package mainimport (    "log"
    "net/http"

    "apiserver/router"

    "github.com/gin-gonic/gin")func main() {    // Create the Gin engine.
    g := gin.New()    // gin middlewares
    middlewares := []gin.HandlerFunc{}    // Routes.
    router.Load(        // Cores.
        g,        // Middlewares.
        middlewares...,
    )

    log.Printf("Start to listening the incoming requests on http address: %s", ":8080")
    log.Printf(http.ListenAndServe(":8080", g).Error())
}

加载路由

main()函数通过调用router.Load函数来加载路由(函数路径为 router/router.go,具体函数实现参照 demo01/router/router.go):

代码语言:javascript
复制
    "apiserver/handler/sd"

    ....    // The health check handlers
    svcd := g.Group("/sd")
    {   
        svcd.GET("/health", sd.HealthCheck)
        svcd.GET("/disk", sd.DiskCheck)
        svcd.GET("/cpu", sd.CPUCheck)
        svcd.GET("/ram", sd.RAMCheck)
    }

该代码块定义了一个叫 sd 的分组,在该分组下注册了/health/disk/cpu/ramHTTP 路径,分别路由到sd.HealthChecksd.DiskChecksd.CPUChecksd.RAMCheck

函数。sd 分组主要用来检查 API Server 的状态:健康状况、服务器硬盘、CPU 和内存使用量。具体函数实现参照 demo01/handler/sd/check.go。

设置 HTTP Header

router.Load函数通过g.Use()来为每一个请求设置 Header,在 router/router.go 文件中设置 Header:

代码语言:javascript
复制
    g.Use(gin.Recovery())
    g.Use(middleware.NoCache)
    g.Use(middleware.Options)
    g.Use(middleware.Secure)
  • gin.Recovery():在处理某些请求时可能因为程序 bug 或者其他异常情况导致程序 panic,这时候为了不影响下一次请求的调用,需要通过gin.Recovery()来恢复 API 服务器
  • middleware.NoCache:强制浏览器不使用缓存
  • middleware.Options:浏览器跨域 OPTIONS 请求设置
  • middleware.Secure:一些安全设置

middleware包的实现见 demo01/router/middleware。

API 服务器健康状态自检

有时候 API 进程起来不代表 API 服务器正常,笔者曾经就遇到过这种问题:API 进程存在,但是服务器却不能对外提供服务。因此在启动 API 服务器时,如果能够最后做一个自检会更好些。笔者在 apiserver 中也添加了自检程序,在启动 HTTP 端口前 go 一个pingServer协程,启动 HTTP 端口后,该协程不断地 ping/sd/health路径,如果失败次数超过一定次数,则终止 HTTP 服务器进程。通过自检可以最大程度地保证启动后的 API 服务器处于健康状态。自检部分代码位于 main.go 中:

代码语言:javascript
复制
func main() {
    ....    // Ping the server to make sure the router is working.
    go func() {        if err := pingServer(); err != nil {
            log.Fatal("The router has no response, or it might took too long to start up.", err)
        }   
        log.Print("The router has been deployed successfully.")
    }()
    ....
}// pingServer pings the http server to make sure the router is working.func pingServer() error {    for i := 0; i < 10; i++ {        // Ping the server by sending a GET request to `/health`.
        resp, err := http.Get("http://127.0.0.1:8080" + "/sd/health")        if err == nil && resp.StatusCode == 200 {            return nil 
        }   

        // Sleep for a second to continue the next ping.
        log.Print("Waiting for the router, retry in 1 second.")
        time.Sleep(time.Second)
    }  
    return errors.New("Cannot connect to the router.")
}

pingServer()函数中,http.Gethttp://127.0.0.1:8080/sd/health发送 HTTP GET 请求,如果函数正确执行并且返回的 HTTP StatusCode 为 200,则说明 API 服务器可用,pingServer函数输出部署成功提示;如果超过指定次数,pingServer直接终止 API Server 进程,如下图所示。

/sd/health 路径会匹配到 handler/sd/check.go 中的 HealthCheck 函数,该函数只返回一个字符串:OK。

编译源码

  1. 下载 apiserver_demos 源码包 $ git clone https://github.com/lexkong/apiserver_demos
  2. apiserver_demos/demo01 复制为 $GOPATH/src/apiserver $ cp -a apiserver_demos/demo01/ $GOPATH/src/apiserver
  3. 首次编译需要下载vendor

因为 apiserver 功能比较丰富,需要用到很多 Go package,统计了下需要用到 60 个非标准 Go 包。为了让读者更容易地上手编写代码,这里将这些依赖用 go vendor 进行管理,并放在 GitHub 上供读者下载安装,安装方法为:

代码语言:javascript
复制
$ cd $GOPATH/src
$ git clone https://github.com/lexkong/vendor

   4.   进入 apiserver 目录编译源代码

代码语言:javascript
复制
$ cd $GOPATH/src/apiserver
$ gofmt -w .   
$ go tool vet .
$ go build -v .

编译后的二进制文件存放在当前目录,名字跟目录名相同:apiserver

笔者建议每次编译前对 Go 源码进行格式化和代码静态检查,以发现潜在的 Bug 或可疑的构造。

cURL 工具测试 API

cURL 工具简介

本教程采用 cURL 工具来测试 RESTful API,标准的 Linux 发行版都安装了 cURL 工具。cURL 可以很方便地完成对 REST API 的调用场景,比如:设置 Header,指定 HTTP 请求方法,指定 HTTP 消息体,指定权限认证信息等。通过-v选项也能输出 REST 请求的所有返回信息。cURL 功能很强大,有很多参数,这里列出 REST 测试常用的参数:

代码语言:javascript
复制
-X/--request [GET|POST|PUT|DELETE|…]  指定请求的 HTTP 方法
-H/--header                           指定请求的 HTTP Header
-d/--data                             指定请求的 HTTP 消息体(Body)
-v/--verbose                          输出详细的返回信息
-u/--user                             指定账号、密码
-b/--cookie                           读取 cookie

典型的测试命令为:

代码语言:javascript
复制
$ curl -v -XPOST -H "Content-Type: application/json" http://127.0.0.1:8080/user -d'{"username":"admin","password":"admin1234"}'

启动 API Server

代码语言:javascript
复制
$ ./apiserver
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:   export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /sd/health                --> apiserver/handler/sd.HealthCheck (5 handlers)
[GIN-debug] GET    /sd/disk                  --> apiserver/handler/sd.DiskCheck (5 handlers)
[GIN-debug] GET    /sd/cpu                   --> apiserver/handler/sd.CPUCheck (5 handlers)
[GIN-debug] GET    /sd/ram                   --> apiserver/handler/sd.RAMCheck (5 handlers)
Start to listening the incoming requests on http address: :8080
The router has been deployed successfully.

发送 HTTP GET 请求

代码语言:javascript
复制
$ curl -XGET http://127.0.0.1:8080/sd/health
OK

$ curl -XGET http://127.0.0.1:8080/sd/disk
OK - Free space: 16321MB (15GB) / 51200MB (50GB) | Used: 31%

$ curl -XGET http://127.0.0.1:8080/sd/cpu
CRITICAL - Load average: 2.39, 2.13, 1.97 | Cores: 2$ curl -XGET http://127.0.0.1:8080/sd/ram
OK - Free space: 455MB (0GB) / 8192MB (8GB) | Used: 5%

可以看到 HTTP 服务器均能正确响应请求。

小结

本小节通过具体的例子教读者快速启动一个 API 服务器,这只是一个稍微复杂点的 “Hello World”。读者可以先通过该 Hello World 熟悉 Go API 开发流程,后续小节会基于这个简单的 API 服务器,一步步构建一个企业级的 API 服务器。

本系列文章转载自公众号:腾讯游戏存储与计算技术 微信号: game_infra

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯技术工程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
命令行工具
腾讯云命令行工具 TCCLI 是管理腾讯云资源的统一工具。使用腾讯云命令行工具,您可以快速调用腾讯云 API 来管理您的腾讯云资源。此外,您还可以基于腾讯云的命令行工具来做自动化和脚本处理,以更多样的方式进行组合和重用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档