GO语言04(简单的RESTful API服务器,API 服务器健康状态自检)
目录
RESTful API服务器
1. REST Web 框架选择
2. 安装Gin
3. 第一个Gin程序
4. 路由模块化
5. 编译源码
API 服务器健康状态自检
1. 服务器健康有哪些?
2. 定义路由分组用于服务器健康检查
3. 服务器健康检查实现
4. 安装依赖并测试
5. 测试
6. 启动apiserver时自检
7. 测试
RESTful API服务器
1. REST Web 框架选择
2. 安装Gin
go get -u -v github.com/gin-gonic/gin
-v :打印出被构建的代码包的名字 -u :已存在相关的代码包,强行更新代码包及其依赖包
3. 第一个Gin程序
// 声明当前文件属于哪个包,如果是主文件,则写成main
package main // 导入gin
import "github.com/gin-gonic/gin" func main() { // 生成了一个实例,这个实例即 WSGI 应用程序 g := gin.Default() // 声明了一个路由/ 及对应的处理函数 g.GET("/", func(c *gin.Context) { c.String(200, "Hello, scRouter") })// 让应用运行在本地服务器上,默认监听端口是 8090g.Run(":8090") // listen and serve on 0.0.0.0:8090
}
# netstat -tlnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 993/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1275/master
tcp6 0 0 :::8000 :::* LISTEN 3351/main
tcp6 0 0 :::22 :::* LISTEN 993/sshd
tcp6 0 0 ::1:25 :::* LISTEN 1275/master
4. 路由模块化
[root@linuxserver apiserver]# tree
.
├── go.mod
├── go.sum
├── main.go
└── router └── router.go
1 directory, 4 files
mkdir router
package router
import ( "github.com/gin-gonic/gin"
)// Load中负责加载中间件middlewares、路由routes和handlers
func Load(g *gin.Engine, mw ...gin.HandlerFunc) *gin.Engine { // 添加路由 g.GET("/", func(c *gin.Context) { c.String(200, "Hello, scRputer") })// 加载中间件 g.Use(mw...) return g
}router目录负责路由相关内容,如定义路由及路由处理函数,路由加载的中间件等
// 声明当前文件属于哪个包,如果是主文件,则写成main
package main
// 导入gin
import ( // 导入路由模块"apiserver/router" "github.com/gin-gonic/gin"
)func main() { // 生成了一个实例,这个实例即 WSGI 应用程序 g := gin.Default() //-modify here- 加载路由 router.Load( // Cores. g, )// 让应用运行在本地服务器上,默认监听端口是 8080g.Run(":8090") // listen and serve on 0.0.0.0:8090
}
测试1配置NoRoute的处理 客户端在访问时,难免会输入错误的url,所以可以添加NoRoute处理404请求,apiserver/route/route.go
package router
import ( "github.com/gin-gonic/gin" "net/http"
)
// Load中负责加载中间件middlewares、路由routes和handlers
func Load(g *gin.Engine, mw ...gin.HandlerFunc) *gin.Engine { // 404 Handler.处理404g.NoRoute(func(c *gin.Context) { c.String(http.StatusNotFound, "url not found") })// 添加路由 g.GET("/", func(c *gin.Context) { c.String(200, "Hello, scRouter") })return g
}
测试2
5. 编译源码
$ gofmt -w .
// Vet 检查 Go 源码并报告可疑的构造
$ go vet .
// 用于编译代码,在编译过程中,会同时编译与之相关联的包
$ go build -v .编译后的二进制文件存放在当前目录,名字跟目录名相同: apiserver 或 apiserver.exe 。
这个文件可以直接运行,不与源代码依赖
./apiserver
API 服务器健康状态自检
1. 服务器健康有哪些?
磁盘空间
CPU状态
MEM状态
服务状态等
2. 定义路由分组用于服务器健康检查
由于后期我们会实现很多路由对应的处理函数,如果量大的话,router文件会变得非常大
因此,我们也可以将处理函数放到handler目录中
”apiserver/handler/sd“
此目录将用于保存服务器检查相关处理函数
注意:短小的处理函数可以直接编写匿名函数放在router中,长函数建议拆分
apiserver/router/router.go
// 加载模块-处理函数模块化"apiserver/handler/sd"// 在Load函数中添加 // -modify here- 添加健康检查的handlersvcd := 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.HealthCheck
、sd.DiskCheck
、sd.CPUCheck
、sd.RAMCheck
函数。 sd 分组主要用来检查 API Server 的状态:健康状况、服务器硬盘、CPU 和内存使用量。 main()
函数通过调用 router.Load
函数来加载路由,路由映射到具体的处理函数
3. 服务器健康检查实现
apiserver/handler/sd/check.go
编写几个检查函数
package sdimport ("fmt""net/http""github.com/gin-gonic/gin""github.com/shirou/gopsutil/cpu""github.com/shirou/gopsutil/disk""github.com/shirou/gopsutil/load""github.com/shirou/gopsutil/mem"
)// 定义常量
const (B = 1KB = 1024 * BMB = 1024 * KBGB = 1024 * MB
)// HealthCheck shows `OK` as the ping-pong result.
func HealthCheck(c *gin.Context) {message := "OK"// http.StatusOK => 所有HTTP状态码都对应到一个名字 (源码)c.String(http.StatusOK, "\n"+message)
}// DiskCheck checks the disk usage.
func DiskCheck(c *gin.Context) {// 可查看disk.Usage的源代码,此处有2个返回值,*UsageStat, errou, _ := disk.Usage("/")usedMB := int(u.Used) / MBusedGB := int(u.Used) / GBtotalMB := int(u.Total) / MBtotalGB := int(u.Total) / GBusedPercent := int(u.UsedPercent)status := http.StatusOKtext := "OK"if usedPercent >= 95 {status = http.StatusInternalServerErrortext = "CRITICAL"} else if usedPercent >= 90 {status = http.StatusTooManyRequeststext = "WARNING"}message := fmt.Sprintf("%s - Free space: %dMB (%dGB) / %dMB (%dGB) | Used: %d%%", text, usedMB, usedGB, totalMB, totalGB, usedPercent)c.String(status, "\n"+message)
}// CPUCheck checks the cpu usage.
func CPUCheck(c *gin.Context) {cores, _ := cpu.Counts(false)a, _ := load.Avg()l1 := a.Load1l5 := a.Load5l15 := a.Load15status := http.StatusOKtext := "OK"if l5 >= float64(cores-1) {status = http.StatusInternalServerErrortext = "CRITICAL"} else if l5 >= float64(cores-2) {status = http.StatusTooManyRequeststext = "WARNING"}message := fmt.Sprintf("%s - Load average: %.2f, %.2f, %.2f | Cores: %d", text, l1, l5, l15, cores)c.String(status, "\n"+message)
}// RAMCheck checks the disk usage.
func RAMCheck(c *gin.Context) {u, _ := mem.VirtualMemory()usedMB := int(u.Used) / MBusedGB := int(u.Used) / GBtotalMB := int(u.Total) / MBtotalGB := int(u.Total) / GBusedPercent := int(u.UsedPercent)status := http.StatusOKtext := "OK"if usedPercent >= 95 {status = http.StatusInternalServerErrortext = "CRITICAL"} else if usedPercent >= 90 {status = http.StatusTooManyRequeststext = "WARNING"}message := fmt.Sprintf("%s - Free space: %dMB (%dGB) / %dMB (%dGB) | Used: %d%%", text, usedMB, usedGB, totalMB, totalGB, usedPercent)c.String(status, "\n"+message)
}
4. 安装依赖并测试
mod tidy 会自动检查依赖并下载需要的内容,非常nice
```
go mod tidy
```
这里主要是安装了:
```
go get github.com/shirou/gopsutil/cpu
go get github.com/shirou/gopsutil/disk
go get github.com/shirou/gopsutil/load
go get github.com/shirou/gopsutil/mem
```
5. 测试
命令行测试:
# curl http://localhost:8090/sd/healthOK
ApiPost测试:
6. 启动apiserver时自检
上面我们已经实现了几个接口用于获取服务器状态,但是,它需要我们主动访问才能获取状态,那么我们如何能在有问题时,直接收到提醒呢?定时任务/监控系统:编写监控脚本,有问题时提醒
启动服务时:主动检查,有问题直接停掉服务,提醒管理员
有时候 API 进程起来不代表 API 服务器正常,如API 进程存在,但是服务器却不能对外提供服务。因此在启动 API 服务器时,如果能够最后做一个自检会更好些。
在 apiserver 中添加了自检程序,通过自检可以最大程度地保证启动后的 API 服务器处于健康状态。
apiserver/main.go
定义pingServer用于检查/sd/health是否正常访问
// pingServer pings the http server to make sure the router is working.
func pingServer() error {for i := 0; i < 10; i++ {// 请求/sd/health => Get返回值有两个resp, err := http.Get("http://127.0.0.1:8090" + "/sd/health")log.Print("Waiting for the router, retry in 1 second.")// 如果返回200,则表示启动成功,直接返回nilif err == nil && resp.StatusCode == 200 {return nil}// 否则1秒后重试log.Print("Waiting for the router, retry in 1 second.")time.Sleep(time.Second)}// 尝试10次,均失败则返回一个错误return errors.New("Cannot connect to the router.")
}
在
pingServer()
函数中,http.Get
向http://127.0.0.1:8080/sd/health
发送 HTTP GET 请求如果函数正确执行并且返回的 HTTP StatusCode 为 200,则说明 API 服务器可用。
如果超过指定次数,服务还是不能访问,
pingServer
会 返回errors,表示API服务器不可用。
apiserver/main.go 调用pingServer检查服务是否正常func main() {...// 调用协程函数,检查服务健康状态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.")}()// 让应用运行在本地服务器上,默认监听端口是 8080g.Run(":8090") // listen and serve on 0.0.0.0:8090
}
在启动 HTTP 端口前 go 一个
pingServer
协程(后台并行执行的一个任务)启动 HTTP 端口后,该协程不断地 ping
/sd/health
路径如果成功,则输出部署成功提示
如果失败次数超过一定次数,则终止 HTTP 服务器进程
7. 测试
GO语言04(简单的RESTful API服务器,API 服务器健康状态自检)相关推荐
- mysql例子 restful_Gin实战:Gin+Mysql简单的Restful风格的API
我们已经了解了Golang的Gin框架.对于Webservice服务,restful风格几乎一统天下.Gin也天然的支持restful.下面就使用gin写一个简单的服务,麻雀虽小,五脏俱全.我们先以一 ...
- Gin实战:Gin+Mysql简单的Restful风格的API
我们已经了解了Golang的Gin框架.对于Webservice服务,restful风格几乎一统天下.Gin也天然的支持restful.下面就使用gin写一个简单的服务,麻雀虽小,五脏俱全.我们先以一 ...
- 启动服务错误5拒绝访问_【Go API 开发实战 5】基础1:启动一个最简单的 RESTful API 服务器...
启动一个最简单的 RESTful API 服务器 本节核心内容 启动一个最简单的 RESTful API 服务器 设置 HTTP Header API 服务器健康检查和状态查询 编译并测试 API 本 ...
- 【Go API 开发实战 5】基础1:启动一个最简单的 RESTful API 服务器
本节核心内容 启动一个最简单的 RESTful API 服务器 设置 HTTP Header API 服务器健康检查和状态查询 编译并测试 API 本小节源码下载路径:demo01 可先下载源码到本地 ...
- C语言实现简单的Web服务器
C语言实现简单的Web服务器 一. 基础知识 二. 详细设计 三. 代码实现 四. 功能测试 五. 内容总结 个人博客:coonaa.cn [本文博客同步地址] 在之前的文章中使用C语言实现基于TCP ...
- C语言API接口开发,腾讯云服务器 API C语言接口
腾讯云服务器的官方API和文档非常详尽,但是对于嵌入式设备还不是很友好,为了在项目中开发一个发送短信的功能,写了一个腾讯云服务器的客户端api,抽取了其中框架部分: 腾讯云服务器 API处理的流程: ...
- azure api 管理_具有Azure功能的无服务器API
azure api 管理 在这篇文章中,我将研究一个非常简单的用例. 在执行部署管道时, FlexDeploy可能会产生一些应被批准或拒绝的人工任务. 例如,某人必须批准对生产环境的部署. 可以在Fl ...
- 具有Azure功能的无服务器API
在这篇文章中,我将研究一个非常简单的用例. 在执行部署管道时, FlexDeploy可能会产生一些应被批准或拒绝的人工任务. 例如,某人必须批准对生产环境的部署. 可以在FlexDeploy UI中或 ...
- web api json_有关使用JSON Web令牌保护无服务器API的速成班
web api json What a mouthful of a title. Wouldn't you agree? In this walkthrough you'll learn about ...
- php yii2 api框架,Yii2框架制作RESTful风格的API快速入门教程
先给大家说下什么是REST restful REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征)性状态转移. 它首次出现在2000年Ro ...
最新文章
- 【Linux 内核】进程管理 task_struct 结构体 ① ( task_struct 结构体引入 | task_struct 代码示例 )
- Java 13,最新最全新特性解读
- QScrollArea滚动条
- python输出10行带标号的hello、world_Python输出hello world(各行命令详解)
- (一)密码学之数论基础
- 信号与线性系统管致中第六版pdf_第五讲 信号流图
- 格式工厂采样率,比特率怎样设置才能使音频声音大容量小
- Linux: 查看网络流量
- KVM详解,太详细太深入了,经典
- mapgis 转换为CAD格式图形 显示不出来的处理
- IDEA中一直indexing问题
- 交换机中的生成树,是什么树?
- 科研新手该如何找到合适的文献?| 开启科研之路(王威教授)
- Coursera课程自然语言处理(NLP)笔记整理(一)
- 2021-01-25广州大学ACM寒假训练赛解题心得
- matlab mex命令,matlab 调用mex
- 对自定义类实现排序的四种方法
- Java面试题(十九) 细说线程池秘境“七大参数”护法的身世
- H5+CSS3 背景图毛玻璃效果实现方案
- 微.解析FoMo3D及其赝品(含智能合约解释)
热门文章
- Open JDK patched with font fix
- 写出linux命令的功能,练习一LINUX命令测试题1
- 通过Socket实现群聊的思路
- 二本学生四年的求职经历
- 计算机局域网的组网,计算机局域网组网方案设计(精选).doc
- npm publish常见问题
- 明源软件热忱欢迎您的加入---2011年校园招聘
- 电脑连上手机热点后上不了网
- 【SpringBoot】63、SpringBoot中教你手把手封装自己的starter(xxl-job-spring-boot-starter)
- oracle rman optimization,Oracle rman备份的使用(转)