1. 程式人生 > >sqler sql 轉rest api 原始碼解析(一)應用的啟動入口

sqler sql 轉rest api 原始碼解析(一)應用的啟動入口

sqler sql 轉rest api 的原始碼還是比較簡單的,沒有比較複雜的設計,大部分都是基於開源
模組實現的。
說明: 當前的版本為2.0,程式碼使用go mod 進行包管理,如果本地執行注意golang 版本,我使用docker 執行, 
參考 https://github.com/rongfengliang/sqler-docker-compose/blob/master/Dockerfile

依賴的開源包

  • 配置解析的(比如bind,exec,validates,include。。。) 使用hashicorp/hcl ,同時使用了text/template 主要是處理sql 的
  • redis 協議支援的(包含了list,help) tidwall/redcon
  • validate,bind ,authorizer 的指定解析 dop251/goja golang 版的js 包
  • exec sql 引數傳遞,通過js 包解析的,dop251/goja
  • rest 路由、請求處理 labstack/echo ,基於context 的巨集解析引數傳遞

處理流程

入口

入口主要包含的資料庫連線的檢測,以及配置檔案巨集的解析,以及rest 、resp 支援協議的啟動

  • 啟動引數的定義
    vars.go,主要是對於啟動引數的定義,包括dsn,driver,resp rest埠定義,同時定義了 macrosManager
    變數
    這個變數在init 階段進行初始化
 
// 啟動變數定義
var (
  flagDBDriver = flag.String("driver", "mysql", "the sql driver to be used")
  flagDBDSN = flag.String("dsn", "root:
[email protected]
(127.0.0.1)/test?multiStatements=true", "the data source name for the selected engine")
  flagAPIFile = flag.String("config", "./config.example.hcl", "the config file(s) that contains your endpoints configs, it accepts comma seprated list of glob style pattern")
  flagRESTListenAddr = flag.String("rest", ":8025", "the http restful api listen address")
  flagRESPListenAddr = flag.String("resp", ":3678", "the resp (redis protocol) server listen address")
  flagWorkers = flag.Int("workers", runtime.NumCPU(), "the maximum workers count")
)
var (
  errNoMacroFound = errors.New("Resource not found")
  errValidationError = errors.New("Validation error")
  errAuthorizationError = errors.New("Authorization Error")
)
var (
  errStatusCodeMap = map[error]int{
    errNoMacroFound: 404,
    errValidationError: 422,
    errAuthorizationError: 401,
  }
)
// 巨集管理變數定義
var (
  macrosManager *Manager
)
   
  • init
    init.go
    init 使用的是golang 的特性,主要是對於資料庫驅動的載入、配置資料庫連線狀態的檢測、以及巨集的解析,賦值(vars.go )
 
{
    // 配置資料庫狀態檢測
    tstconn, err := sqlx.Connect(*flagDBDriver, *flagDBDSN)
    if err != nil {
      fmt.Println(color.RedString("[%s] %s - connection error - (%s)", *flagDBDriver, *flagDBDSN, err.Error()))
      os.Exit(0)
    }
    tstconn.Close()
  }
  {
    // 巨集的解析以及vars.go 中變數的賦值
    manager, err := NewManager(*flagAPIFile)
    if err != nil {
      fmt.Println(color.RedString("(%s)", err.Error()))
      os.Exit(0)
    }
    macrosManager = manager
  }
   
  • macrosManager 的處理
    macrosManager 主要是解析hcl 配置檔案,並儲存map 物件中,同時提供了GET以及LIST 方便後邊
    echo rest 框架處理巨集呼叫的
    macrosManager 資料結構
 
type Manager struct {
  // 巨集物件,包含了,rest 請求的生命週期的元件
  macros map[string]*Macro
 // 主要是為了使用使用text/template 模版解析exec 巨集
  compiled *template.Template
}
   

Macro 資料結構
Macro 定義了每個巨集的完整資訊: method validator authorizer exec bind include(依賴),transformer 資料轉換
主要的方式是Call ,更具輸入的input 資料指定rest 的處理(資料校驗,資料繫結,依賴執行,資料轉換),後邊
為具體分析

type Macro struct {
  Methods []string
  Include []string
  Validators map[string]string
  Authorizer string
  Bind map[string]string
  Exec string
  Aggregate []string
  Transformer string
  name string
  manager *Manager
}
   
  • mian 入口
    main.go 主要是對於rest 以及resp 協議服務的初始化&&啟動
 
// resp 協議支援
go (func() {
    err <- initRESPServer()
  })()
// rest 協議支援
  go (func() {
    err <- initRESTServer()
  })()
 

參考資料

https://github.com/dop251/goja 
https://github.com/tidwall/redcon 
https://github.com/labstack/echo 
https://github.com/hashicorp/hcl