-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
268 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# This is an example goreleaser.yaml file with some sane defaults. | ||
# Make sure to check the documentation at http://goreleaser.com | ||
builds: | ||
- | ||
env: | ||
- CGO_ENABLED=0 | ||
binary: pxc-checker | ||
archive: | ||
replacements: | ||
darwin: MacOS | ||
linux: Linux | ||
windows: Windows | ||
386: i386 | ||
amd64: x86_64 | ||
checksum: | ||
name_template: 'checksums.txt' | ||
snapshot: | ||
name_template: "{{ .Tag }}-next" | ||
changelog: | ||
sort: asc | ||
filters: | ||
exclude: | ||
- '^docs:' | ||
- '^test:' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
language: go | ||
go: | ||
- 1.9.x | ||
- tip | ||
|
||
os: | ||
- linux | ||
dist: trusty | ||
sudo: false | ||
|
||
matrix: | ||
allow_failures: | ||
- go: tip | ||
|
||
gobuild_args: -v | ||
|
||
script: | ||
- cd "${TRAVIS_BUILD_DIR}" | ||
- go get | ||
- go build -o pxc-checker ./... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
_ "github.com/go-sql-driver/mysql" | ||
"github.com/valyala/fasthttp" | ||
"strconv" | ||
"time" | ||
) | ||
|
||
type ReasonCode int | ||
|
||
const ( | ||
reasonInternalError ReasonCode = -1 | ||
reasonOk ReasonCode = 0 | ||
reasonForceEnabled ReasonCode = 1 | ||
reasonNodeNotAvailable ReasonCode = 2 | ||
reasonWSRepFailed ReasonCode = 3 | ||
reasonCheckTimeout ReasonCode = 4 | ||
reasonRWDisabled ReasonCode = 5 | ||
) | ||
|
||
type Response struct { | ||
*NodeStatus | ||
ReasonText string | ||
ReasonCode ReasonCode | ||
} | ||
|
||
func checkerHandler(ctx *fasthttp.RequestCtx) { | ||
|
||
response := Response{NodeStatus: status} | ||
ctx.SetContentType("application/json") | ||
|
||
if config.CheckForceEnable { | ||
ctx.SetStatusCode(fasthttp.StatusOK) | ||
response.ReasonText = "Force enabled" | ||
response.ReasonCode = reasonForceEnabled | ||
} else if !status.NodeAvailable { | ||
ctx.SetStatusCode(fasthttp.StatusServiceUnavailable) | ||
response.ReasonText = "Node is not available" | ||
response.ReasonCode = reasonNodeNotAvailable | ||
} else if (status.WSRepStatus != 4) && (status.WSRepStatus != 2) { | ||
ctx.SetStatusCode(fasthttp.StatusServiceUnavailable) | ||
response.ReasonText = "WSRep failed" | ||
response.ReasonCode = reasonWSRepFailed | ||
} else if float64(status.Timestamp)+float64(config.CheckFailTimeout)/1000 < float64(time.Now().Unix()) { | ||
ctx.SetStatusCode(fasthttp.StatusServiceUnavailable) | ||
response.ReasonText = "Check timeout" | ||
response.ReasonCode = reasonCheckTimeout | ||
} else if !config.CheckROEnabled && !status.RWEnabled { | ||
ctx.SetStatusCode(fasthttp.StatusServiceUnavailable) | ||
response.ReasonText = "Node is read only" | ||
response.ReasonCode = reasonRWDisabled | ||
} else { | ||
ctx.SetStatusCode(fasthttp.StatusOK) | ||
response.ReasonText = "OK" | ||
response.ReasonCode = reasonOk | ||
} | ||
|
||
if respJson, err := json.Marshal(response); err != nil { | ||
errStr := fmt.Sprintf(`{"ReasonText":"Internal checker error","ReasonCode":%d,"err":"%s"}`, reasonInternalError, err) | ||
ctx.SetBody([]byte(errStr)) | ||
ctx.SetStatusCode(fasthttp.StatusInternalServerError) | ||
} else { | ||
ctx.SetBody(respJson) | ||
} | ||
|
||
return | ||
} | ||
|
||
func checker(status *NodeStatus) { | ||
for { | ||
time.Sleep(time.Duration(config.CheckInterval) * time.Millisecond) | ||
curStatus := &NodeStatus{} | ||
curStatus.Timestamp = int(time.Now().Unix()) | ||
|
||
rows, err := dbConn.Query("SHOW GLOBAL VARIABLES;") | ||
if err != nil { | ||
*status = *curStatus | ||
continue | ||
} | ||
curStatus.NodeAvailable = true | ||
|
||
for rows.Next() { | ||
var key, value string | ||
err := rows.Scan(&key, &value) | ||
if err != nil { | ||
*status = *curStatus | ||
continue | ||
} | ||
switch key { | ||
case "read_only": | ||
if value == "OFF" { | ||
curStatus.RWEnabled = true | ||
} | ||
case "wsrep_local_state": | ||
curStatus.WSRepStatus, _ = strconv.Atoi(value) | ||
} | ||
} | ||
|
||
*status = *curStatus | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
WEB_LISTEN=":9200" | ||
|
||
MYSQL_HOST="127.0.0.1" | ||
MYSQL_PORT=3306 | ||
MYSQL_USER="monitor" | ||
MYSQL_PASS="monitorUserPassword" | ||
|
||
CHECK_RO_ENABLED=false | ||
CHECK_FORCE_ENABLE=false | ||
CHECK_INTERVAL=500 # ms | ||
CHECK_FAIL_TIMEOUT=3000 # ms |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package main | ||
|
||
import ( | ||
"database/sql" | ||
"fmt" | ||
"github.com/buaazp/fasthttprouter" | ||
"github.com/labstack/gommon/log" | ||
"github.com/namsral/flag" | ||
"github.com/valyala/fasthttp" | ||
"time" | ||
) | ||
|
||
type NodeStatus struct { | ||
WSRepStatus int | ||
RWEnabled bool | ||
NodeAvailable bool | ||
Timestamp int | ||
} | ||
|
||
type Config struct { | ||
WebListen string | ||
WebReadTimeout int | ||
WebWriteTimeout int | ||
CheckROEnabled bool | ||
CheckInterval int | ||
CheckFailTimeout int | ||
CheckForceEnable bool | ||
MysqlHost string | ||
MysqlPort int | ||
MysqlUser string | ||
MysqlPass string | ||
MysqlTimeout int | ||
} | ||
|
||
var ( | ||
status = &NodeStatus{} | ||
config *Config | ||
dbConn *sql.DB | ||
) | ||
|
||
func main() { | ||
var err error | ||
config, err = parseFlags() | ||
if err != nil { | ||
log.Fatalf("Options parsing failed with err: %s", err) | ||
} | ||
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/", config.MysqlUser, config.MysqlPass, config.MysqlHost, config.MysqlPort) | ||
log.Printf("Connecting to mysql with dsn: %s", dsn) | ||
dbConn, _ = sql.Open("mysql", dsn) | ||
|
||
go checker(status) | ||
|
||
router := getRouter() | ||
server := &fasthttp.Server{ | ||
Handler: router.Handler, | ||
DisableKeepalive: true, | ||
GetOnly: true, | ||
Concurrency: 2048, | ||
ReadTimeout: time.Duration(config.WebReadTimeout) * time.Millisecond, | ||
WriteTimeout: time.Duration(config.WebWriteTimeout) * time.Millisecond, | ||
} | ||
|
||
log.Printf("Server starting on %s", config.WebListen) | ||
if err := server.ListenAndServe(config.WebListen); err != nil { | ||
log.Fatalf("Error in ListenAndServe: %s", err) | ||
} | ||
} | ||
|
||
func getRouter() *fasthttprouter.Router { | ||
router := fasthttprouter.New() | ||
router.GET("/", checkerHandler) | ||
return router | ||
} | ||
|
||
func parseFlags() (*Config, error) { | ||
config := Config{} | ||
flag.StringVar(&config.WebListen, "WEB_LISTEN", ":9200", "Listen interface and port") | ||
flag.IntVar(&config.WebReadTimeout, "WEB_READ_TIMEOUT", 30000, "Request read timeout, ms") | ||
flag.IntVar(&config.WebWriteTimeout, "WEB_WRITE_TIMEOUT", 30000, "Request write timeout, ms") | ||
flag.BoolVar(&config.CheckROEnabled, "CHECK_RO_ENABLED", false, "Make 'read_only' nodes availible") | ||
flag.BoolVar(&config.CheckForceEnable, "CHECK_FORCE_ENABLE", false, "Ignoring checks status and force enable node") | ||
flag.IntVar(&config.CheckInterval, "CHECK_INTERVAL", 500, "Mysql checks interval, ms") | ||
flag.IntVar(&config.CheckFailTimeout, "CHECK_FAIL_TIMEOUT", 3000, "To count a node inaccessible if for the specified time there were no successful checks, ms") | ||
flag.StringVar(&config.MysqlHost, "MYSQL_HOST", "127.0.0.1", "MySQL host addr") | ||
flag.IntVar(&config.MysqlPort, "MYSQL_PORT", 3306, "MySQL port addr") | ||
flag.StringVar(&config.MysqlUser, "MYSQL_USER", "monitor", "MySQL username") | ||
flag.StringVar(&config.MysqlPass, "MYSQL_PASS", "", "MySQL password") | ||
|
||
flag.Parse() | ||
return &config, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[Unit] | ||
Description=PXC Checker | ||
After=network.target | ||
|
||
[Service] | ||
EnvironmentFile=/etc/pxc/checker/%i.conf | ||
ExecStart=/usr/bin/pxc-checker | ||
KillMode=process | ||
User=mysql | ||
Group=mysql | ||
|
||
[Install] | ||
WantedBy=multi-user.target |