1. 程式人生 > 實用技巧 >haproxy dataplaneapi golang sdk 簡單使用

haproxy dataplaneapi golang sdk 簡單使用

前邊有簡單說過基於go-swagger 生成haproxy dataplaneapi api 以下一個簡單說明

環境準備

  • docker-compose 檔案
version: "3"
services:
  grafana:
   image: grafana/grafana
   ports:
   - "3000:3000"
  prometheus:
   image: prom/prometheus
   volumes:
   - "./prometheus.yml:/etc/prometheus/prometheus.yml"
   ports:
   - "9090:9090"
  haproxy:
   build: ./
   ports:
   - "80:80"
   - "5555:5555"
   - "8404:8404"
   - "8080:8080"
   - "9000:9000"
   - "9001:9001"
   - "9002:9002"
   - "1000-1005:1000-1005"
   - "10080:10080"
  nginx1:
   image: nginx
   ports:
   - "8090:80"
  nginx2:
   image: nginx
   ports:
   - "8091:80"
  • haproxy dockerfile
    基於haproxy 團隊的docker映象(內建了dataplaneapi)
FROM haproxytech/haproxy-debian:2.2.1
COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg
  • demo haproxy 配置
global 
 user root
 group root
 master-worker
 stats socket /run/haproxy.sock mode 600 level admin
 stats timeout 2m
 log stdout local0
 mworker-max-reloads 3
 set-dumpable
defaults 
 mode http
 log global
 option httplog
 option redispatch
 timeout connect 5s
 timeout client 5s
 timeout server 5s
userlist api 
 user admin insecure-password dalong
resolvers dns 
 hold nx 30s
 hold obsolete 30s
 hold other 30s
 hold refused 30s
 hold timeout 30s
 hold valid 10s
 timeout resolve 1s
 timeout retry 1s
 resolve_retries 3
 parse-resolv-conf
frontend stats 
 bind *:8404
 stats enable
 stats uri /stats
 stats refresh 10s
 http-request use-service prometheus-exporter if { path /metrics }
frontend test_frontend 
 mode http
 maxconn 2000
 bind *:10080 name http
 default_backend test_backend
backend be_503 
 errorfile 503 /usr/local/etc/haproxy/errors/503.http
backend test_backend 
 mode http
 balance roundrobin
 server server1 nginx1:80 check maxconn 30 weight 100
program dataplane-api 
 command /usr/bin/dataplaneapi --log-level=debug --host 0.0.0.0 --port 5555 --haproxy-bin /usr/sbin/haproxy --config-file /usr/local/etc/haproxy/haproxy.cfg --reload-cmd "kill -SIGUSR2 1" --restart-cmd="" --reload-delay 5 --userlist=api
 no option start-on-reload
  • 啟動效果

會有一個示例demo,以下是stat 介面

程式碼整合

以下是一個簡單的程式碼整合,具體操作處理流程我有寫過,可以參考 https://www.cnblogs.com/rongfengliang/p/12914925.html

package main
import (
 "context"
 "log"
 httptransport "github.com/go-openapi/runtime/client"
 "github.com/go-openapi/strfmt"
 "github.com/rongfengliang/haproxy-golang/client"
 "github.com/rongfengliang/haproxy-golang/client/backend"
 "github.com/rongfengliang/haproxy-golang/client/bind"
 "github.com/rongfengliang/haproxy-golang/client/frontend"
 "github.com/rongfengliang/haproxy-golang/client/server"
 "github.com/rongfengliang/haproxy-golang/client/transactions"
 "github.com/rongfengliang/haproxy-golang/models"
)
// String point
func String(s string) *string {
 return &s
}
// Bool point
func Bool(s bool) *bool {
 return &s
}
// Int64 point
func Int64(s int64) *int64 {
 return &s
}
func main() {
 // context object for  control connet
 ctx := context.Background()
 // 1. first get  transaction version
 client := client.New(httptransport.New("localhost:5555", "/v2", []string{"http"}), strfmt.Default)
 // make the authenticated request to get all items
 basicAuth := httptransport.BasicAuth("admin", "dalong")
 frontends, err := client.Frontend.GetFrontends(nil, basicAuth)
 if err != nil {
  log.Panicln("some wrong:", err)
  }
 versionID := frontends.ConfigurationVersion
 log.Println(versionID)
 // for test print frontend info
 for _, frontend := range frontends.GetPayload().Data {
  log.Println("get frontend info :", frontend.Name, frontend.Mode, frontend.DefaultBackend)
  }
 // 2. create transaction for generate id
 commitTransaction, err := client.Transactions.StartTransaction(&transactions.StartTransactionParams{Version: versionID, Context: ctx}, basicAuth)
 if err != nil {
  log.Panicln("create transaction some wrong:", err.Error())
  }
 transactionID := commitTransaction.Payload.ID
 log.Println(transactionID)
 // 3. create backend object
 createBackendCreated, createBackendAccepted, err := client.Backend.CreateBackend(&backend.CreateBackendParams{
  Context: ctx,
  Data: &models.Backend{
   Name: "dalongrong",
   Mode: "http",
   Balance: &models.Balance{
    Algorithm: String("roundrobin"),
    },
   Httpchk: &models.Httpchk{
    Method: "HEAD",
    URI:   "/",
    Version: "HTTP/1.1",
    },
   },
  TransactionID: &transactionID,
  }, basicAuth)
 if err != nil {
  log.Panicln("create backend some wrong:", err.Error())
  }
 if createBackendCreated == nil {
  log.Println(createBackendAccepted.GetPayload())
  }
 // 4. add backend server to backend use create server wrapper
 createServerCreated, createServerAccepted, err := client.Server.CreateServer(&server.CreateServerParams{
  TransactionID: &transactionID,
  Backend:    "dalongrong",
  Context:    ctx,
  Data: &models.Server{
   Name:  "server1",
   Address: "nginx2",
   Port:  Int64(80),
   Check:  "disabled",
   Maxconn: Int64(30),
   Weight: Int64(100),
   },
  }, basicAuth)
 if err != nil {
  log.Panicln("add  backend server has some wrong:", err.Error())
  }
 if createServerCreated == nil {
  log.Println(createServerAccepted.GetPayload())
  }
 // 5. create frontend
 createFrontendCreated, createFrontendAccepted, err := client.Frontend.CreateFrontend(&frontend.CreateFrontendParams{
  TransactionID: &transactionID,
  Data: &models.Frontend{
   Name:      "dalongrong_frontend",
   Mode:      "http",
   DefaultBackend: "dalongrong",
   Maxconn:    Int64(1000),
   },
  Context: ctx,
  }, basicAuth)
 if err != nil {
  log.Panicln("create  frontend  has some wrong:", err.Error())
  }
 if createFrontendCreated == nil {
  log.Println(createFrontendAccepted.GetPayload())
  }
 // 6. create frontend && backend bind
 createBindCreated, createBindAccepted, err := client.Bind.CreateBind(&bind.CreateBindParams{
  TransactionID: &transactionID,
  Frontend:   "dalongrong_frontend",
  Data: &models.Bind{
   Name:  "httpdemo",
   Address: "*",
   Port:  Int64(9000),
   },
  Context: ctx,
  }, basicAuth)
 if err != nil {
  log.Panicln("create  bind  has some wrong:", err.Error())
  }
 if createBindCreated == nil {
  log.Println(createBindAccepted.GetPayload())
  }
 // 7. apply transaction && do commit
 commitTransactionOK, commitTransactionAccepted, err := client.Transactions.CommitTransaction(&transactions.CommitTransactionParams{
  ID:   transactionID,
  Context: ctx,
  }, basicAuth)
 if err != nil {
  log.Panicln("apply haproxy config  has some wrong:", err.Error())
  }
 if commitTransactionOK != nil {
  // apply config ok
  log.Println(commitTransactionOK.GetPayload())
  }
 if commitTransactionAccepted != nil {
  // accept but not apply success
  log.Println(commitTransactionAccepted.GetPayload())
  }
}
  • 執行
go run main.go
  • 效果

說明

以上是一個簡單的使用說明,實際上我們基於swagger api 也可以提供其他語言的支援(nodejs,golang)同時也可以製作一個dashboard,當然新版本對於
haproxy 配置的更新處理使用了一個原子操作的 renameio,簡化了以前配置reload 的處理

參考資料

https://hub.docker.com/r/haproxytech/haproxy-debian
https://github.com/rongfengliang/haproxy-dataplaneapi-golang
https://github.com/haproxytech/dataplaneapi
https://github.com/google/renameio