avatarJen-Hsuan Hsieh (Sean)

总结

本文主要介绍了如何在Golang中构建一个简单的Web服务,用于集成本地Windows服务和可执行文件的API设计,并探讨了不同的实现方法及其优缺点。

摘要

文章首先介绍了将调用执行文件的动作放置在Controller中的直观方法,并通过示例代码展示了如何实现。作者提到了使用libs/jobExecuter.go来执行命令,config.json来配置执行文件路径,以及如何使用spf13/viper库来读取配置文件。接着,文章讨论了将任务写入数据库并由Windows服务检查未执行任务的改进方法,并展示了如何在MySQL中建立新的表格以及如何编写job.go来处理任务的插入。

文章还介绍了如何使用jakecoffman/cron库来设置定时任务,以及如何将应用程序包装成Windows服务使用NSSM。最后,作者总结了整个实施过程,并提供了其他相关主题的文章链接。

观点

  1. 直接在Controller中调用执行文件的方法简单直接,但会导致API响应时间过长,且难以追踪历史执行记录。
  2. 通过将任务写入数据库并由Windows服务定期检查执行任务的方法,可以解耦API的响应时间和执行文件的运行时间,同时也方便了对任务执行的追踪和记录。
  3. 使用定时任务和Windows服务可以让应用程序在后台自动运行,提高了系统的自动化和稳定性。
  4. 作者强调了实践中的学习和记录过程,并鼓励读者在文章中提出见解和建议,以促进知识的交流和讨论。

[Golang] Build A Simple Web Service part.4 — Design An API To Integrate With Local Windows Service And Executable File

Introduction

在實務上很多時候需要讓web service呼叫執行檔做一些事情, 本篇將會分析不同設計方式的優缺點, 並且記錄在Golang中要如何實作這些機制 。

Copy right@A layman

Call executable in the API

最直覺的方式是將呼叫執行檔的動作放到Controller中,一旦Request進來便會呼叫該執行檔 ,先試著使用這樣的方式看看。

Copy right@A layman

基於前一篇中Use the interface的專案資料夾的根目錄下 ,新增libs資料夾 , jobExecuter.go ,config.go以及config.json:

Copy right@A layman

以下將說明新增及修改到的檔案 。

libs/jobExecuter.go: jobExecuter.go的內容如下 ,ExecuteCommand的內容就是呼叫某個執行檔. path為檔案路徑 ,arguments為其參數 ,並將執行過後的std output, error output印出來:

config.json: 這裏將延伸Software Testing — Design A Dark Traffic System To Test HTTPS Requests With Goreplay ,以呼叫Goreplay listener為例 ,將Goreplay的路徑放到config.json中 ,其中key為”gorPath”, value為檔案路徑 。

lib/config.go: Golang有一個很方便的套件管理工具spf13/viper ,Viper 可以支援讀取 JSON ,TOML ,YAML ,HCL 等格式的設定檔案 ,也可以讀取環境變數, 這邊將讀取config的行為封裝成獨立的package 。

安裝方式為在terminal中輸入以下指令:

go get github.com/spf13/viper

安裝完後import進程式碼 ,SetConfigName為檔案名稱 ,AddConfigPath為檔案的相對路徑 ,並用Get指定key以取出對應的value:

routes/webService.go: 首先新增一個struct<>作為API回傳時的格式 ,並在InitRouter中新增一組POST路由-replayTraffics ,並實作這個HTTP handler function 。

在handler中從form取出參數的方式為r.FromValue(“field name”) ,將參數取出後呼叫libs.ExecuteCommand就可以完成透過API呼叫server端執行檔的任務 。

這種作法相當單純 ,角色只有Controller以及近似於plugin的執行檔 ,如果哪天需要改變呼叫的執行檔只需要修改config.json裡的key/value ,並修改controller即可 ,但實際執行後會發現幾個缺點:

1. 顯然需要等到執行檔執行完畢後 ,handler才會丟response出來: 如果執行時間很長 ,這個response時間就會跟著很長 。 2. 難以追蹤歷史的執行記錄: 因為我們沒有存任何log或是狀態 ,這點是可以再改進的地方 。

Call executable with database and Windows service

改良方式是將task寫到DB ,並由另一個Windows service檢查DB中是否有未執行的task ,若是有則呼叫對應的執行檔執行任務 ,任務完成後複寫DB 。

Copy right@A layman

首先進到MySQL console ,建立新的table以存放Goreplay所需要的參數:

在models資料夾下新增job.go:

Copy right@A layman

job.go的工作為寫入一項新任務, 程式碼如下:

修改routes/webService.go:

接著將原本libs/jobExecuter.go的邏輯改寫為Windows service ,讓Windows service檢查DB中是否有新任務 ,若有新任務就呼叫執行檔即可 。

Use cron job and NSSM to make a Windows service

先安裝jakecoffman/cron ,這個工具的使用方式是在程式中設定排程的時間間隔 ,根據官網 ,時間間隔的格式分成predefined expression以及cron expression:

go get -u github.com/jakecoffman/cron

predefined expression是jakecoffman/cron所預設的一些時間間隔:

Picture originated from https://github.com/jakecoffman/cron

cron expression

Picture originated from https://github.com/jakecoffman/cron

使用方式為先import “github.com/jakecoffman/cron”後 ,在main()加入以下程式碼:

但如果只這樣寫 ,程式將會直接結束 ,必須想辦法將程式停住 ,這樣jakecoffman/cron才可以每隔五分鐘就執行一次任務 ,完整程式碼如下:

到這邊就可以讓應用程式每隔一段時間執行一次任務 ,接著編譯成執行檔:

go build main.go

接著安裝NSSM(Non-Sucking Service Manager) ,可以包裝應用程式成Windows Service ,下載安裝後可以依照以下指令進行操作 ,依序為安裝 ,啟動 ,停止以及移除:

nssm install jobRunner path/cron.exe
nssm start jobRunner
nssm stop ddAuto
nssm remove ddAuto

Summary

謝謝你耐心地讀到Summary,我是Sean HS, 是位軟體工程師。 這片文章是我在研究過程時的筆記,若有錯誤之處,期待您的見解,與您交流討論。

Other topics

中文
Golang
Web Development
Windows Services
Software Development
Recommended from ReadMedium