你好 Satckoverflow!
TLDR 我想重新創建https://github.com/KorayGocmen/scheduler-worker-grpc而不在作業人員上進行埠轉發。
我正在嘗試建立一個有競爭力的編程裁判服務器來評估提交的內容,作為我學校的一個專案,我在那里向孩子們教授編程。
因為評估計算量很大,我希望有多個作業節點。調度程式將接收提交并將它們分發給作業節點。為了便于作業人員部署(因為它經常會發生變化),我希望作業人員能夠訂閱調度程式,從而成為作業人員并接收作業。
作業人員可能與調度程式不在同一個網路上 作業人員駐留在 VM 中(也許稍后將被移植到 docker,但目前它存在問題)。
調度程式應該能夠知道作業人員的資源使用情況,向作業人員發送不同型別的作業并接收結果流。
我目前正在考慮使用 grpc 來解決我對作業人員和調度程式之間通信的要求。
我可以創建多個調度程式服務方法,例如:
- 注冊作業者,接收作業流
- 流式傳輸作業結果,一無所獲
- 定期流式傳輸作業狀態,什么也不接收
但是,我更喜歡以下內容,但不知道是否有可能:
- 調度器 GRPC api:
- 注冊一個作業人員(使作業人員 GRPC api 可供調度程式使用)
- 工人 GRPC api:
- 開始作業(回傳作業狀態流)
- 取消作業???
- 獲取資源使用情況
如果連接丟失,作業人員應自動取消注冊。
所以我的問題是......如果worker在沒有埠轉發的NAT后面,是否可以創建一個可以注冊到調度程式以供以后使用的grpc worker api?
其他可能不必要的資訊:
更糟糕的是,我有多種完全不同型別的作業(流式傳輸互動式控制臺,針對準備好的測驗用例執行代碼)。我可能只是為不同的作業創造不同的工人。
有時作業涉及在本地檔案系統(最大 500 MB)上擁有通常保存在調度程式附近的大檔案,因此我想將作業發送給已經從調度程式下載特定檔案的作業人員。否則,將大檔案下載到其中一名作業人員上。在作業人員上同時擁有所有檔案需要超過 20 GB,因此我想避免它。
一個作業人員可以同時運行多個作業(最多 16 個)。
我正在撰寫系統。
uj5u.com熱心網友回復:
只要只有作業人員啟動連接,您就不必擔心 NAT。gRPC 支持任一方向(或兩者)的流式傳輸。這意味著您的所有需求都可以僅使用調度程式上的一臺服務器來實作;調度程式無需連接回作業人員。
根據您的描述,您的服務可能如下所示:
syntax = "proto3";
import "google/protobuf/empty.proto";
service Scheduler {
rpc GetJobs(GetJobsRequest) returns (stream GetJobsResponse) {}
rpc ReportWorkerStatus(stream ReportWorkerStatusRequest) returns (google.protobuf.Empty) {}
rpc ReportJobStatus(stream JobStatus) returns (stream JobAction) {}
}
enum JobType {
JOB_TYPE_UNSPECIFIED = 0;
JOB_TYPE_CONSOLE = 1;
JOB_TYPE_EXEC = 2;
}
message GetJobsRequest {
// List of job types this worker is willing to accept.
repeated JobType types = 1;
}
message GetJobsResponse {
string jobId = 0;
JobType type = 1;
string fileName = 2;
bytes fileContent = 3;
// etc.
}
message ReportWorkerStatusRequest {
float cpuLoad = 0;
uint64 availableDiskSpace = 1;
uint64 availableMemory = 2;
// etc.
// List of filenames or file hashes, or whatever else you need to precisely
// report the presence of files.
repeated string haveFiles = 2;
}
其中大部分是偏好問題(oneof例如,您可以使用列舉來代替列舉),但希望很明顯,從客戶端到服務器的單個連接足以滿足您的要求。
維護可用工人的集合非常簡單:
func (s *Server) GetJobs(req *pb.GetJobRequest, stream pb.Scheduler_GetJobsServer) error {
ctx := stream.Context()
s.scheduler.AddWorker(req)
defer s.scheduler.RemoveWorker(req)
for {
job, err := s.scheduler.GetJob(ctx, req)
switch {
case ctx.Err() != nil: // client disconnected
return nil
case err != nil:
return err
}
if err := stream.Send(job); err != nil {
return err
}
}
}
基礎教程包括所有型別流的示例,包括 Go 中的服務器和客戶端實作。
至于注冊,這通常意味著創建某種憑證,作業人員在與服務器通信時將使用該憑證。這可能是一個隨機生成的令牌(服務器可以使用它來加載相關的元資料),或者一個用戶名/密碼組合,或者一個 TLS 客戶端證書,或類似的。設定作業人員時,詳細資訊將取決于您的基礎架構和所需的作業流程。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/524281.html
標籤:去tcpgrpc
