用gin+xorm+docker編寫Online Judge後端

項目鏈接: https://github.com/Myriad-Dreamin/core-oj/tree/develop

思路:

  • 將worker分爲兩種, compiler & judger
  • compiler負責隔離編譯環境,設置編譯資源限制,權限限制
  • judger負責隔離運行環境,sandboxize
  • 設計結構體管理compilers/judgers
  • gin-server只是作爲core的測試服務器,可以利用compiler/judger的daemon自行編寫服務

compiler

  • daemon與compilers之間用grpc通信。
  • compiler的資源受到daemon管理,當compiler超時無反應時,直接摧毀compiler重建一個新的compiler,並向上級報告嚴重錯誤
  • compiler的language config可自定義,暴露的接口可以定義新的編譯類型。

judger

  • 隔絕所有網絡環境。
  • daemon與judgers之間用unix-socket通信。
  • 資源限制與judger類似。
  • 使用docker的用戶映射,docker根用戶root爲物理機普通用戶,除了共享容器的完全訪問權限,沒有其他任何權限。judger開闢子進程運行程序時,改變其uid-gid爲運行時用戶worker。worker只有目標程序的100權限,沒有judger以及物理機其他的任何權限。

docker configuration

  • 採用alpine最小鏡像
  • 支持c/c++/java/python2/python3的編譯及運行。
  • c/c++編譯器爲g++,java sdk爲openjdk8,python2,3版本分別爲2.7,3.7。
  • 單個compiler佔用外存273M,單個judger佔用外存197M。

problem/code api

problem orm模型如下。

// Problem example
type Problem struct {
	ID       int    `xorm:"not null pk autoincr 'id'"`
	Name     string `xorm:"'name'"`
	OwnerUID int    `xorm:"owner_uid"`
}

OwnerUID爲預設的用戶uid。
大部分配置位於path/to/problem/Problem.ID/problem_config.xxx中。
problem-config支持yaml/xml/toml/json。
yaml的配置示例如下:

judge:
  judge-type: acm
  tasks:
    - name: task
      time-limit: 1000000000
      memory-limit: 262144
      input-path: /codes/
      output-path: /codes/
special-judge:
  enable: true
  language-type: c++11
  file-path: /spj.cpp

查看源碼: https://github.com/Myriad-Dreamin/core-oj/blob/develop/problem-config/problem-config.example.yml
judge支持多種類型acm (目前只支持acm類型,未來可能支持ioi, interactive類型等),可以將問題分爲多個子類型。每個子類型允許設置時間限制/空間限制,輸入/輸出路徑。
special judge支持多種語言類型的special judge,目前只支持testlib.lib(c++)

Example

目前項目編寫了一個使用core編寫Online Judge後端的示例。
查看源碼: https://github.com/Myriad-Dreamin/core-oj/tree/develop/gin-server

支持的api接口如下:

codeService.Get /code/:id@GET

查詢code信息

codeService.GetContent /code/:id/content@GET

查詢code代碼

codeService.GetResult /code/:id/result@GET

查詢code judge的結果

codeService.PostForm /code/postform@POST

添加code

codeService.Delete /code/:id@DELETE

刪除code

problemService.Get /problem/:id@GET

獲取problem信息

problemService.PostForm /problem/postform@POST

添加problem

problemService.Delete /problem/:id@DELETE

刪除problem

problemService.Stat /problemfs/:id/stat@GET

查詢problem所屬文件夾的文件信息

problemService.Mkdir /problemfs/:id/mkdir@PUT

查詢problem所屬文件夾的文件信息

problemService.Ls /problemfs/:id/ls@GET

查看problem所屬文件夾下某文件夾所有文件

problemService.Read /problemfs/:id/read@GET

查看problem所屬文件夾的文件內容

problemService.Write /problemfs/:id/write@POST

上傳文件到problem所屬文件夾

problemService.Writes /problemfs/:id/writes@POST

上傳多個文件到problem所屬文件夾

problemService.Zip /problemfs/:id/zip@POST

上傳壓縮包到problem所屬文件夾並解壓

problemService.ReadConfigV2 /problemfs/:id/config@GET

讀取problem-config

problemService.PutConfig /problemfs/:id/config@PUT

修改problem-config

注意事項:

  • Alpine可運行文件需要經過linux,i386交叉編譯,否則可能無法識別
  • 合理配置Docker,防止遠程代碼惡意行爲
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章