項目鏈接: 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,防止遠程代碼惡意行爲