Skip to content

Commit

Permalink
feature 支持4层日志,优化健康检查
Browse files Browse the repository at this point in the history
  • Loading branch information
GuoFlight committed Aug 25, 2024
1 parent 7e87ad2 commit bb09863
Show file tree
Hide file tree
Showing 11 changed files with 289 additions and 6 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# v0.5.0

新特性(Features)

* 支持配置nginx日志(access_log)

优化

* 健康检查接口:检查nginx配置是否正确

# v0.4.0

新特性(Features)
Expand Down
14 changes: 13 additions & 1 deletion api/v1/handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package v1

import (
"github.com/gin-gonic/gin"
"openfly/common"
)

type Res struct {
Expand All @@ -11,5 +12,16 @@ type Res struct {
}

func Health(c *gin.Context) {
c.String(200, "alive")
_, gerr := common.GNginx.Test()
if gerr != nil {
c.JSON(200, Res{
Code: 1,
Msg: gerr.Error(),
})
return
}
c.JSON(200, Res{
Code: 0,
Msg: "healthy",
})
}
9 changes: 9 additions & 0 deletions common/datastruct.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ type NginxConfL4 struct {
IncludeFiles []string `json:"includeFiles,omitempty"`
WhiteList []WhiteListItem `json:"whiteList,omitempty"`
Comments []string `json:"comments,omitempty"`
// 日志
Log NginxLog `json:"log,omitempty"`
// 限速
ProxyUploadRate string `json:"proxyUploadRate,omitempty"`
ProxyDownloadRate string `json:"proxyDownloadRate,omitempty"`
Expand Down Expand Up @@ -41,3 +43,10 @@ type UpstreamHost struct {
FailTimeoutSecond int `json:"failTimeoutSecond,omitempty"`
IsBackup bool `json:"isBackup,omitempty"`
}
type NginxLog struct {
Mod string `json:"mod,omitempty"` // off:不打印日志;local:单独打印日志;global/其他:继承全局配置。
FormatName string `json:"formatName,omitempty"`
Path string `json:"path,omitempty"`
Buffer string `json:"buffer,omitempty"`
Flush string `json:"flush,omitempty"`
}
45 changes: 45 additions & 0 deletions common/nginx.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,17 @@ func (n *Nginx) CheckConfigL4(l4s []NginxConfL4) *gerror.Gerr {
if gerr != nil {
return gerr
}
// 参数校验:日志
reLogBuffer := "^[0-9]+[km]?$"
regular = regexp.MustCompile(reLogBuffer)
if l4.Log.Buffer != "" && !regular.MatchString(l4.Log.Buffer) {
return gerror.NewErr(fmt.Sprintf("invalid buffer: %s,Expected: %s", l4.Log.Buffer, reLogBuffer))
}
reLogFlush := "^[0-9]+[sm]?$"
regular = regexp.MustCompile(reLogFlush)
if l4.Log.Flush != "" && !regular.MatchString(l4.Log.Flush) {
return gerror.NewErr(fmt.Sprintf("invalid flush: %s,Expected: %s", l4.Log.Flush, reLogFlush))
}
}
return nil
}
Expand All @@ -102,6 +113,11 @@ func (n *Nginx) GenConfigL4(l4 NginxConfL4) (string, *gerror.Gerr) {
confUpstream := n.genConfigL4Upstream(l4.Upstream, l4.Listen)
// 生成server语句
confServer = append(confServer, fmt.Sprintf("listen %d;", l4.Listen))
// 生成access_log语句
confLog := n.genConfigL4Log(l4)
if confLog != "" {
confServer = append(confServer, confLog)
}
// 生成proxy_pass语句
confServer = append(confServer, fmt.Sprintf("proxy_pass %d;", l4.Listen))
// 限速
Expand Down Expand Up @@ -136,6 +152,35 @@ func (n *Nginx) GenConfigL4(l4 NginxConfL4) (string, *gerror.Gerr) {
}
return fmt.Sprintf("%s\n%s\nserver {\n\t%s\n}", commentStr, confUpstream, strings.Join(confServer, "\n\t")), nil
}
func (n *Nginx) genConfigL4Log(l4 NginxConfL4) string {
if l4.Log.Mod == "local" {
// 日志路径
if l4.Log.Path == "" {
l4.Log.Path = filepath.Join(conf.GConf.L4.Log.Path, fmt.Sprintf("%d.stream.log", l4.Listen))
}
ret := fmt.Sprintf("access_log %s", l4.Log.Path)
// 日志格式
if l4.Log.FormatName == "" {
l4.Log.FormatName = conf.GConf.L4.Log.FormatNameDefault
}
if l4.Log.FormatName != "" {
ret = ret + " " + l4.Log.FormatName
}
// buffer
if l4.Log.Buffer != "" {
ret = ret + " " + fmt.Sprintf("buffer=%s", l4.Log.Buffer)
}
// flush
if l4.Log.Flush != "" {
ret = ret + " " + fmt.Sprintf("flush=%s", l4.Log.Flush)
}
return ret + ";"
} else if l4.Log.Mod == "off" {
return "access_log off;"
} else {
return ""
}
}
func (n *Nginx) genConfigL4Upstream(upstream Upstream, port int) string {
var confUpstream []string
// 生成upstream中的server语句
Expand Down
58 changes: 58 additions & 0 deletions common/nginx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ func TestNginx_GenConfigL4(t *testing.T) {
ProxyUploadRate: "20M",
ProxyConnectTimeout: "1s",
ProxyTimeout: "2m",
Log: NginxLog{
Mod: "local",
FormatName: "main",
Path: "",
Buffer: "5k",
Flush: "5s",
},
WhiteList: []WhiteListItem{
{
conf.Allow,
Expand Down Expand Up @@ -163,3 +170,54 @@ func TestNginx_CheckConfigL4(t *testing.T) {
fmt.Println(gerr)
}
}

func TestNginx_genConfigL4Log(t *testing.T) {
l4 := NginxConfL4{Listen: 8081}
// 关闭日志
l4.Log = NginxLog{
Mod: "off",
FormatName: "",
Path: "",
Buffer: "",
Flush: "",
}
conf := GNginx.genConfigL4Log(l4)
fmt.Println(conf)
// 输出空
l4.Log = NginxLog{
Mod: "global",
}
conf = GNginx.genConfigL4Log(l4)
fmt.Println(conf)
// 输出空
l4.Log = NginxLog{
Mod: "hosydfoshdfw0efwef",
}
conf = GNginx.genConfigL4Log(l4)
fmt.Println(conf)
// 自动生成日志路径
l4.Log = NginxLog{
Mod: "local",
Path: "",
}
conf = GNginx.genConfigL4Log(l4)
fmt.Println(conf)
// 指定日志路径和log_format
l4.Log = NginxLog{
Mod: "local",
Path: "/var/log/nginx/test.log",
FormatName: "test_log",
}
conf = GNginx.genConfigL4Log(l4)
fmt.Println(conf)
// 指定buffer和flush
l4.Log = NginxLog{
Mod: "local",
Path: "/var/log/nginx/test.log",
FormatName: "test_log",
Buffer: "5k",
Flush: "5s",
}
conf = GNginx.genConfigL4Log(l4)
fmt.Println(conf)
}
21 changes: 18 additions & 3 deletions conf/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import (
)

var (
GConf ConfigFileStruct
PathData = "./data"
DefaultPathBak = "./bak"
GConf ConfigFileStruct
PathData = "./data"
DefaultPathBak = "./bak"
DefaultPathL4Log = "/var/log/nginx/l4"
)

// ConfigFileStruct 配置文件结构体
Expand Down Expand Up @@ -41,6 +42,12 @@ type ConfigFileStruct struct {
MaxFailsDefault int `toml:"maxFailsDefault"`
FailTimeoutDefault int `toml:"failTimeoutDefault"`
} `toml:"nginx"`
L4 struct {
Log struct {
Path string `toml:"path"`
FormatNameDefault string `toml:"formatNameDefault"`
} `toml:"log"`
} `toml:"l4"`
}

// ParseConfig 解析配置文件
Expand Down Expand Up @@ -75,4 +82,12 @@ func CheckAndInit() {
if err != nil {
log.Fatal(err)
}
// 创建L4日志目录
if GConf.L4.Log.Path == "" {
GConf.L4.Log.Path = DefaultPathL4Log
}
err = os.MkdirAll(GConf.L4.Log.Path, 0770)
if err != nil {
log.Fatal(err)
}
}
2 changes: 1 addition & 1 deletion conf/const.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package conf

var (
Version = "v0.4.0"
Version = "v0.5.0"
NgFileExtension = ".conf"
EtcdSubPathL4 = "/l4"
)
Expand Down
7 changes: 6 additions & 1 deletion config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,9 @@ prefix="/openfly"
[nginx]
weightDefault=10
maxFailsDefault=99999
failTimeoutDefault=10
failTimeoutDefault=10

[l4.log]
# Example: "/var/log/nginx/l4"
path="/var/log/nginx/l4"
formatNameDefault="main"
105 changes: 105 additions & 0 deletions docs/v0.5.0/api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# 健康检查

```shell
curl http://127.0.0.1:1216/v1/health
```

# 鉴权

```shell
# 获取Token
token=$(curl -s -XPOST http://127.0.0.1:1216/v1/login -d "{\"username\":\"admin\",\"password\":\"admin\"}" -H "Content-Type: application/json" | jq -r .data)
echo ${token}
# 访问需要鉴权的接口
curl -H "Authorization: ${token}" http://127.0.0.1:1216/xxx
```

# Nginx相关API

```shell
# 删除配置
curl -XDELETE -H "Authorization: ${token}" http://127.0.0.1:1216/v1/admin/nginx/delete?listen=30001
# 禁用指定端口的配置(启用为on,禁用为off)
curl -XPOST -H "Authorization: ${token}" http://127.0.0.1:1216/v1/admin/nginx/switch -d "listen=30001&switch=off"
# 获取指定端口的配置
curl -s -H "Authorization: ${token}" http://127.0.0.1:1216/v1/admin/nginx/get?listen=30001
# 获取所有配置
curl -H "Authorization: ${token}" http://127.0.0.1:1216/v1/admin/nginx/getAll
# 新增L4配置
curl -i -H "Content-Type: application/json" -XPOST -H "Authorization: ${token}" http://127.0.0.1:1216/v1/admin/nginx/add -d '
{
"listen":30001,
"upstream":{
"hosts":[
{
"ip":"1.1.1.1",
"port":53
}
]
}
}'
# 更新L4配置
curl -i -H "Content-Type: application/json" -XPOST -H "Authorization: ${token}" http://127.0.0.1:1216/v1/admin/nginx/set -d '
{
"listen":30001,
"upstream":{
"hosts":[
{
"ip":"1.1.1.1",
"port":53
}
]
}
}'
```

# 所有支持的参数

```shell
curl -i -H "Content-Type: application/json" -XPOST -H "Authorization: ${token}" http://127.0.0.1:1216/v1/admin/nginx/set -d '
{
"disable": false,
"listen": 30001,
"comments": ["我是注释","I am the comment."],
"includeFiles": ["/etc/nginx/my.conf"],
"proxyUploadRate": "10M",
"proxyDownloadRate": "20M",
"proxyConnectTimeout": "10s",
"proxyTimeout": "10m",
"log": { // 默认值:继承全局配置
"mod": "local", // off:不打印日志;local:单独打印日志;global/其他:继承全局配置。
"path": "/var/log/nginx/test.stream.log",
"formatName": "my_log_format",
"buffer": "5k",
"flush": "5s"
},
"upstream":{
"hosts":[
{
"ip": "1.1.1.1",
"port": 53,
"isBackup": false,
"weight": 100,
"maxFails": 10,
"failTimeoutSecond":2
}
],
"isHash": true,
"hashField": "test_field",
"interval": 10,
"rise": 2,
"fall": 2,
"timeout": 1000
},
"whiteList": [
{
"type": "allow",
"target": "1.1.1.1"
},
{
"type": "deny",
"target": "all"
}
]
}'
```
6 changes: 6 additions & 0 deletions docs/v0.5.0/dev.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# 一些测试case

```shell
# 写入有问题的配置
etcdctl put /openfly/l4/30001 '{"listen":30001,"upstream":{"hosts":[{"ip":"","port":53}]}}'
```
18 changes: 18 additions & 0 deletions docs/v0.5.0/faq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
如何优雅退出

* 发送term(15号)给openfly进程,可以在INFO日志中查看到退出过程。示例:```kill <pid>``

若nginx因配置错误无法启动,如何解决?

1. 保证nginx本身配置无错误。
2. 通过openfly接口 修改/删除 错误配置。
3. 通过etcd 修改/删除 错误配置。

添加重复接口会报错吗?

*

若配置有问题,会导致线上问题吗?

* 不会。
* nginx -t失败后配置不生效。

0 comments on commit bb09863

Please sign in to comment.