Alchemi的实现机制初探

本文介绍了基于.NET的计算网格Alchemi的实现与使用。阐述其基本编程模式,包含从GThread继承类、用GApplication实现主程序等步骤。还剖析了Alchemi的运行机制,如通过Remoting实现,代码和数据序列化后部署到远程计算机,以达分布式计算目的。

前边的文字介绍了基于.net的计算网格(Computing Grid)的实现Alchemi,并对其使用做了简单的介绍。个人一直对其不同于其他Grid框架的基于Thread的实现很感兴趣,通过细粒度的Thread,应用Alchemi可以比较容易的实现分布算法。今天比较闲暇,因此对其源码做了简单的浏览,结合其文档,大概得出以下认识。

Alchemi的基本编程模式如下:

第一,从GThread继承自己的GThread类,实现具体的计算代码;
第二,使用GApplication实现主程序:
(1)通过GApplication.Threads.Add添加线程;
(2)通过GApplication.Connection初始化连接和Grid平台;
(3)GApplication.Start启动计算;
(4)必须订阅事件以获知线程结束和计算结束。

一个Alchemi必须包含以下部分:User, Manager, Executor。User通过继承GTread类创建自己的执行代码,通过GApplication的实例连接到Manager来执行代码。在初始化时,需要指定Thread运行需要的任何数据、Dll等信息,Alchemi负责把这些数据或第三方代码部署到Excutor所在的计算机,在运行结束后删除之。对于一般的.net程序,则简单的使用
App.Manifest.Add(new ModuleDependency(typeof(PrimeNumberChecker).Module));
类似的语句将本程序集添加即可。

20050909001.jpg

Manager提供透明的计算服务,一个Manager可以有数个User来使用,同时,Manager将任务分配给自己的Executor来完成任务。这些任务在Manager上存储于SQL Server或者MSDE。Manager同时验证User是否合法用户。

Excutor提供计算服务,在计算之前,任务通过先进先服务的原则依次获得计算。

Alchemi通过.net的Remoting机制来实现。上边提到的User, Manager, Executor分别在GManager,  GExecutor, GApplication中实现,其继承自GNode,其中实现了基本的通信机制。一个Grid程序的执行过程如下:

首先,用户创建继承自GTread的类,创建GApplication的实例,所有执行代码需要的数据被加载到DependencyCollection中,FileDependencyCollection是一个继承自ReadOnlyCollectionBase的一个集合类。而继承自GTread的类的实例线程则加载到ThreadCollection中。ThreadCollection是继承自CollectionBase的一个自定义Collection,作为保存GTread实例的容器。

20050909002.jpg

接着,GApplication序列化执行Thread需要的代码和数据,并将其发送到Manager所在计算机,并持久化到硬盘,线程状态等信息则保存到SQL Server数据库中。以下是GApplication的Start的代码:

public void Start()
{
      ...
     
      Init();
      lock(_Threads)
      {
            foreach (GThread thread in _Threads)
            {
                  if (thread.Id == -1)
                  {
                        SetThreadOnManager(thread);
                  }
            }
      }
     
      ...
}

其中首先通过Init初始化系统,然后遍历Threads集合,通过SetThreadOnManager方法将其发送到Manager,代码如下,关键在于Manager.Owner_SetThread方法,其中最后一个参数将需要的数据、代码等序列化。

private void SetThreadOnManager(GThread thread)
{
      thread.SetId(++_LastThreadId);
      thread.SetApplication(this);

      Manager.Owner_SetThread(
            Credentials,
            new ThreadIdentifier(_Id, thread.Id, thread.Priority),
            Utils.SerializeToByteArray(thread));
}

在Manager的Owner_SetThread方法中,Thread被添加到MApplicationCollection集合中。

将线程发送给Manager后,GApplication实例通过订阅GThreadFinish等事件返回执行结果。Manager通过MApplicationCollection和MExecutorCollection集合保存其用户和Thread信息。通过Owner_CreateApplication和Owner_SetApplicationManifest来完成用户需求的任务的创建,在Owner_SetThread方法中完成Thread的创建。对于有空闲的dedicated的Executor,可以直接连接并执行之,对于没有的情况下,则保存在集合中,由Executor反过来调用来执行Thread。

20050909003.jpg

在Excutor中,执行Thread的方法在ExecuteThreadInAppDomain中,其中首先创建应用程序域,然后通过以下语句执行之:

首先从Manager获取Thread:
byte[] rawThread = Manager.Executor_GetThread(Credentials, _CurTi);
GridAppDomain gad = (GridAppDomain) _GridAppDomains[_CurTi.ApplicationId];
     
然后执行之,并设置完成状态:
byte[] finishedThread = gad.Executor.ExecuteThread(rawThread);
Manager.Executor_SetFinishedThread(Credentials, _CurTi, finishedThread, null);

其中的gad.Executor定义在AppDomainExecutor中,ExecuteThread方法如下:

GThread gridThread = (GThread) Utils.DeserializeFromByteArray(thread);
gridThread.SetWorkingDirectory(AppDomain.CurrentDomain.SetupInformation.PrivateBinPath);
gridThread.Start();
return Utils.SerializeToByteArray(gridThread);

首先从数据中重建GThread类,然后设置目录,运行,最后序列化回为数组流。其中的序列化使用的是.net的BinaryFormatter。

对于non-dedicated的Thread,通过StartNonDedicatedExecuting(i),设置一个i参数来完成间隔一定时间从Manager获取Thread来调用。

这样,我们对Alchemi的运行机制做了一个简单的剖析,文中肯定存在不少问题和错误,欢迎指正和讨论。了解一个系统的内部实现,一方面可以很好的应用之,另一方面也可以学习其设计思想,应用在我们的项目中。对于Alchemi,个人觉得其核心思想很简单,就是通过一定机制,将执行代码和数据序列化,然后临时部署到远程计算机,然后启动之,达到分布式计算的目的。与一般的远程调用机制比较,一般的远程调用是调用远程计算机上存在的程序,而Alchemi是将代码先部署到远程计算机,然后在执行之。

转载于:https://www.cnblogs.com/maweifeng/archive/2005/09/09/233059.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值