本文介绍如何使用Golang实现心跳程序。
需求说明
实现心跳程序,其他应用可以简单集成。客户端程序通过HTTP协议进行检测,返回当前程序状态、版本ID以及已运行时间。
程序实现
package main
import (
"encoding/json"
"github.com/hako/durafmt"
"log"
"net/http"
"time"
)
const NotAvailableMessage = "Not available"
var CommitHash string
var StartTime time.Time
type HeartbeatMessage struct {
Status string `json:"status"`
Build string `json:"build"`
Uptime string `json:"uptime"`
}
func init() {
StartTime = time.Now()
}
func handler(rw http.ResponseWriter, r *http.Request) {
hash := CommitHash
if hash == "" {
hash = NotAvailableMessage
}
df, _ := durafmt.ParseString(time.Since(StartTime).String())
uptime := df.String()
err := json.NewEncoder(rw).Encode(HeartbeatMessage{"running", hash, uptime})
if err != nil {
log.Fatalf("Failed to write heartbeat message. Reason: %s", err.Error())
}
}
func RunHeartbeatService(address string) {
http.HandleFunc("/heartbeat", handler)
log.Println(http.ListenAndServe(address, nil))
}
首先定义了两个变量,CommitHash、StartTime,然后定义结构体HeartbeatMessage封装返回值。
接着在init方法中给StartTime变量赋初始值。下面时处理请求handler方法:
func handler(rw http.ResponseWriter, r *http.Request) {
hash := CommitHash
if hash == "" {
hash = NotAvailableMessage
}
df, _ := durafmt.ParseString(time.Since(StartTime).String())
uptime := df.String()
err := json.NewEncoder(rw).Encode(HeartbeatMessage{"running", hash, uptime})
if err != nil {
log.Fatalf("Failed to write heartbeat message. Reason: %s", err.Error())
}
}
这个把CommitHash给hash,CommitHash可以通过上文的知识,在编译时赋值。然后计算应用已运行的时间并返回HeartbeatMessage结构体的值。durafmt是时间周期格式化工具,比内置的更直观易用。
当然最重要的是HTTP服务,Golang只需要一句代码http.ListenAndServe(address, nil)
就搞定:
func RunHeartbeatService(address string) {
http.HandleFunc("/heartbeat", handler)
log.Println(http.ListenAndServe(address, nil))
}
该函数定义http服务,同时暴露一个请求地址:/heartbeat
。
Postman测试
定义一个最简单的应用,在main方法中调用心跳功能,为了避免影响业务,让其在独立的协程中运行。
func main() {
go RunHeartbeatService(":9090")
// 阻塞主程序,模拟应用一直在运行
select {}
}
现在可以通过postman定时请求心跳地址,验证程序是否一直正常运行。
localhost:9090/heartbeat
{"status":"running","build":"Not available","uptime":"3 minutes 47 seconds 148 milliseconds 967 microseconds"}
Go客户端测试
下面我们写Get方法,使用Go语言实现http客户端进行测试:
func Get(address string) (HeartbeatMessage, error) {
// 定义http client
client := &http.Client{}
req, err := http.NewRequest("GET", address, nil)
resp, err := client.Do(req)
if err != nil {
return HeartbeatMessage{}, err
}
// 解析响应并返回结果
b, err := io.ReadAll(resp.Body)
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return HeartbeatMessage{}, errors.New(fmt.Sprintf("Wrong status code: %d", resp.StatusCode))
}
message := HeartbeatMessage{}
err = json.Unmarshal(b, &message)
if err != nil {
log.Println("Error occured unmarshalling the response")
}
return message, nil
}
Go单元测试
package main
import (
"fmt"
"testing"
)
func TestGet(t *testing.T) {
hs, err := Get("http://localhost:9090/heartbeat")
if err != nil {
fmt.Println(err)
}
fmt.Println(hs)
}
测试结果:
=== RUN TestGet
{running Not available 6 minutes 2 seconds 625 milliseconds 381 microseconds}
--- PASS: TestGet (0.01s)
PASS
当然还可以使用httptest进行模拟测试,本月有机会学习分享。参考代码:
https://github.com/enbritely/heartbeat-golang
到此这篇关于Golang编译选项ldflags实例应用详解的文章就介绍到这了,更多相关Golang ldflags内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!