1. 概念
分布式计算是一种计算方法,和集中式计算是相对的。
随着计算技术的发展,有些应用需要非常巨大的计算能力才能完成,如果采用集中式计算,需要耗费相当长的时间来完成。
分布式计算将该应用分解成许多小的部分,分配给多台计算机进行处理。这样可以节约整体计算时间,大大提高计算效率。
2. 简单的分布式计算框架
想要实现分布式计算,首先我们至少需要两个进程,一个负责逻辑的准备和逻辑的准备,一个负责执行计算,如小图所示(我们以 JVM 进程为例)
这样的计算架构其实就和 client/server 这种架构设计类似,我们可以使用 socket 编程达到效果。
由此我们就可以很容易的写出分布式的架子:
Driver:
object Driver {
def main(args: Array[String]): Unit = {
val client = new Socket("localhost", 9999)
val out: OutputStream = client1.getOutputStream
out.write(2)
out.flush()
println("发送数据成功")
out.close()
client.close()
}
}
Executor:
object Executor {
def main(args: Array[String]): Unit = {
val server = new ServerSocket(9999)
println("服务器启动,等待接收数据")
val client: Socket = server.accept()
val in: InputStream = client.getInputStream
val i: Int = in.read()
println("接收到客户端发送的数据:" + i)
in.close()
client.close()
server.close()
}
}
运行结果:
3. 带有计算任务的分布式计算框架
在 Driver 向 Executor 发送数据的同时,我们也可以将对应的计算任务发送过去,Task 就是一个简单的任务
Task:
/**
* 在网络中发送就必须实现序列化
*/
class Task extends Serializable {
// 数据
val datas = List(1, 2, 3, 4)
// 计算逻辑
val logic : (Int)=> Int = _ * 2
// 计算
def compute() : List[Int] = {
datas.map(logic)
}
}
Driver:
object Driver {
def main(args: Array[String]): Unit = {
val client = new Socket("localhost", 9999)
val out: OutputStream = client.getOutputStream
val outObj = new ObjectOutputStream(out)
val task = new Task
outObj.writeObject(task)
outObj.flush()
outObj.close()
client.close()
}
}
Executor:
object Executor {
def main(args: Array[String]): Unit = {
val server = new ServerSocket(9999)
println("服务器启动,等待接收数据")
val client: Socket = server.accept()
val in: InputStream = client.getInputStream
val inObj = new ObjectInputStream(in)
val task: Task = inObj.readObject().asInstanceOf[Task]
val list: List[Int] = task.compute()
println("计算结果为:" + list)
inObj.close()
in.close()
client.close()
server.close()
}
}
运行结果:
4. 多 Executor 的分布式计算框架
在实际生产环境中的数据量往往是庞大的,如果此时我们只用一个 Executor 来处理如此多的数据,可能会导致响应时间变慢,这个时候我们可以使用多个 Executor 来处理数据,因此就有了如下的模型
在计算过程中,我们需要将数据拆分,因此可以使用 SubTask 作为子任务存储数据和计算逻辑
Task:
class Task extends Serializable {
// 数据
val datas = List(1, 2, 3, 4)
// 计算逻辑
val logic : (Int)=> Int = _ * 2
}
SubTask:
class SubTask extends Serializable {
var datas: List[Int] = _
var logic: (Int)=>Int = _
def compute() = {
datas.map(logic)
}
}
Driver:
object Driver {
def main(args: Array[String]): Unit = {
val client1 = new Socket("localhost", 9999)
val client2: Socket = new Socket("localhost", 8888)
val task = new Task
val subTask1: SubTask = new SubTask()
subTask1.datas = task.datas.take(2)
subTask1.logic = task.logic
val out1: OutputStream = client1.getOutputStream
val outObj1: ObjectOutputStream = new ObjectOutputStream(out1)
outObj1.writeObject(subTask1)
outObj1.flush()
outObj1.close()
out1.close()
client1.close()
val subTask2: SubTask = new SubTask()
subTask2.datas = task.datas.takeRight(2)
subTask2.logic = task.logic
val out2: OutputStream = client2.getOutputStream
val outObj2: ObjectOutputStream = new ObjectOutputStream(out2)
outObj2.writeObject(subTask2)
outObj2.flush()
outObj2.close()
out2.close()
client2.close()
}
}
Executor1:
object Executor {
def main(args: Array[String]): Unit = {
val server = new ServerSocket(9999)
println("服务器启动,等待接收数据")
val client: Socket = server.accept()
val in: InputStream = client.getInputStream
val inObj: ObjectInputStream = new ObjectInputStream(in)
val task: SubTask = inObj.readObject().asInstanceOf[SubTask]
val result: List[Int] = task.compute()
println("接收客户端[9999]发送的数据:" + result)
inObj.close()
in.close()
client.close()
server.close()
}
}
Executor2:
object Executor2 {
def main(args: Array[String]): Unit = {
val server = new ServerSocket(8888)
println("服务器启动,等待接收数据")
val client: Socket = server.accept()
val in: InputStream = client.getInputStream
val inObj: ObjectInputStream = new ObjectInputStream(in)
val task: SubTask = inObj.readObject().asInstanceOf[SubTask]
val result: List[Int] = task.compute()
println("接收客户端[8888]发送的数据:" + result)
inObj.close()
in.close()
client.close()
server.close()
}
}
运行结果:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201221145402134.png
以上就是我对分布式计算的简单模拟,希望这篇文章能够加深你对分布式计算的理解