启动一个最简单的 RESTful API 服务器

本节核心内容

  • 启动一个最简单的 RESTful API 服务器

  • 设置 HTTP Header

  • API 服务器健康检查和状态查询

  • 编译并测试 API

本小节源码下载路径:demo01

可先下载源码到本地,结合源码理解后续内容,边学边练。

如无特别说明,本教程的操作和编译目录均是 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 代码:

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):

    "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/ram HTTP 路径,分别路由到 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:

    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 中:

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 上供读者下载安装,安装方法为:

$ cd $GOPATH/src$ git clone https://github.com/lexkong/vendor
  1. 进入 apiserver 目录编译源代码

$ 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 测试常用的参数:

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

典型的测试命令为:

$ curl -v -XPOST -H "Content-Type: application/json" http://127.0.0.1:8080/user -d'{"username":"admin","password":"admin1234"}'

启动 API Server

$ ./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: :8080The router has been deployed successfully.

发送 HTTP GET 请求

$ curl -XGET http://127.0.0.1:8080/sd/healthOK

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

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

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

小结

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

启动服务错误5拒绝访问_【Go API 开发实战 5】基础1:启动一个最简单的 RESTful API 服务器...相关推荐

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

    本节核心内容 启动一个最简单的 RESTful API 服务器 设置 HTTP Header API 服务器健康检查和状态查询 编译并测试 API 本小节源码下载路径:demo01 可先下载源码到本地 ...

  2. 位于本地计算机无法启动拒绝访问,本地计算机无法启动 remote access connection manager 服务错误5:拒绝访问怎么处理?...

    本地计算机 无法启动 Print Spooler 服务./错误5:拒绝访问怎么回事? 悬赏分:0 - 提问时间2008-10-8 11:55 问题为何被关闭 我的打印机无缘无故就不能用了,Print ...

  3. 【原创】无法在 ADRE 上打开 NTDS 服务,错误 0x5 “拒绝访问。” AD站点无法复制...

    服务器报错如下: 报错信息从网上找的,自己的网络保存一份. AD同步报错信息 正在执行初始化设置: 正在尝试查找主服务器... 主服务器 = ADRE * 已识别的 AD 林. 已完成收集初始化信息. ...

  4. jit 调试失败,出现以下错误:拒绝访问。jit调试由用户帐户NT AUTHORITY\NETWORK SERVICE 启动...

    今天本来程序运行好着呢,中间修改了一段代码,出现如下错误: jit 调试失败,出现以下错误:拒绝访问. jit调试由用户帐户 " NT AUTHORITY\NETWORK SERVICE & ...

  5. 检索 COM 类工厂中 CLSID 为 {00024500-0000-0000-C000-000000000046} 的组件失败,原因是出现以下错误: 80070005 拒绝访问...

    检索 COM 类工厂中 CLSID 为 {00024500-0000-0000-C000-000000000046} 的组件失败,原因是出现以下错误: 80070005 拒绝访问 已重装office2 ...

  6. COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件失败,原因是出现以下错误: 80070005 拒绝访问。最新解决方案

    检索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件失败,原因是出现以下错误: 80070005 拒绝访问. (异常来自 HRE ...

  7. 检索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件失败,原因是出现以下错误: 80070005 拒绝访问。

    我在实现Word导出功能时使用了Office2007,在公司的电脑上运行没问题.由于需要向客户演示所以我要在本地搭一套环境,于是出现了"检索 COM 类工厂中 CLSID 为 {000209 ...

  8. COM 类工厂中 CLSID 错误: 80070005 拒绝访问的解决方案

    检索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件失败,原因是出现以下错误: 80070005 拒绝访问. (异常来自 HRE ...

  9. win7服务器未能登录怎么解决,win7开机提示group policy client服务未能登录拒绝访问怎么办...

    ‍‍ 有些win7专业版用户在电脑开机的时候提示group policy client服务未能登录拒绝访问,导致无法进入系统开不了机,遇到这种情况该怎么办呢?group policy client服务 ...

最新文章

  1. JedisPool资源池优化
  2. 分割2021算法合集
  3. 陌上花开 HYSBZ - 3262 (CDQ分治)
  4. java随机产生十个坐标_java中随机坐标
  5. python web验证码_python web框架Flask——手机短信验证码
  6. C++之指针探究(四):指针和二维数组
  7. runtime之ivar内存布局篇
  8. Netty之Pipeline总结
  9. 51单片机跑马灯程序
  10. Mac用Homebrew安装libimobiledevice
  11. 13.STC15W408AS单片机SPI
  12. 201621123068 Week02-Java基本语法与类库
  13. 虚拟地址如何访问到物理地址
  14. html中空格符号以及空格字符实体的总结
  15. 使用Clonezilla复制硬盘
  16. 微信小程序退款 报错 FAIL 证书验证失败
  17. windows 10 系统LCM通信库的编译
  18. 基于Java的留言板系统的设计与实现
  19. mac设置端口号转发到默认端口80、443
  20. Java opencv4 如何识别一张图片的你想要的物体的数量

热门文章

  1. AVG Anti-Spyware 7.5 .0.50(原EWIDO)汉化 破解 注册 序列号
  2. 2.4 嵌入矩阵-深度学习第五课《序列模型》-Stanford吴恩达教授
  3. 内核启动流程分析(一)编译体验
  4. 【童心制物】一篇很硬的标新立异级别的体验测评——聊新版造物编程盒
  5. linux 打印输出重定向的问题
  6. 034:DTL常用过滤器(3)
  7. requests(一): 发送一个json格式的post请求
  8. 【跃迁之路】【448天】刻意练习系列207(2018.04.29)
  9. Python--day8--Socket编程/异常处理
  10. 个人Web前端开发切图PS设置