这是我参与「第四届青训营 」笔记创作活动的第16天。
代码逻辑
- 原配置文件样式
{
"configall": [
{
"operatpr":"map",
"concurrent":"1"
}
]
}
一、 初始化(在两节点主程序启动前执行):运行一次即可
- 读取配置文件信息,生成任务信息存入配置文件中。
- 初始化后配置文件样式
{ "configall": [ { "operatpr":"map", "concurrent":"1" } ], "tasks":[ { "tasktype":"map", "taskname":"map1", "func":"org.team3090.simple.Worker.Map" //不必须,本地调用类方法。 } ] }
二、 两节点各自主程序:同时运行
- 读取配置文件的总任务数记录a:tasks数组的大小
- a依次递减,根据奇偶区分触发哪个节点上的提交任务方法。
- 提交作业:Executor.submitJob(String taskname,int tasknow)
- 创建rpc服务,将创建的服务端地址存入配置文件中对应tasks数组中task的内部信息。
- 从source算子开始创建,避免接下来建立客户端的线程循环等待过久。
- 更新配置文件:*由任务数组下标拼接而成,依次递减,防止相同造成冲突。
{ "configall": [ { "operatpr":"map", "concurrent":"1" } ], "tasks":[ { "tasktype":"map", "taskname":"map", "func":"org.team3090.simple.Worker.Map", "local":"节点2:990*" } ] } - 创建线程准备执行算子任务:开rpc客户端监听上一算子的rpc服务端,接收数据。子线程完成工作如下:
- 监听配置文件中上一算子的rpc服务端是否创建完成:不断读配置文件检测 上一算子任务的"local"key是否存在。(更新配置文件的tasks.task.source (上一算子的 local 地址))
- 注:监听用while(bzw),所以只有在所需rpc服务器创建后才会申请建立客户端连接,所以不用考虑没建立服务器就创建客户端连接,防止因此导致报错。
- 注:对于一对多,多对一情况:map->多个reduce->sink
- sink算子任务需创建(reduce并行度)个客户端分别连接reduce*的服务端。
- 检测到所需服务端地址更新后创建客户端连接,算子工作,准备接收数据。
- 更新配置文件(可省):可不更新source值。
{ "configall": [ { "operatpr":"source", "concurrent":"1" } ], "tasks":[ { "tasktype":"map", "taskname":"map1", "func":"org.team3090.simple.Worker.Map", "local":"节点2:990*", "source":"节点1:990*+1" //不必须记录,在key存在后,可同时记录到本地,供客户端建立连接使用。 } ] } - 将收到的数据进行处理后,发送到本算子任务的rpc服务端,供监听该服务端的下一算子任务的rpc客户端读取。
- 监听配置文件中上一算子的rpc服务端是否创建完成:不断读配置文件检测 上一算子任务的"local"key是否存在。(更新配置文件的tasks.task.source (上一算子的 local 地址))
- 创建rpc服务,将创建的服务端地址存入配置文件中对应tasks数组中task的内部信息。
- 两节点主程序需要保持运行,防止主线程关闭导致算子子线程也随之运行结束。