隨着時代的發展,OJ已經真正成爲測評工具,其作用不再侷限爲ACM備戰,還有老師檢測學生能力、學生入學考試、能力評測(例如ZJU的PAT)、找工作刷題和麪試(例如牛客)等,而目前OJ的開源框架也越來越多,但是很多OJ都是基於HUSTOJ進行定製或者二次開發。
無論是什麼方法,在OJ的衆多問題中,有一個就是:性能問題。說實話,我在一些OJ羣裏,經常會看到有人問:1核1G的機器,可以同時判多少題目?可以有多少人同時用?如果比賽,大約有多少人需要多高性能的機器?那麼"判題姬"是否只能存在傳統的宿主機中,能否通過其他方式煥發新的生命力?
有一種方法,就是和現有的雲函數進行結合。
簡單思路
通過雲函數實現在線編程的思路基本有兩個:
- 每個用戶的代碼建立一個函數,用後刪除;
- 每個語言建立一個函數,用戶傳遞代碼,每次執行;
這兩種方法,第一種無疑是簡單的,但是目前對於很多雲函數服務商來說,函數數量有一定限制,而且每次執行這個操作相對比較繁瑣。
所以,本文采用第二種策略,建立一個函數,每次執行,用戶傳入代碼,系統執行,返回結果。
基本實現
代碼寫入系統:
def WriteCode(code):
try:
with open("/tmp/mytest.py", "w") as f:
f.write(code)
return True
except Exception as e:
print(e)
return False
執行代碼:
def RunCode(input_data=None):
child = subprocess.Popen("python /tmp/mytest.py", stdin=input_data, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True, shell=True)
error = child.stderr.read()
output = child.stdout.read()
return error, output
代碼和用例處理邏輯:
def main_handler(event, context):
if WriteCode(event["code"]):
try:
temp_list = []
for eve in event["input"]:
result = RunCode()
temp_list.append({"error":result[0].decode("utf-8"),"result": result[1].decode("utf-8"), "exception":""})
return json.dumps(temp_list)
except Exception as e:
return json.dumps({"error":"","result": "", "exception":str(e)})
用戶在傳入數據的時候,需要注意事件爲:
{
"code": "print('hello')",
"input": ["111","22222"]
}
這樣就可以在每次請求的時候把代碼傳入(code),每個測試用例的input就是input內容。
本題輸出結果:
此時,就實現了Python判題機的基本功能,此時通過騰訊云云API:
(https://cloud.tencent.com/document/api/583/17243)實現參數傳入,通過
Explorer(https://console.cloud.tencent.com/api/explorer?Product=scf&Version=2018-04-16&Action=Invoke&SignVersion=)
進行代碼撰寫,直接接入自己的OJ就可以了。
One More Thing
雖然這是一個簡單的代碼執行工具,但是實際上這個小工具可以在很多地方有着額外的應用。本文我只是再次只是拋磚引玉,例如我們做了一個OJ,如果在本地跑代碼可能性能和安全性都會受到挑戰,那麼此時,放入騰訊云云函數中,就會簡單、安全、便捷的多,最主要的是騰訊雲的函數調用免費額度很高。
此外,如果臨時舉辦比賽,也不用費心費力擴容縮容,只要有雲函數,後端的主要壓力,都傳給Serverless搞定,這也算是發揮了雲函數的一個優勢和特性。
那麼,除了在OJ中使用的用途,它還有啥用?簡單舉兩個例子:
- Anycodes、Codepad這些在線編程網站,之前很多人就問是如何實現的,試想一下,通過這個策略,是不是很好實現了在線編程?確切說,只需要一個前端,就可以實現在線寫代碼的一個網頁。
- 菜鳥教程這些網站,可以看代碼然後點擊運行,很炫酷的功能,很多小夥伴也想往自己博客增加一個類似的功能,也可以基於這個方法來實現。
作者介紹:
劉宇,騰訊雲Serverless團隊後臺研發工程師。畢業於浙江大學,先後參與騰訊云云函數產品研發、自動擴縮容、CLI等模塊建設以及社區相關工作。本文轉載自微信公衆號 ServerlessCloudNative(ID:ServerlessGo)
《Serverless 實踐系列(一):如何通過 SCF 與自然語言處理爲網站賦能》
《Serverless 實踐系列(二):爲 Python 雲函數打包依賴》
《Serverless 實踐系列(四):網站監控腳本的實現》