为了账号安全,请及时绑定邮箱和手机立即绑定

没有端口转发的调度程序-工作集群

没有端口转发的调度程序-工作集群

Go
开满天机 2023-03-07 16:54:11
TLDR 我想重新创建https://github.com/KorayGocmen/scheduler-worker-grpc而无需对工作人员进行端口转发。我正在尝试建立一个有竞争力的编程评判服务器来评估提交的内容,作为我学校的一个项目,我在那里教孩子们编程。因为评估的计算量很大,所以我希望有多个工作节点。调度程序将接收提交并将它们分发给工作节点。为了便于工人部署(因为它会经常变化),我希望工人能够订阅调度程序,从而成为一名工人并接受工作。worker 可能与调度程序不在同一个网络上 + worker 驻留在 VM 中(也许稍后会移植到 docker 但目前存在问题)。调度器应该能够知道 worker 的资源使用情况,向 worker 发送不同类型的作业并接收结果流。我目前正在考虑使用 grpc 来解决我对工作人员和调度程序之间通信的要求。我可以创建多个调度程序服务方法,例如:注册工人,接收工作流流作业结果,什么也收不到定期流工作状态,什么也没有收到但是我更喜欢以下但idk是否可能:调度器 GRPC api:注册一个工作人员(使工作人员 GRPC api 可用于调度程序)工人 GRPC api:开始工作(返回工作状态流)取消工作???获取资源使用情况如果连接丢失,worker 应该自动注销。所以我的问题是...是否可以创建一个 grpc worker api,如果该 worker 在没有端口转发的情况下位于 NAT 后面,则可以将其注册到调度程序以供以后使用?其他可能不必要的信息:更糟糕的是,我有多种完全不同类型的工作(流式传输交互式控制台,针对准备好的测试用例执行代码)。我可能只是为不同的工作创建不同的工人。有时作业涉及在本地文件系统(最多 500 MB)上有大文件,这些文件通常保存在调度程序附近,因此我想将作业发送给已经从调度程序下载特定文件的工作人员。否则将大文件下载到其中一名工人身上。在工作人员上同时拥有所有文件将占用超过 20 GB,因此我想避免它。一个 worker 可以同时运行多个作业(最多 16 个)。我正在写系统。
查看完整描述

1 回答

?
MMMHUHU

TA贡献1834条经验 获得超8个赞

只要只有工作人员发起连接,您就不必担心 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 客户端证书,或类似的。详细信息将取决于您的基础设施和设置工作人员时所需的工作流程。


查看完整回答
反对 回复 2023-03-07
  • 1 回答
  • 0 关注
  • 78 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信