==========================================
真實面試環境中,被問到的相關問題,感興趣的可以看下
==========================================
1.?這個項目是你獨立完成的嗎?團隊中你的職責是什么?
是的,這個項目是我獨立完成的,從需求分析、系統設計到項目部署都我做的。重點工作包括:
- 使用 C++ 編寫判題核心模塊,實現對用戶代碼的編譯、運行,判題功能
- 搭建了一個簡單的 Web 界面,支持題目提交、實時查看運行的結果
- 也使用 MySQL 管理題目與提交記錄,用makefile腳本完成自動化部署
2. 這個項目的主要目標是什么?為什么要做這個項目??
- 主要目標是搭建一個高性能、穩定、安全的在線評測系統,用于自動評判編程題的提交結果,支持多人并發提交
- ?做這個項目的初衷,一方面是出于我對算法和系統編程的興趣,另一方面我也想通過實踐鍛煉自己在 Linux 系統編程和 C++ 開發方面的能力,所以我就做了一個基于Linux的高性能在線OJ平臺
3. 項目用了哪些技術?為什么選這些技術?
C++ STL 標準庫,
?Boost 標準庫,對文件路徑,文件名字符串進行分割,和根據需要拼接字符串
- ctemplate第三方開源前端網頁渲染庫,為了將我們的題目信息顯示在網頁上
jsoncpp 第三方開源序列化、反序列化庫,因為對用戶提交的請求進行解析時,數據格式應該是json的,如果我手動拼接字符串不僅繁瑣、易錯,還不利于維護。而
jsoncpp
提供了清晰的 API,可以快速構建、解析 JSON 數據結構,提升開發效率,代碼也更穩定易讀jsoncpp
是跨平臺的,開源、輕量,能很好地與 C++ 項目集成,也避免了自己重復造輪子。- ?Ace前端在線編輯器,是為了提供一個高亮、自動縮進、語法提示友好的在線代碼編輯環境,提升用戶在 OJ 平臺上的編程體驗。
對于普通的純文本,Ace 支持多種語言語法高亮(如 C++、Python)、自動補全、主題切換
????????這個項目也考慮到了多進程,多線程的場景,其中網絡庫cpp-httplib就是多線程的,也進行了加鎖解鎖處理?
MySQL C connect,為了將題目信息,用戶記錄存入mysql中
2. 架構與設計類?
1.?項目的整體架構是怎樣的?你是怎么參與設計的?
- 首先設計了項目的宏觀結構,兩個大模塊,CompileServer模塊提供了對提交的代碼進行編譯的服務,OJServer模塊提供在線OJ服務,
- 我在設計CompileSever服務時,先設計編譯模塊,再設計運行模塊,最后在進行了編譯運行,其中引入了第三方庫cpp-httplib,用來發起http和接受http請求,其中數據的發送和接受都使用了json進行序列化/反序列化
- 設計OjServer的時候,使用了MVC模塊,其中oj_mode管理數據的存儲,以及對外提供接口,oj_view引入了ctemplate第三方庫進行網頁渲染,本質就是key-value之前的替換,
oj_central是這個服務的核心,
負載均衡調度,就是加權遍歷所有的主機,并找到最小負載主機,進行服務,它會提供3個接口,一個是得到所有題目,一個是得到某個題目的詳細信息,最后就是判題功能 - 之后設計前端服務時,使用了第三方插件ACE一個編寫代碼的編譯框,后用了JQuery獲取html中的內容,構建json,通過類似信號槽機制借助ajax向后臺發起基于http的json請求,并實現前后端交互
- 最后引入了mysql數據庫,借助第三方工具Navicat?連接數據庫,存儲題目數據,替換之前文件版的存儲數據
2. 模塊之間如何解耦?怎么處理模塊間通信??
模塊解耦方式:
通過 HTTP 接口進行通信:
OJServer
作為主服務,通過 HTTP 請求調用CompileServer
暴露的編譯接口(REST API)CompileServer
編譯完成后返回標準化 JSON 數據(包括編譯是否成功、錯誤信息、可執行文件路徑等)- 這樣設計,兩個模塊通過標準協議通信,無需強依賴對方內部結構,解耦良好。
- 我也定義了統一的數據結構(使用
jsoncpp
處理 JSON)(所有錯誤、狀態都用統一的錯誤碼和消息返回,方便主模塊統一處理)
通信流程(舉例)?
- 用戶提交代碼后,
OJServer
將其打包為 JSON 請求,發送到CompileServer
。
CompileServer 編譯后將結果(是否成功、錯誤信息、可執行路徑)通過 HTTP 響應返回給 OJServer,OJServer 再進入執行與判題流程。?
3. 用到了什么設計模式?為什么用??
單例模式
使用場景:
- 項目中的日志模塊、配置加載模塊使用了單例模式,確保全局只有一個實例,節省資源并統一管理。?
為什么用:?
- 日志系統或配置對象需要被多個模塊頻繁調用,但又不希望重復創建,單例模式能保證線程安全的同時節省資源?
3. 測試與部署類
1. 項目是怎么測試的?有沒有寫自動化測試??
我在項目開發過程中有進行接口測試,主要使用 Apifox 工具對 OJServer
和 CompileServer
暴露的接口進行了自動化測試
- 提交不同語言、正確與錯誤的代碼,驗證編譯結果是否準確返回?
- 測試如代碼為空、非法語言類型、編譯失敗等邊界情況?
- 用 Apifox 批量模擬多用戶并發提交,觀察系統響應和穩定性
為什么使用 Apifox:?
- Apifox 支持接口文檔、調試和自動化測試一體化?
- 主要也有使用簡單的特點?
是否寫了測試代碼:?
- ?編譯模塊核心邏輯(如
CompileTask
)我也寫了部分單元測試代碼,驗證編譯參數拼接、錯誤碼返回邏輯是否正確。
2. 怎么部署上線的?本地/服務器端用了什么環境??
項目最終部署在 Linux 服務器上運行,主要采用的是手動部署 + 可執行文件運行的方式。
使用 Makefile 編譯生成
compile_server
和oj_server
可執行文件我在服務器上通過
./compile_server 8081
直接啟動編譯服務,監聽 8081 端口
同理,./oj_server?
8081
模塊也監聽一個獨立端口,并啟動在線OJ服務
為什么這樣部署:?
- 相較于復雜的容器部署,這種方式簡單高效,便于調試與快速上線,同時也適合我的項目開發階段。?
4. 反思與改進類?
1. 如果重新做一次,有什么地方你會改進?
使用 Docker替代手動項目部署
- 之前項目是通過 手動部署 + 可執行文件運行的方式
- 其實可以使用Docker 容器進行項目的部署,會更安全,
- 也會讓每次提交自動創建臨時容器執行代碼,更安全、更易于資源回收和管理,
- 也方便后期支持多語言環境
增加前端用戶體驗優化
目前前端使用的是 Ace 編輯器,功能上滿足需求,但界面較為基礎簡單。如果重做,我會:
加入代碼運行狀態的 loading 動畫、歷史提交記錄
支持自動保存代碼草稿、鍵盤快捷提交
整體 UI 使用 Vue?等前端框架提升交互體驗
- 基于注冊和登錄的錄題功能
- 業務擴展:比如自己寫個論壇,接入在線OJ中
- 把編譯服務部署在docker中
- 將cpphttplib改成rest_rpc庫
- 判斷一道題目正確之后,自動下一道題目
- 將導航欄中的功能一個一個的都實現一下
2. 從這個項目中你學到了什么??
- 我掌握了 Linux 下的系統編程,實踐了 C++ 工程化開發,熟悉了模塊化設計、Makefile 構建、jsoncpp 第三方庫集成等內容
- 通過設計
CompileServer
和OJServer
兩個模塊,我學會了如何通過 HTTP + JSON 實現模塊解耦與通信 - 從開發、測試(用 Apifox 自動化測試)、部署上線(Linux 環境部署)、日志調試,我第一次完整地實踐了一個后端服務從設計到上線的全過程
5.?技術細節類?
1. 你在項目中遇到過哪些技術難題?怎么解決的?
問題一:如何讓這個OJ平臺成為一個高性能的平臺,支持用戶的高并發訪問
OJServer
和 CompileServer
是完全解耦的,通過 HTTP 接口通信,可以分布式部署在不同機器上,便于資源調度和獨立擴展。
我將編譯模塊(CompileServer
)做成可水平擴展的獨立服務,部署了多個后端編譯節點,然后通過 負載均衡(如 Nginx / 自寫調度邏輯) 將用戶提交分發到不同主機進行編譯,避免一個主機負載太高的情況
在我設計的這個負載均衡模塊,oj_server應該選擇后端的負載最低的那個compile_server,
- 具體的操作就是循環遍歷,找到權重也就是負載最低的那個compile_server
如果要進一步提高效率的話,可以試試任務隊列 + 線程池 ,實現異步處理用戶提交,提升系統處理速度
問題二:測試運行模塊時出現了死循環?
- 一般的測試環境都是沒什么問題的,
- 但后來發現是惡意程序死循環了,不停消耗CPU資源 ,?
- 解決辦法是:添加進一步的資源約束
- 在json string數據中添加上資源限制(setrlimit)的屬性 ,資源不足或cpu超時,導致OS終止進程,直接發送對應的信號終止的 ?
問題三:用戶代碼運行的安全隔離?
用戶提交的代碼是我無法控制的,比如死循環、惡意訪問文件系統等。如果直接運行在服務器上,非常不安全,容易造成系統崩潰或泄露敏感信息。?
我采用了 fork + exec
啟動子進程,讓子進程進行判斷,這樣就不會影響原來的服務了,然后結合setrlimit()
控制 CPU 時間、內存、文件大小,主要目的就是代碼在受限環境中運行
2. 性能優化做過嗎?具體做了哪些優化?效果如何??
原先編譯和輸出結果都寫入臨時文件,I/O 開銷較大。
優化:
改用內存管道或共享內存傳遞編譯輸出 / 執行結果
減少中間文件寫入次數,僅必要時存入磁盤文件中,
3. 你個系統,最多支持多少并發訪問量?
????????在實際開發階段,我用 Apifox 模擬了多用戶并發提交代碼的場景,雖然沒有用專業壓測工具,但結合測試結果和架構設計,我估算當前系統可以穩定支持 100~200 個并發請求。?