分布式计算模拟

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
在这里插入图片描述
在这里插入图片描述
以上就是我对分布式计算的简单模拟,希望这篇文章能够加深你对分布式计算的理解

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值