搜索
您的当前位置:首页云计算的关键技术与应用实例

云计算的关键技术与应用实例

来源:智榕旅游
云计算的关键技术与应用实例.txt世上有三种人:一是良心被狗吃了的人,二是良心没被狗吃的人,三是良心连狗都不吃的人。︶﹋丶 爱情是个梦,而我却睡过了头﹌第一篇从并行计算到云计算

第1章并行计算与云计算................ 2

1.1 并行计算到云计算的演变...................... 2 1.2 云计算需要定义吗?....... 4

1.3 云计算是否是新瓶装旧酒...................... 5 1.4 MPI与Hadoop,不同学科 学者的选择...... 6

1.5 云计算与浏览器..................... 8

第2章MPI并行计算环境的建立..................... 10 2.1 配置前的准备工作.......... 10 2.2 挂载NFS文件系统......... 11 2.3 配置ssh实现MPI节点间

用户的无密码访问.......... 12

2.4 安装MPICH2......................... 12 2.5 建立并行计算环境时的 注意事项......... 14

第3章并行计算时代的程序设计方法....... 15

3.1 最简单的并行程序.......... 15

3.2 获取进程标志和机器名......................... 18 3.3 有消息传递功能的并行程序........... 20 3.4 Monte Carlo法在并行程序设计 中的应用......... 23 3.5 并行计算中节点间的 Reduce操作. 25

3.6 用MPI的6个基本函数实现 Reduce函数功能................ 28 3.7 计算与通信的并行.......... 30 3.8 节点间自定义复杂数据 结构的传输.. 34

3.9 MPI与MySQL数据库的 结合应用......... 37

3.10 设计MPI并行程序时的

注意事项..... 41

第4章从MPI走向云计算........... 43 4.1 MPI没有分布式文件系统支持.... 43

4.2 MPI无法应对节点的失效.................. 44 4.3 假如用MPI来构建云计算系统... 44 第二篇云计算的关键技术

第5章Map/Reduce是云计算的选择吗..... 48 5.1 Map/Reduce跨越50年的

历史....................... 48

5.2 实现Map/Reduce的C语言实例. 49

5.3 采用MPI实现并行化的

Map/Reduce功能................ 51 第6章Hadoop技术.. 58

6.1 Hadoop与MPI在数据处理上的 对比....................... 58 6.2 Hadoop的主从式结构. 59

6.2.1 主从式文件系统HDFS....... 59 6.2.2 主从式计算系统 Map/Reduce.......... 60

6.2.3 文件分块策略分析.................... 61 6.3 Hadoop文件系统HDFS的 前辈GFS......... 64

6.4 构建云文件系统需要解决的 关键问题......... 66

6.5 云计算不相信节点服务器.................. 67 6.6 揭密云计算架构下的典型

服务器——Google服务器................. 68 6.6.1 Google服务器概述................... 68 6.6.2 揭开Google服务器的 神秘面纱................ 69 6.6.3 Google服务器的配置

情况. 69

6.6.4 Google服务器的性能 评测. 73

第7章Hadoop环境的建立.......... 75 7.1 Hadoop配置环境............... 75 7.2 配置ssh实现Hadoop结点间

用户的无密码访问.......... 76

7.3 JDK的安装配置................. 76 7.4 Hadoop的安装配置........ 77

7.5 Hadoop中的Hello World..................... 81 7.6 C语言程序在Hadoop 上运行................ 82 第8章动手做自己的云计算

V0.01系统..... 86

8.1 系统总体分析........................ 86 8.1.1 系统架构................... 86 8.1.2 文件分布式存储流程............. 88 8.1.3 计算与存储的整合流程...... 88

8.2 管理节点程序设计与分析.................. 89 8.2.1 管理节点服务器程序

主函数........................ 90 8.2.2 管理节点各线程函数的 设计.. 93

8.2.3 主服务器中其他函数的

设计.. 95

8.3 子节点程序分析................. 98 8.3.1 子节点主函数..... 99

8.3.2 子节点各线程函数设计.. 102

8.4 客户端API设计............. 107

8.4.1 客户端文件的存储................ 108 8.4.2 客户端启动子节点计算... 113 8.4.3 客户端应用的简单实例... 114 8.5 客户端应用开发实例115 第三篇云计算应用实例

第9章基于不可信服务器节点的云计算 基础架构....... 118

9.1 云计算基础架构的应用场景........ 118 9.2 云计算基础架构.............. 120 9.3 基于单向指针目录映射的分层

用户隔离...... 121

9.4 云文件系统的物理存储管理........ 123

9.5 云存储的安全级别划分...................... 124 9.6 计算和存储的整合....... 125 9.7 计算和存储的迁移....... 126

9.8 任务的可并行性和分类分析........ 127 9.9 简化的服务器级粗粒度计算和 存储资源分配方案... 130

9.10 数据的云计算系统之旅.................. 133 第10章云计算与智能.................... 135 10.1 云计算的智能与人类

智能的比较........................ 135

10.2 云计算提升终端智能......................... 136 10.3 云计算智能与Monte Carlo 方法................ 138

10.4 云计算时代不确定性智能算法

示例——模拟谐振子算法........... 138

10.4.1 简谐振动的描述.................... 139 10.4.2 模拟谐振子算法描述...... 141 10.4.3 模拟谐振子算法流程...... 144 10.4.4 模拟谐振子算法分析...... 146 10.4.5 模拟谐振子算法应用于 旅行商问题..... 149

10.4.6 模拟谐振子算法在连续 和非线性优化问题中的

应用.......................... 161 10.4.7 模拟谐振子算法的隐含 并行性................... 162

10.5 云计算中的人工智能......................... 162 第11章云计算企业之间的竞争性 分析................... 164

11.1 云计算技术流派分析.......................... 164 11.1.1 存储型—数据密集云 计算平台............ 164 11.1.2 计算型—计算密集云

计算平台............ 165

11.1.3 综合云计算平台.................... 165

11.2 国际云计算公司分析.......................... 165 11.2.1 云计算技术的提出者 Google.................... 166

11.2.2 “端”的霸主微软............. 166 11.2.3 蓝色巨人IBM的蓝云.... 167 11.2.4 云计算的市场先行者 Amazon公司. 168

11.2.5 Salesforce从SaaS走入

云中.......................... 168

11.2.6 热爱白皮书的Sun............... 169 11.2.7 EMC云计算的核心是

虚拟化................... 170

11.2.8 渔翁得利的思科.................... 170

11.3 国内云计算公司分析.......................... 171 11.3.1 拥有基础设施的 世纪互联............ 171

11.3.2 阿里巴巴下决心

入云.......................... 172 11.3.3 中国移动的BigCloud...... 172 11.3.4 国产旗帜友友云计算

平台.......................... 173 11.3.5 曙光高性能与云计算...... 173 11.3.6 展览也要云..... 173

11.4 开源云计算平台分析.......................... 174 11.5 国际国内云计算平台提供商

对比研究.. 175

11.6 产业综合分析.................. 179 11.6.1 云计算与网络设备商的 关系.......................... 179 11.6.2 云计算与移动通讯运 营商的关系..... 180

11.6.3 云计算与服务器提 供商的关系..... 180

11.6.4 云计算与应用程序开 发商的关系..... 181

后记:未来的计算机—不确定性和

隐含并行计算...................... 182 附录:计算力的标准Linpack测试详细 指南..................... 186 参考文献196

面对云计算,有的人越来越糊涂,经常听到有人用云里雾里来形容现在的云计算。云计算系统

确实是一个庞大和综合的系统,即使是国际大公司也不敢贸然进军云计算领域,大量的企业不

是将自己的传统技术优势称为云计算,就是雷声大雨点小的观望。一般开发者更是不适应在机

群的环境下工作,所以本章将用一个简单的例子来展现云计算的基本特点和技术开发方式,我

们并不保证这个系统是一个完善的系统,但它具备了云计算的一些基本特点如计算和存储的整

合、计算向存储的迁移、文件的分布式存储、计算的并行化等,我们对这些功能采用了最简单

的实现方法以使大多数读者能从中体会到云计算技术的核心理念,所以我们命名这个系统为云

计算V0.01,运行环境为Windows。 8.1

系统总体分析

我们进行系统总体结构设计时主要着眼于云计算基本特征的实现,不考虑系统中很多细节性的

要求和高级要求,并采用中等水平的读者能完成的难度设计。

设计需要实现的基本功能如下。 (1)向开发云应用的客户提供可以调用的API函数,利用API函数实现对云计算系统的访问。 (2)实现分布式的文件存储。

(3)实现计算向存储的迁移,使计算和存储在同一个节点完成,避免数据在网络中的传送。 (4)向用户隔离计算的并行性和存储的分布性,用户无需关心系统具体的操作过程。 (5)初步实现对数据求和及求最大值的处理,演示云计算的基本特点。读者可以通过增加处理

函数实现更多的计算功能。 8.1.1

系统架构

云计算V0.01系统是一个完全模型化的实验用系统,开发和运行环境为Windows系统,通过对该

系统的学习使读者对云计算技术的基本要点有一定的了解,云计算V0.01将云计算设备分为3个

角色:管理节点、子节点和客户端。管理节点和子节点构成了云计算的服务器端,客户端通过

对API的调用实现对云计算系统的访问,并通过API整合为不同的应用程序。为了简化系统的设

计难度,我们在做云计算V0.01时限定所做的计算任务包括对大数据量数组求和、求最大值

等操

作,读者可通过实际的系统体会存储的分布化与计算的并行化的关系,并理解计算向存储迁移

的作用。云计算V0.01没有实现存储的副本策略,因此暂时不能处理节点失效的问题,这也是为

了降低系统难度的需要。以下的系统架构方法仅供参考和学习,并且不代表我们赞成这一架构,

不同的读者可以设计不同的系统架构。

系统的整个架构如图8.1所示,这种架构方式是一个以客户端为核心的架构方法,系统中的所有

操作指令均由客户端发出,管理节点不和任一子节点作数据和指令的通信,管理节点的作用主

要是维护root.dat和node.dat两个系统文件。root.dat文件存储着现在系统中已注册的用户名及该用

户所对应的文件分块描述文件所在节点的IP地址,系统利用这一文件可实现用户的注册、认证

及用户登录后获得文件分块描述文件所在节点的IP地址。node.dat文件则维护着整个云计算系统

所有子节点的IP地址、端口、最大空间、剩余空间等信息,客户端通过该文件能够获得整个机

群的信息,从而实现向各子节点的直接连接。客户端从管理节点获得了相关的系统信息后将根

据这一信息直接向各个子节点发起连接,完成文件存储及计算的功能,这大大提高了数据传输

的速率,减轻了管理节点的负荷。各用户文件的具体分块和存储方式被系统用该用户的用户名

(username)作为文件名的文件分块描述文件存储于其中的一个子节点,这一子节点的IP可在

root.dat文件中找到。

图8.1 云计算V0.01的系统结构

在云计算V0.01系统中不同角色间存在两类数据的传送:一类是命令数据CMD,管理节点和子

节点通过命令数据判断自己下一步所要完成的任务;一类是信息数据,这类数据是系统要完成

相关任务所需要数据,如系统描述信息、文件信息等,这类数据的数据量相对较大。由于采用

了计算向存储的迁移策略,系统中出现用户文件数据传输的情况很少,这大大提高了系统的运

行效率。

8.1.2

文件分布式存储流程

系统在进行文件存储时先通过客户端连接管理节点,读取root.dat文件数据,检验是否有该用户

存在,并获取用户数据块文件所在节点的IP地址。通过读取node.dat文件从管理节点读取

子节点

的IP地址的列表,根据以上信息完成对数据的分割,启动多线程函数同时连接各子节点将数据

分别保存在各个节点上,最后更新username表以备访问时重新找到文件的分布情况。uesername

文件将被存储于某一节点上,管理节点会根据现有username文件的分布情况向用户分配一个节

点的IP地址存放username文件,文件名就是该用户的用户名,由于用户名在系统中是惟一的,

所以每个用户的username也是惟一的,不会造成混乱,如图8.2所示。 图8.2 文件的分布式存储流程 8.1.3

计算与存储的整合流程

如图8.3所示,在云计算V0.01系统中,我们利用获得的用户名、文件名、数据块号以及数据分

块信息文件的IP地址信息,可以惟一地确定任一数据块的位置和文件名,客户端同时向各个子

节点发送启动计算的命令,各节点就地读取数据块本地文件,并对其进行计算,计算完成后发

送回客户端汇总得到最后的结果。 图8.3 计算与存储的整合流程

这一计算过程不用移动任何数据,对于数据的处理就在存储数据块的节点完成,系统根据客户

端的指令,将计算迁移到节点上分布式的完成,大大提高了计算效率,避免了数据在网络中的

大量流动所造成的效率下降,对于海量数据来说,这一做法的效果是相当明显的。对于不同的

数据,我们可以定义不同的数据处理方法,从而扩展系统的应用领域。 8.2

管理节点程序设计与分析

管理节点在云计算V0.01系统中只与客户端进行通信,存储系统中的节点信息和用户注册信息,

并不负责任务的调度工作。

在管理节点我们将保存root.dat和node.dat两个系统信息文件。root.dat文件保存用户名及该用户文

件系统所在的子节点的IP地址,采用userInfo数据结构来描述。客户端程序只有获得了子节点IP

地址才能和该子节点直接建立连接获取子节点上的用户存储情况文件,该文件的文件名就是用

户的用户名,通过这一个文件可以知道数据的具体存储情况,从而由客户端直接与数据块存储

节点建立连接。node.dat文件保存了云计算系统的所有子节点的IP地址、总空间和可用空间等信

息,由nodeInfo数据结构来描述。

管理节点各函数调用关系如图8.4所示。

图8.4 管理节点函数调用结构 8.2.1

管理节点服务器程序主函数

管理节点主程序为整个管理程序的主入口,通过4个线程函数来监听并完成客户端所提交的任 务。

程序8.1

/*文件名mainsever.cpp*/

// 定义管理节点服务器程序的入口点 void test();

int _tmain(int argc, _TCHAR* argv[])

{

openfile(); //获得root.dat、node.dat的文件指针 test(); //该函数完成对主服务器的配置工作 WSADATA wsa; int ret = 0;

int PORT = 5100; SOCKET s_socket;

SOCKET c_socket;

struct sockaddr_in s_sockaddr;

struct sockaddr_in c_sockaddr;

int c_sockaddr_len = sizeof(c_sockaddr); ret = WSAStartup(MAKEWORD(2, 2), &wsa); if(ret != 0)

{

cout << \"Init WinSock failed:\" << ret << endl;

return 0; }

if((s_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == SOCKET_ERROR) {

cout << \"Create Socket Failed:\" << WSAGetLastError() << endl; WSACleanup(); return 0;

}

s_sockaddr.sin_family = AF_INET; s_sockaddr.sin_port = htons(PORT);

s_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

if(bind(s_socket, (SOCKADDR *)&s_sockaddr, sizeof(s_sockaddr)) == SOCKET_ERROR) {

cout << \"bind failed:\" << WSAGetLastError() << endl; closesocket(s_socket); WSACleanup(); return 0;

}

if(listen(s_socket, 5) == SOCKET_ERROR) {

cout << \"Listen Failed:\" << WSAGetLastError() << endl; closesocket(s_socket); WSACleanup(); return 0; }

CMD cmd;

//进入循环接收来自客户端的操作命令cmd while(1) {

c_socket = accept(s_socket, (SOCKADDR *)&c_sockaddr, &c_sockaddr_len); recv(c_socket, (char *)&cmd, sizeof(CMD), 0);//从客户端获取操作命令 SOCKET *tsock = (SOCKET *)malloc(sizeof(SOCKET)); *tsock = c_socket; switch(cmd) {

case USERADD:

_beginthreadex(NULL, 0, &useraddthread, tsock, 0, NULL);//进入增加用户线程 break;

case USERGET:

_beginthreadex(NULL, 0, &usergetthread, tsock, 0, NULL);//进入获取用户信息 线程

case USERDEL:

_beginthreadex(NULL, 0, &userdelthread, tsock, 0, NULL);//删除用户,暂未定 义

case GETNODE:

_beginthreadex(NULL, 0, &getnodeaddrthread, tsock, 0, NULL);//进入获取节点 信息线程 default: break; } }

cin.get(); cin.get(); return 0;

}

//test()函数用于配置各子节点的IP、端口等信息,并将信息存储到管理节点的node.dat文件

void test()

{

cout << \"输入地址信息\" << endl; char ip[16];

int port = 5101;

while(1) {

cout << \"输入IP\" << endl; scanf(\"%s\

if(strcmp(ip,\"0\") == 0) break;

if(nodeadd(ip, port, 1024*10) == 0) cout << \"该记录已经存在\" << endl; }

cout << \"主服务器配置完成\" << endl; }

上面的管理服务器主程序在5100端口监听来自客户端的连接及操作命令,其命令由cmd定义, 根据从客户端接收到的命令进入不同的处理线程,在本系统已实现的功能有添加用户功能、获

取用户信息功能和获取节点信息功能。管理节点服务器在启动时就调用test()函数完成对子节点

信息的添加及配置。节点信息被存到node.dat文件,用户信息被存到root.dat。在用户需要进行数

据访问时将读取这两个文件获得当前云计算系统所有已接入系统的子节点,并判断当前用户是

否存在,如存在则返回其文件分配信信息存储位置。

我们要注意的是在现在这个系统中管理节点并不和任何的子节点进行通信,也不直接协调子节

点的工作。用户在获取相关信息后将直接与子节点联系进行操作和数据访问,这样可以大大减

轻主节点的负载。

在管理节点程序中我们定义了一些常用的数据结构主要有userInfo,该数据结构与root.dat文件有

关,包括用户名、用户数据配置文件所在节点的IP地址等信息,因为用户数据文件的信息没有

存放在管理节点而是放在某一个子节点上的,客户端要访问文件数据首先要从管理节点的 root.dat文件中获取该用户数据配置文件所在节点的IP地址,再通过该IP地址获取数据的存储信

息。另一个数据结构是nodeInfo,该数据结构与node.dat文件有关,包括节点IP、端口、节点总

容量、可用空间等,系统中所有节点的相关内容都采用这一数据结构存入node.dat文件。 主节点服务器程序部分参数及数据结构的定义如程序8.2所示。 程序8.2

/*文件名melem.h*/

#define USERADD 1 //添加用户 #define USERGET 2 //获取用户信息 #define USERDEL 3

#define GETNODE 4 //获取节点信息

#define BLOCKSIZE 1024//定义文件块大小 typedef int CMD; //CMD为命令标识 /*此结构体写入root.dat文件*/ typedef struct {

char user[20]; //用户名

char ip[16]; //用户数据配置文件所在节点的IP地址 int port; }userInfo;

/*此结构体写入node.dat文件*/ typedef struct {

char ip[16]; //存储节点的IP地址 int port; //端口号

int userNum; //用户数目

_off_t totalsize; //节点的总容量 _off_t freesize; //节点的可用空间 }nodeInfo;

typedef struct {

char ip[16];

int port; }nodeaddr; 8.2.2

管理节点各线程函数的设计

管理节点程序的功能基本是由其定义的4个线程函数(其中删除用户未定义)提供的,这些函数

的功能主要是完成用户信息的注册、服务器节点信息的管理和用户数据配置信息的管理。管理

节点可以看作是一个信息的中转站,其自身并不完成任何的数据操作和处理工作。 各线程的函数定义如下。 1

.增加新用户线程函数 程序8.3

/*文件名mthread.cpp*/

/*增加新的用户,用于新用户注册功能*/ unsigned _stdcall useraddthread(LPVOID p) {

SOCKET* tsock = (SOCKET *)p; struct sockaddr_in taddr; int len = 20;

char* username = (char *) malloc (len * sizeof(char)); recv(*tsock, username, len, 0);//从客户端接收用户名 int result = useradd(username);

send(*tsock, (char *)&result, sizeof(int), 0); closesocket(*tsock); free(username); free(tsock); return 1;

}

函数useraddthread()接收来自于客户端的新注册用户名,调用useradd()函数将用户名及存储该用

户文件信息的节点IP地址写入主节点的root.dat文件,客户端访问该文件可以获得某一用户的文

件存储信息文件所在的子节点IP地址,该文件的文件名就是用户名。 2

.获取用户信息线程函数 程序8.4

/*文件名mthread.cpp*/

/*客户端获取用户信息文件*/

unsigned _stdcall usergetthread(LPVOID p) {

SOCKET* tsock = (SOCKET *)p; struct sockaddr_in taddr; int len = 20;

char* username = (char *) malloc (len);

userInfo *user = (userInfo *) malloc (sizeof(userInfo)); recv(*tsock, username, len, 0);

cout << \"接收到的用户名:\" << username << endl;

/*根据用户名读取root.dat中的用户及对应存储文件描述信息的子节点IP*/ if(userget(username, user) == 0) {

cout << \"get false\" << endl; strcpy(user->user, \"0\"); strcpy(user->ip,\"0.0.0.0\"); user->port = 0;

}

cout << \"int_thread:\" << user->user << \" \" << user->ip << \":\" << user->port << endl; send(*tsock, (char *)user, sizeof(userInfo), 0); closesocket(*tsock); free(username); free(user); return 1;

}

函数usergetthread()接收来自客户端的用户名,并在root.dat文件中查找该用户名对应的userInfo

数据结构,并传回给客户端。其中调用userget()函数从root.dat读取与username对应的userInfo信

息。通过调用这一函数客户端可以知道对应用户的文件描述文件存储在哪个子节点上,通过连

接该子节点获取文件的具体存储方式。客户端在调用一这函数后将通过返回的IP地址与存储了

数据分块描述情况文件的子节点进行连接。 3

.文件分块线程函数 程序8.5

/*文件名mthread.cpp*/

/*根据node.dat文件中的节点信息,将数据块分配到各节点*/ unsigned _stdcall getnodeaddrthread(LPVOID p) {

SOCKET* tsock = (SOCKET *)p; int blocknum = 0;

nodeInfo *node = (nodeInfo *) malloc (sizeof(nodeInfo)); nodeaddr *naddr = (nodeaddr *) malloc (sizeof(nodeaddr));

recv(*tsock, (char *)&blocknum, sizeof(int), 0); //获取数据块个数 for(int i = 0; i < blocknum; i++) {

memset(node, 0, sizeof(nodeInfo)); memset(naddr,0, sizeof(nodeaddr));

datagetnode(node);//获取该数据块的存储位置 naddr->port = node->port; strcpy(naddr->ip, node->ip);

send(*tsock, (char *)naddr, sizeof(nodeaddr), 0); //该数据块的存储位置发送回客户端 }

closesocket(*tsock); free(node); free(naddr); free(tsock); return 1;

}

函数getnodeaddrthread()接收来自客户端的数据块个数,并为每个数据块分配一个存储节点,数

据块的分配通过调用datagetnode()函数来完成,该函数按剩余空间最大的策略向各数据块分配存

储节点,并将分配结果发送回客户端,由客户端根据接收到的子节点IP直接连接子节点来完成

文件的存储工作,并将存储结果写入子节点中的数据分块描述文件中,以便系统在下次读取时

获得数据的存储情况。 8.2.3

主服务器中其他函数的设计

主服务器其他函数定义。

程序8.6

/*文件名mfile.cpp*/

/*向node.dat文件添加节点信息*/

int nodeadd(char* ip, int port, _off_t totalsize) {

nodeInfo *temp = (nodeInfo *) malloc (sizeof(nodeInfo)); fseek(fp_node, 0, 0); /*判断该节点是否已存在*/

while( fread(temp, sizeof(nodeInfo), 1, fp_node) == 1) {

if(strcmp(temp->ip, ip) == 0 && temp->port == port) {

free(temp); return 0; }

}

strcpy(temp->ip, ip); temp->port = port;

temp->userNum = 0;

temp->totalsize = totalsize;

temp->freesize = totalsize; /*写入node.dat文件*/

fwrite(temp, sizeof(nodeInfo), 1, fp_node); fseek(fp_node, 0, 0); fflush(fp_node); free(temp);

return 1; }

/*分配用户数据描述文件存储节点的IP*/ int usergetnode(nodeInfo *node) {

nodeInfo *temp = (nodeInfo *) malloc (sizeof(nodeInfo)); fseek(fp_node, 0, 0); int num = 0; int no = 0;

/*寻找已分配uesername文件最少的节点IP*/

if(fread(node, sizeof(nodeInfo), 1, fp_node) != 1) return 0;

while( fread(temp, sizeof(nodeInfo), 1, fp_node) == 1) {

++num;

if(temp->userNum < node->userNum) {

*node = *temp;

no = num; } }

memset(temp, 0, sizeof(nodeInfo)); *temp = *node;

temp->userNum += 1;

fseek(fp_node, no*sizeof(nodeInfo), 0);

fwrite(temp, sizeof(nodeInfo), 1, fp_node); fseek(fp_node, 0, 0); fflush(fp_node); free(temp); return 1; }

/*将username及对应存储数据描述文件的节点IP写入root.dat文件*/ int useradd(char* username)

{

userInfo *temp = (userInfo *) malloc (sizeof(userInfo)); nodeInfo *node = (nodeInfo *) malloc (sizeof(nodeInfo)); fseek(fp_user, 0, 0);

while( fread(temp, sizeof(userInfo), 1, fp_user) == 1) /*检测该用户名是否存在*/

if(strcmp(temp->user, username) == 0) {

free(temp);

free(node);

return 0; //该用户名已经存在

}

if(usergetnode(node) == 0)//获取该用户数据描述文件存储节点的IP,通过node参数传出

return -1; //获取节点失败

memset(temp, 0, sizeof(userInfo)); strcpy(temp->user, username); strcpy(temp->ip, node->ip);

temp->port = node->port;

/*将userInfo信息写入root.dat文件,确认数据块描述文件的存储位置*/ fwrite(temp, sizeof(userInfo), 1, fp_user) ; fseek(fp_user, 0, 0); fflush(fp_user); free(temp); free(node);

return 1; }

/*根据用户名,读取root.dat文件中的userInfo数据*/

int userget(char* username, userInfo *user)

{

userInfo *temp = (userInfo *) malloc (sizeof(userInfo)); fseek(fp_user, 0, 0);

while( fread(temp, sizeof(userInfo), 1, fp_user) == 1) if(strcmp(temp->user, username) == 0) {

*user = *temp; return 1; }

return 0; }

/*根据node.dat文件获取系统中的节点信息nodeInfo,并按最大剩余空间优先策略分配给数据块

*/

/*分配完成后更新node.dat文件的内容*/

int datagetnode(nodeInfo *node) {

nodeInfo *temp = (nodeInfo *) malloc (sizeof(nodeInfo)); fseek(fp_node, 0, 0); int num = 0;

int no = 0;

if(fread(node, sizeof(nodeInfo), 1, fp_node) != 1) return 0;

/*首先向剩余空间最大的节点分配数据块*/

while( fread(temp, sizeof(nodeInfo), 1, fp_node) == 1) {

++num;

if(temp->freesize > node->freesize) {

*node = *temp; no = num; } }

memset(temp, 0, sizeof(nodeInfo)); *temp = *node;

temp->freesize -= BLOCKSIZE;

fseek(fp_node, no*sizeof(nodeInfo), 0);

/*将分配后的信息写回node.dat文件,更新文件信息*/ fwrite(temp, sizeof(nodeInfo), 1, fp_node); fseek(fp_node, 0, 0); fflush(fp_node); free(temp); return 1;

}

/*获得rood.dat和node.dat的文件指针*/ /*fp_user指向root.dat文件*/ /*fp_node指向node.dat文件*/ void openfile()

{

if( (fp_user = fopen(\"root.dat\fp_user = fopen(\"root.dat\

if( (fp_node = fopen(\"node.dat\fp_node = fopen(\"node.dat\} 8.3

子节点程序分析

云计算V0.01中子节点主要完成数据的存储及用户文件存储信息的保存,各用户文件存储信息的

文件名为该用户的用户名,子节点程序需要在所有的节点上同时运行。文件的存储和访问由客

户端与子节点直接连接来完成,子节点和管理节点不进行任何的数据通信工作。

各数据块存储的文件名为username_filename_blockNo,即用户名加文件名加数据块号,之间用

下划线连接。

子节点函数调用结构如图8.5所示。 图8.5 子节点函数调用结构 8.3.1

子节点主函数

子节点的主程序启动后监听来自于客户端发过来的命令cmd,根据不同的命令进入不同的线程

进行处理。 程序8.7

/*文件名blocksever.cpp*/

// blocksever.cpp : 定义控制台应用程序的入口点 int _tmain(int argc, _TCHAR* argv[]) {

WSADATA wsa; int ret = 0;

int PORT = 5101; SOCKET s_socket;

SOCKET c_socket;

struct sockaddr_in s_sockaddr;

struct sockaddr_in c_sockaddr;

int c_sockaddr_len = sizeof(c_sockaddr); ret = WSAStartup(MAKEWORD(2, 2), &wsa); if(ret != 0) {

cout << \"Init WinSock failed:\" << ret << endl;

return 0; }

if((s_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == SOCKET_ERROR) {

cout << \"Create Socket Failed:\" << WSAGetLastError() << endl; WSACleanup(); return 0; }

s_sockaddr.sin_family = AF_INET; s_sockaddr.sin_port = htons(PORT);

s_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

if(bind(s_socket, (SOCKADDR *)&s_sockaddr, sizeof(s_sockaddr)) == SOCKET_ERROR) {

cout << \"bind failed:\" << WSAGetLastError() << endl; closesocket(s_socket); WSACleanup(); return 0; }

if(listen(s_socket, 5) == SOCKET_ERROR) {

cout << \"Listen Failed:\" << WSAGetLastError() << endl; closesocket(s_socket); WSACleanup(); return 0; }

CMD cmd;

while(1) {

c_socket = accept(s_socket, (SOCKADDR *)&c_sockaddr, &c_sockaddr_len); recv(c_socket, (char *)&cmd, sizeof(CMD), 0);

SOCKET *tsock = (SOCKET *)malloc(sizeof(SOCKET)); *tsock = c_socket;

/*获取用户文件存储信息,该文件存储于其中一个子节点*/ /*用户根据管理节点提供的IP,直接连接该子节点获取*/ if(cmd == USERINFOGET)

_beginthreadex(NULL, 0, &userinfogetthread, tsock, 0, NULL);

else if(cmd == FILEINFOADD)

_beginthreadex(NULL, 0, &fileinfoaddthread, tsock, 0, NULL);//添加文件存储 信息

else if(cmd == STOREBLOCK)

_beginthreadex(NULL, 0, &storedatathread, tsock, 0, NULL); //存储数据块 else if(cmd == GETDATA)

_beginthreadex(NULL, 0, &getdatathread, tsock, 0, NULL); //完成计算工作

else continue; }

return 0; }

子节点的主函数的功能是启动对客户端发出命令的监听和执行,主要是完成4项工作,分别由4

个不同的线程函数来完成。一是获取文件存储信息;二是在文件分块描述文件中添加信息;三

是实现数据块的存储工作;四是在各节点启动计算,完成存储与计算的整合工作。 子节点程序要用到的一些常用数据结构定义如下。 程序8.8

/*文件名belem.h*/ #ifndef BELEM_H #define BELEM_H

#include \"stdafx.h\" #define USERNAME_LEN 20 #define FILENAME_LEN 64 #define BLOCKNAME_LEN 128 #define LISTLEN 5

#define MAINIP \"127.0.0.1\" #define USERADD 1 #define USERGET 2 #define USERDEL 3

#define USERINFOGET 5 #define FILEINFOADD 6 #define STOREBLOCK 7

#define GETDATA 8 typedef int CMD;

/*fileInfo数据结构为子节点上用户数据文件描述的内容*/ typedef struct {

char filename[FILENAME_LEN]; //文件名 int blockNO; //数据块号

char ip[16]; //数据块存放节点的IP地址 int port; }fileInfo;

/*数据块描述数据结构*/ typedef struct {

int blockNO; char ip[16]; int port; }blockInfo;

typedef struct {

fileInfo *e; int length; int size; }fileInfoList; #endif

8.3.2

子节点各线程函数设计 1

.获取文件存储信息线程函数 程序8.9

/*文件名bthread.cpp*/

unsigned _stdcall userinfogetthread(LPVOID p) //获取用户信息文件线程 {

SOCKET* tsock = (SOCKET *)p;

char username[USERNAME_LEN];

recv(*tsock, username, USERNAME_LEN, 0); FILE *fp;

if((fp = fopen(username, \"rb\")) == NULL)

fp = fopen(username, \"wb+\"); //打开用户存储信息描述表 struct _stat info;

_stat(username, &info);//获取文件信息 _off_t filelen = info.st_size;

send(*tsock, (char *)& filelen, sizeof(_off_t), 0); if(filelen > 0) {

char *buf = (char *) malloc (filelen); fread(buf, 1, filelen, fp); send(*tsock, buf, filelen, 0); free(buf); }

closesocket(*tsock); fclose(fp); return 1; }

用户从管理节点获取到数据块描述文件所在的节点IP地址后,即可连接该节点并调用此函数获

取文件内容,由于该文件的文件名就是用户名,所以子节点只要知道了用户名即可知道需要打

开的文件名,该节点通过socket接收用户名就是这个原因。 2

.添加数据块描述信息线程函数 程序8.10

/*文件名bthread.cpp*/

unsigned _stdcall fileinfoaddthread(LPVOID p)//添加文件信息线程 {

SOCKET* tsock = (SOCKET *)p; int listlen = 0;

char filename[FILENAME_LEN]; char username[USERNAME_LEN];

fileInfo ftmp;//定义文件信息数据结构 blockInfo btmp; fileInfoList L; initlist(&L);

recv(*tsock, username, USERNAME_LEN, 0); //获取用户名

recv(*tsock, filename, FILENAME_LEN, 0); //获取文件名

recv(*tsock, (char *)& listlen, sizeof(int), 0) //获取文件分块个数,即获取顺序表的长度

for(int i = 0; i < listlen; i++) //获取各个数据块的存储信息与在文件中的顺序号,顺序号以0 开始 {

recv(*tsock, (char *)&btmp, sizeof(btmp), 0);//接收数据块信息,包括块号、存储的IP地

strcpy(ftmp.filename, filename); strcpy(ftmp.ip, btmp.ip); ftmp.blockNO = btmp.blockNO; ftmp.port = btmp.port;

addlist(&L, ftmp);//加入顺序表

}

FILE *fp;

if((fp = fopen(username, \"rb+\")) == NULL)

fp = fopen(username, \"wb+\");

fileadd(&L, fp);//将文件存储信息的顺序表添加到数据分块文件中,文件名就为用户名 fclose(fp);

int result = 1;

send(*tsock, (char *)&result, sizeof(int), 0); destroylist(&L); closesocket(*tsock); free(tsock); return 1;

}

添加数据块描述信息线程函数从客户端通过socket接收用户名、文件名及文件分块个数,并将每

个数据块的块号blockNO和存储位置所在IP地址等信息建立顺序表,将此顺序表存到该用户的文

件分块描述文件中。

这一线程函数调用fileadd()函数实现向username添加文件块存储信息,这个信息由fileInfo数据结

构来描述,fileadd()函数定义如下。 程序8.11

/*位于文件bfile.cpp中*/

int fileadd(fileInfoList *L, FILE * fp) //fp为username文件指针 {

char filename[20]; fileInfo file;

strcpy(filename, L->e[0].filename);

if(filesearch(filename, fp) == 0) //检测是否有同名文件 filedel(filename,fp); //如有同名文件则删除并覆盖该文件 fseek(fp, 0, SEEK_END);

for(int i = 0; i < L->length; i++) {

file = L->e[i];

fwrite(&file, sizeof(fileInfo), 1, fp); }

return 1; }

/*在username文件中检测是否有同名文件*/ int filesearch(char* filename, FILE *fp) {

fileInfo ftmp;

fseek(fp, 0, 0);

while( fread(&ftmp, sizeof(fileInfo), 1, fp) == 1) if(strcmp(ftmp.filename, filename) == 0) return 0; return 1; }

/*覆盖同名文件*/

int filedel(char* filename, FILE *fp) {

fileInfo ftmp; fseek(fp, 0, 0); while(!feof(fp))

{

fread(&ftmp, sizeof(fileInfo), 1, fp); if(strcmp(ftmp.filename, filename) == 0) {

strcpy(ftmp.filename, \"0\");

fseek(fp, ftell(fp)-sizeof(fileInfo),0); fwrite(&ftmp, sizeof(fileInfo), 1, fp);

fseek(fp,ftell(fp), 0); } }

return 1; }

在文件存储信息的添加过程中我们采用顺序表来维护各数据块的存储信息,因此定义了几个基

本的顺序表操作。 程序8.12

/*位于文件blist.cpp*/ /*初始化顺序表函数*/

int initlist(fileInfoList *L)

{

L->e = (fileInfo *) malloc (LISTLEN * sizeof(fileInfo)); if(L->e == NULL) {

printf(\"初始化表,分配内存失败\"); return 0; }

L->length = 0;

L->size = LISTLEN;

return 1; }

/*向顺序表中加入一个数据块存储信息*/

int addlist(fileInfoList *L, fileInfo e) {

if(L->length >= L->size)

{

fileInfo *newbase = (fileInfo *)

realloc

LISTLEN)*sizeof(fileInfo)); if(newbase == NULL) {

printf(\"向表添加数据,增加内存空间失败\"); return 0; }

L->e = newbase; L->size += LISTLEN; }

L->e[L->length] = e; ++ L->length; return 0;

}

/*释放存储空间*/

int destroylist(fileInfoList *L)

(L->size

+

(L->e,

{

L->length = 0; L->size = 0; free(L->e); return 0; } 3

.保存数据块线程函数 程序8.13

/*文件名bthread.cpp*/

unsigned _stdcall storedatathread(LPVOID p)//保存数据块 {

SOCKET* tsock = (SOCKET *)p; int datalen = -1;

int blockNo = -1;

char filename[FILENAME_LEN];

char username[USERNAME_LEN];

recv(*tsock,username, USERNAME_LEN, 0); recv(*tsock, filename, FILENAME_LEN, 0);

recv(*tsock, (char *)& blockNo, sizeof(int), 0); recv(*tsock,(char *)& datalen, sizeof(int), 0); char *buf = (char *) malloc (datalen); recv(*tsock,buf, datalen, 0);

cout << \"storedatathread blockNo:\" << blockNo << endl; cout << \"storedatathread buflen:\" << datalen << endl;

char blockname[BLOCKNAME_LEN]; //数据块文件名

sprintf(blockname, \"%s_%s_%d\生成数据块文件名 FILE *fp;

fp = fopen(blockname, \"w+\"); //打开数据块文件 fwrite(buf, 1, datalen, fp); //写入信息 fclose(fp); free(buf);

closesocket(*tsock); free(tsock); return 1; }

本函数完成对各数据块的存储工作,客户端根据管理节点的数据块存储安排,获取各数据块存

储节点的IP地址,由客户端直接连接各存储节点,调用storedatathread()函数,本函数获取数据

块的所属用户名、文件名、块号、块大小和数据块的具体内容,将数据块存储在当前节点,各

个数据块的命名原则为用户名_文件名_块号(username_filename_blockNO),这样任何一个数据

块将有一个惟一的文件名,该数据块的存储信息同时被写入了数据块描述文件。虽然文件被分

割为多个数据块并存储在不同的子节点上,但由于有数据块描述文件,我们可以在任何时候恢

复并访问该文件。

4

.获取数据计算结果线程函数 程序8.14

/*文件名bthread.cpp*/

unsigned _stdcall getdatathread(LPVOID p)//获取数据计算结果 {

SOCKET* tsock = (SOCKET *)p; int datalen = 0; int blockNo = 0;

_off_t result = 0;

char filename[FILENAME_LEN];

char username[USERNAME_LEN];

recv(*tsock,username, USERNAME_LEN, 0); recv(*tsock, filename, FILENAME_LEN, 0);

recv(*tsock, (char *)& blockNo, sizeof(int), 0); FILE *fp;

char blockname[BLOCKNAME_LEN];//数据块文件名

sprintf(blockname, \"%s_%s_%d\fp = fopen(blockname, \"r\"); //打开本节点上的数据块文件 getresult(&result, fp); //在本节点完成计算工作 fclose(fp);

cout << \"num:\" << result << endl;

send(*tsock, (char *)& result, sizeof(_off_t), 0); closesocket(*tsock); free(tsock); return 1; }

获取数据计算结果线程函数实现了在这个云计算系统中计算与存储的整合演示,我们以对一串

数据求和操作为例,客户端根据数据块存储描述文件的描述向各个存储有数据块的节点发送用

户名、文件名和数据块号,这些信息实际上就确定了一个数据块文件的位置,存储每个数据块

的节点就在该节点就地启动对该数据块的计算工作,完成计算后将自己的局部计算结果发送到

客户端,由客户端完成数据的最后整合工作。这样就避免了大量数据在机群中的移动,大大提

高系统的工作效率,体现了“计算向存储迁移”的云计算理念。这一线程函数中的getresult()函数

就是完成计算工作的函数,根据不同的数据和工作需要我们定义不同的计算函数,这一函数必

需在所有的节点上都要驻留,这样系统才能将计算向该节点迁移。函数getresult()在本例中的定 义如下。

程序8.15

/*位于文件bfile.cpp中*/

/*完成对本节点数据块内数据的求和操作*/ int getresult(_off_t *num, FILE *fp) {

fseek(fp, 0, 0); char c; int i = 0; int j = 0; while(!feof(fp)) {

c = fgetc(fp); cout << c; j = 0;

while(!feof(fp)) {

i = 0;

if(c >= '0'&& c <= '9') {

i = atoi(&c); j = 10*j +i; }

c = fgetc(fp); cout << c;

if(c < '0'|| c > '9') break; }

*num += j; }

return 1; }

我们的计算数据是按字符串存储,函数getresult()对本节点数据块实施求和操作,我们同样也定

义其他的数据处理函数,如类似wordcount函数等,通过这一函数我们实现对数据的本地化处理,

每个getresult()函数只处理本节点所存储数据块的数据。这一函数演示了计算向存储的迁移过程。 8.4

客户端API

设计

云计算V0.01为客户端提供了可以访问的API函数,从负载上我们给客户端增加了一些负载,将

文件的分块等工作交给了客户端来完成,只是将计算工作交给子节点来完成。客户端的主要工

作模式是从管理节点读取系统信息,根据这一信息与各子节点直接进行联系完成文件操作及计

算任务。

下面是系统提供的主要API函数,分别在capi.cpp和cfun.cpp中定义。

int cwrite(userInfo user, char* filename, FILE *fp, FILE *fp_tmp); //将数据写入节点

int getdata(char* username, char* filename, FILE *fp_tmp);

int creatconnect(char* ip, int port, SOCKET *csock); //链接服务器,成功返回1,失败返回0

int userregister(char* username); //用户注册

int userlogin(char* username, userInfo *user, FILE *fp); //用户登录 int getuserfile(userInfo user, FILE *fp); //从节点获取用户信息文件 int getuseraddr(userInfo *user); //从主节点获取用户信息文件存放地址 int getnode(nodeaddrList *L, int num); //从主节点分配节点地址

int userinfoadd(fileInfoList *L, userInfo user, FILE *fp_tmp);//用户信息文件中添加一个文件信息

8.4.1

客户端文件的存储

客户端文件的存储是通过调用API函数cwrite()来实现的,它在实际调用时采用如下的形式: cwrite(user, \"data.txt\

函数参数中user为文件所属用户的用户名,data.txt为需要存储的数据文件,fp为该文件的指针,

fp_t是临时文件的指针。F数据结构存储有本次文件分割后所有数据块的存储信息,即username

文件中的信息。函数cwrite()同时把该信息写入子节点和本地的临时文件中。 API函数cwrite()的定义如下。 程序8.16

/*保存在文件capi.cpp中*/

/*实现文件分布式存储功能的API*/

int cwrite(userInfo user, char* filename, FILE *fp, FILE *fp_tmp) {

cout << \"In cwrite \" << endl; datalist D;

threadelemlist T; threadlist H;

initdatalist(&D);

initthreadelemlist(&T); initthreadlist(&H);

filecut(&D, fp);//文件分块

blockdatalist(&D, &T, user.user, filename);

HANDLE hd;

for(int i = 0; i < T.length; i ++) {

hd =(HANDLE) _beginthreadex(NULL, 0, &storedatathread, &(T.e[i]), 0, NULL); addthreadlist(&H,hd); }

WaitForMultipleObjects(H.length, H.e, true, INFINITE); fileInfo finfo; fileInfoList F; initFInfolist(&F); /*建立文件分块信息列表*/

for(int i = 0; i < T.length; i++) {

strcpy(finfo.filename, filename); strcpy(finfo.ip, T.e[i].ip); finfo.port = T.e[i].port;

finfo.blockNO = T.e[i].blockNO; addFInfolist(&F, finfo);

}

/*fileInfoList数据结构存储有该用户所有文件的分块信息*/ userinfoadd(&F,user, fp_tmp); destroyFInfolist(&F); destroydatalist(&D);

destroythreadelemlist(&T); destroythreadlist(&H); return 1;

}

文件存储API函数在完成对数据结构的初始化后,首先调用文件分块函数filecut(),分块函数对

fp所指向的文件进行分块,分块数据由datalist数据结构来维护,datalist数据结构描述如下。

程序8.17

/*保存在文件celem.h中*/ /*数据块数据结构*/ typedef struct {

char buf[BLOCKSIZE]; //数据块缓冲区 int datalen; //数据块大小 int blockNO; //块号 }data;

/*数据块顺序表结构*/. typedef struct {

data *e; //数据块结构体数组指针

int length; //数据块个数 int size; //数据块大小 }datalist;

数据存储API调用filecut()函数后,实现将文件的分块信息写入datalist表,分块完成后datalist表的

内容将如图8.6所示。

图8.6 分块完成后datalist表的内容 程序8.18

/*保存在文件cfile.cpp中*/ /*实现文件分块功能*/

int filecut(datalist *L, FILE *fp) {

char c;

data d;

memset(&d, 0, sizeof(data));

d.blockNO = 0; //对数据块的块号赋初值 d.datalen = BLOCKSIZE; int i = 0; fseek(fp, 0, 0); /*生成数据块*/

while(!feof(fp)) {

++d.blockNO; //数据块号增加 d.datalen = BLOCKSIZE;

for(i = 0; i < BLOCKSIZE; i ++) {

c = fgetc(fp); d.buf[i] = c; }

/*将分块信息写入datalist表*/ if(feof(fp)) {

d.datalen = i;

adddatalist(L, d); //向数据块表中增加一个数据块记录 break; }

c = fgetc(fp);

fseek(fp, -1L, 1); while(1) {

if(c<'0'&& c> '9') break;

if(d.buf[i-1]<'0'|| d.buf[i-1]> '9')

break; else { --i;

--d.datalen; fseek(fp, -1L, 1); }

}

adddatalist(L, d); }

return 1; }

文件的分割完成后cwrite()函数调用storedatathread()函数启动向各子节点的写入操作,完成数

据的分块存储。storedatathread()函数的定义如下。 程序8.19

/*文件存放位置cthread.cpp*/

unsigned _stdcall storedatathread(LPVOID p) {

threadelem *t = (threadelem *)p; WSADATA wsa;

SOCKET csock; int ret = 0;

ret = WSAStartup(MAKEWORD(2, 2), &wsa); if(ret != 0)

{

cout << \"Init WinSock failed:\" << ret << endl; return 0; }

csock = socket(AF_INET, SOCK_STREAM, 0); CMD cmd;

if(creatconnect(t->ip, t->port, &csock) == 0) {

cout << \"链接节点服务器失败\" << endl; closesocket(csock); WSACleanup(); return 0;

}

cmd = STOREBLOCK;

send(csock, (char *)&cmd, sizeof(CMD), 0); send(csock, t->username, USERNAME_LEN, 0);

send(csock, t->filename, FILENAME_LEN, 0);

send(csock, (char *)&(t->blockNO), sizeof(int), 0); send(csock, (char *)&(t->datalen),sizeof(int), 0);

send(csock, t->data, t->datalen, 0); closesocket(csock); WSACleanup(); return 1; }

函数storedatathread()向子节点发送的命令cmd为STOREBLOCK,该命令将启动子节点的存储

任务完成数据块的存储工作,同时客户端向子节点发送用户名、文件名等信息。

存储API函数cwrite()在最后调用userinfoadd()函数将文件分块信息写入节点服务器的usrename文

件并写入本地临时文件,从而完成整个文件分布式存储工作。 程序8.20

/*文件保存位置cfun.cpp*/

int userinfoadd(fileInfoList *L, userInfo user,FILE *fp_tmp)/*文件分块信息写入节点服务器的

usrename文件并写入本地临时文件*/ {

WSADATA wsa;

SOCKET blocksock;

int ret = 0;

ret = WSAStartup(MAKEWORD(2, 2), &wsa); if(ret != 0) {

cout << \"Init WinSock failed:\" << ret << endl; return 0;

}

blocksock = socket(AF_INET, SOCK_STREAM, 0);

if(creatconnect(user.ip, user.port, &blocksock) == 0) {

cout << \"链接节点服务器失败\" << endl; closesocket(blocksock); WSACleanup(); return 0; }

CMD cmd = FILEINFOADD;

char filename[FILENAME_LEN]; strcpy(filename, L->e[0].filename); int listlen = L->length; blockInfo btmp;

send(blocksock, (char *)&cmd, sizeof(CMD), 0); //发送添加文件信息命令 send(blocksock, user.user, USERNAME_LEN, 0); //发送用户名 send(blocksock, filename, FILENAME_LEN, 0); //发送文件名

send(blocksock, (char *)&listlen, sizeof(int), 0); //发送表长度 for(int i = 0; i < listlen; i++)

{

strcpy(btmp.ip, L->e[i].ip); btmp.port = L->e[i].port;

btmp.blockNO = L->e[i].blockNO;

send(blocksock, (char *)& btmp, sizeof(blockInfo), 0);//向子节点发送数据分块信息 }

int result = 0;

recv(blocksock, (char *)&result, sizeof(int), 0); if(result != 1) {

cout << \"在节点上添加文件信息失败\" << endl; return 0;

}

fileadd(L, fp_tmp);//将文件信息添加到本地临时文件 return 1; }

函数userinfoadd()写入节点上的username文件中的内容如图8.7所示,是各数据块所属文件、存储

位置的IP、文件块号等信息,根据这些信息我们能找到所有该文件的数据块并对其进行计算处 理。

图8.7 函数userinfoadd()写入节点上的username文件中的内容 8.4.2

客户端启动子节点计算

客户端启动子节点计算的API函数调用为getdata(),它实际调用时是如下的形式 getdata(username, \"data.txt\

参数username为用户名,data.txt为数据的文件名,fp_t是本地临时保存文件分块信息的文件指针。

函数getdata()的具体定义如下。 程序8.21

/*文件保存位置capi.cpp*/

int getdata(char* username, char* filename, FILE *fp_tmp) {

fileInfo file; fileInfoList L; threadlist H; threadelemlist_r T; initFInfolist(&L); initthreadlist(&H);

initthreadelemlist_r(&T);

fileget(filename, &L, fp_tmp); threadelem_r t;

for(int i = 0; i < L.length; i++) {

strcpy(t.username, username);

strcpy(t.finfo.filename, L.e[i].filename); strcpy(t.finfo.ip, L.e[i].ip); t.finfo.port = L.e[i].port;

t.finfo.blockNO = L.e[i].blockNO; addthreadelemlist_r(&T, t); }

HANDLE hd;

for(int i = 0; i < T.length; i++) {

hd =(HANDLE) _beginthreadex(NULL, 0, &getdatathread, &(T.e[i]), 0, NULL); addthreadlist(&H,hd);

}

WaitForMultipleObjects(H.length, H.e, true, INFINITE); destroyFInfolist(&L);

destroythreadelemlist_r(&T); destroythreadlist(&H); return 1; }

其中getdatathread()函数向各节点发送计算指令GETDATA,启动各子节点相应的计算程序工作,

并向各节点发送相应的文件信息。getdatathread()函数定义如下。 程序8.22

/*文件存放位置cthread.cpp*/

unsigned _stdcall getdatathread(LPVOID p)//获取计算结果 {

threadelem_r *t = (threadelem_r *)p; WSADATA wsa; SOCKET csock; int ret = 0;

ret = WSAStartup(MAKEWORD(2, 2), &wsa); if(ret != 0)

{

cout << \"Init WinSock failed:\" << ret << endl; return 0; }

csock = socket(AF_INET, SOCK_STREAM, 0);

CMD cmd;

if(creatconnect(t->finfo.ip, t->finfo.port, &csock) == 0) {

cout << \"链接节点服务器失败\" << endl; closesocket(csock); WSACleanup(); return 0;

}

cmd = GETDATA;

_off_t result = 0;

send(csock, (char *)&cmd, sizeof(CMD), 0); send(csock, t->username, USERNAME_LEN, 0);

send(csock, t->finfo.filename, FILENAME_LEN, 0);

send(csock, (char *)&(t->finfo.blockNO), sizeof(int), 0); recv(csock, (char *)&result, sizeof(_off_t), 0); NUM += result; closesocket(csock); WSACleanup(); return 1; }

8.4.3

客户端应用的简单实例

下面的程序是一个以控制台程序实现的客户端系统,它实现了云计算V0.01的基本功能。 程序8.23

/*文件名client.cpp*/ #include \"stdafx.h\" #include #include #include #include #include #include \"celem.h\" #include \"cfun.h\" #include \"cglobal.h\" #include \"cthread.h\" #include \"clist.h\" #include \"capi.h\"

#pragma comment (lib, \"wsock32.lib\") using namespace std;

int _tmain(int argc, _TCHAR* argv[]) {

char username[20]; userInfo user;

cout << \"用户注册\\n输入用户名:\" << endl; scanf(\"%s\

cout << username << endl;

FILE *fp_t;

fp_t = fopen(\"temp\打开temp文件 cout << userlogin(username,&user, fp_t) << endl; //产生需要计算的数据并写入文件 FILE *fp;

fp = fopen(\"data.txt\int m = 0;

for(int i = 0; i < 500; i++) {

fprintf(fp,\"%d \m += i; }

fclose(fp);

cout << \"\" << m << endl; fp = fopen(\"data.txt\fseek(fp_t, 0, 0);

cwrite(user, \"data.txt\实现文件的分布式存储 fclose(fp);

/*向各子节点发出计算指令,并汇总结果*/ getdata(username, \"data.txt\/*NUM为求和的结果*/ cout << NUM << endl; cin.get(); cin.get(); return 0; }

这一程序的输出为对所有数据求和的值,系统先由各节点计算存储在自己节点上的数据之和, 再发送到客户端完成数据的汇总求和工作,一旦文件已实现分布式的存储,中间将不会有任何

数据文件的传输工作,大大加快了计算的进程,实现了计算向存储的迁移。 8.5

客户端应用开发实例

通过客户端API的支持我们可以验证云计算V0.01的部分功能,在前面的讲述中我们已给出过一

个控制台程序的例子,下面这两个示例是我们做的一个带有用户界面的测试系统,实现对一组

数据的求和及求最大值的操作。数据我们采用自己生成的从0开始的一组连续整数,读者可以采

用自己生成的数据来实验。求最大值的操作我们前面没做讲解,读者可自行设计函数来实现这

一计算功能。相关的运行界面如图8.8和图8.9所示,该界面是采用Visual C++编写的C/S架构的对

话框程序。

图8.8 对20000个数据求和的用户界面

图8.9 在20000个数据中求最大值的用户界面

以上的实例只是我们云计算V0.01的一种应用方式,用户可根据自己的需要增加相应的功能,云

计算V0.01是个很不完善的系统,对于可并行化的问题云计算V0.01的这种做法应该是一种可行

的做法,我们更希望读者能在初步理解其结构的基础上以自己的思想开发出自己的云计算实验

系统,我们并不想以此来禁锢读者的思维。

现在很多的企业已经开始向用户提供云计算服务,一个可以实用化的云计算基础架构需用解决

许多关键的技术,云计算时代IT技术人员需要协调有史以来最大规模的服务器群,并保证整个

系统能够持续不断正常运行。云计算时代用户的大量关键数据、关键业务和关键应用被转移到

云端,因此系统的安全性、高可用性、高性能成为对云计算系统的基本要求。

现在的云计算企业良莠不齐,由于云计算平台技术是一个复杂的系统,技术涉及面相当宽,对

从事云计算研发的企业的技术实力和资金实力有很高的要求,其中真正能在现阶段进行云计算

平台研发的企业并不是太多,现阶段大量号称能提供云计算服务的企业更多的都是将自己原有

的技术和资源中类似云计算的部分称为云计算:如主机租用、网络存储等。

要实现上万台甚至上百万台服务器的协调工作,并向开发者提供丰富的API,满足普通用户和企

业级用户多样化的需求是一件十分困难的问题,所以一个可以实用化的云计算系统是一个复杂

的系统工程,甚至不是一个企业能独立完成的,它需要服务器提供商、存储设备提供商、系统

平台提供商、网络设备提供商、网络带宽提供商、应用开发商共同努力。 从Google的经验和未来服务器群的庞大规模来看,将服务器失效作为云计算系统的服务器模型

是符合实际情况的,这种情况下单个服务器可以看作是不可信的节点,在系统设计时必须要将

不可信服务器节点的失效屏蔽在系统之内,不能向开发者和普通用户传递。

本章将以不可信节点为模型介绍一个云计算基础架构的模型,我们并不奢望这一模型是十全十

美的,只是希望能为读者提供一种构建系统的思路。 9.1

云计算基础架构的应用场景

我们要设计云计算的基础架构首先要确认这一系统的应用场景,应用场景的确认实际就确认了

对云计算系统的总体要求。一个可实用的云计算基础架构一定是面向真实场景的架构,云计算

的生命力就是面向用户、以用户为中心,本章中的云计算基础架构就是以实际的云计算中心为

设计场景,这一场景主要包括以下的要点。

(1)节点数量的规模是十分巨大的,单个节点的失效概率比较大,从而整个系统出现某个节点

失效的概率是相当大的。

这一场景要求系统能对所有节点进行有效监控和协调,及时对节点失效故障作出迅速的报警, 并将故障的详细情况向管理节点汇报,作出相应的数据和计算迁移操作,保证系统的连续运行。

由于系统节点数量十分巨大,所以系统中出现失效节点的概率是很大的,正如我们前面讲过的

原理如果一个节点在一年内的失效机率为0.1%,即每1 000年出现一次失效,在有10 000个节点

的机群中一年内出现有一个节点失效的概率是1 000%,在有1 000 000个节点的机群中一年内出

现有一个节点失效的概率是100 000%,即一年内会出现1 000个节点失效,这个概率就比较大了,

平均每天有3个节点会失效。其实一个节点一年内的失效机率为0.1%是相当低的了,没有哪台服

务器能运行1 000年才出现失效的,如果这个值加大那每天将有数以百计的节点会失效。 (2)云计算中心可能跨区域地在多个中心之间整合。

由于云计算中心可能会位于不同的地方,中心之间的协调和通讯是系统必须要考虑的问题,而

且由于存在跨区域的云计算中心为数据存储提供了一个比跨机柜更为高级的跨区域数据安全保

证级别,对于安全性要求很高的数据可以提供跨区域级的数据备份,从而也就可以在重大节点

故障发生时实现跨区域的计算和存储的迁移,系统可以实现更高的可用性。 (3)用户在云计算系统上是要同时从事数据密集和计算密集的工作的,而不是单一的存储或计

算工作。

现有的很多云计算系统未实现数据密集应用和计算密集应用同时支持,而今后云计算系统在面

向多样化的用户时,不同需求的用户将在同一个系统运行和工作,有从事科学计算的、有从事

信息挖掘的、有从事简单办公的、有从事图像处理的,这些应用既有数据密集的也有计算密集

的,还有计算和数据同时密集的,所以云计算系统必须要灵活应对这种多样化的需求。 (4)一个云计算基础架构应该具备适应大量不同应用的能力,个人用户、企业级用户、开发者

都能在这个系统中工作。

大量的应用在系统中运行,系统必须要对不同的应用、不同的用户进行有效的软硬件隔离,从

而保证这些业务之间不能出现相互影响,不同用户的数据之间不能相互覆盖。 (5)非云计算基础架构的设计者和提供者是不需要了解任何云计算中心的软硬件情况的,他们

只需要对计算和存储资源按需使用,云计算中心对他们来讲只是一个随需应变的资源池。 对普通用户映射出按需提供的计算和存储资源池是云计算中的一项核心技术,虚拟化的方法是

解决这一问题的重要手段。

以上应用场景为云计算基础架构的设计提出相应的要求,在设计云计算系统时必须考虑其对应

用场景的适应性。当然我们所提供的应用场景并不是一个非常全面的场景,一个商业级的产品

可能需要考虑更为复杂的场景情况。 9.2

云计算基础架构

根据我们在上面提出的云计算应用场景模型,本节提出一个云计算的基本架构,为读者提供参

考。这一架构的框架如图9.1所示。 图9.1 不可信节点的云计算基础框架图 在这一框架下我们着力要解决以下几个问题。

(1)不可信节点出现故障时对用户的隔离。

(2)计算与存储的整合,以适应计算密集和数据密集的任务。 (3)计算资源和存储资源的虚拟化。

(4)应用层不同应用和不同用户之间数据存储和计算的隔离。

(5)应用层接口和操作系统的提供。

我们曾强调这一云计算系统是基于不可信节点设计的,框架的底层就是由大量的这类节点组成,

各服务器使用现有的主流操作系统,通过各类网络将所有的节点连接起来成为一个庞大的机群

系统,这一部分组成了云计算的物理硬件核心,这一核心的复杂性将通过云计算的软件核心层

对所有用户屏蔽。这些复杂性包括节点故障、网络故障、节点间的调度、负载平衡、数据安全、

数据存储位置、计算位置、各节点的具体配置、系统高可用性的实现等。Google的系统给了我

们良好的示范,我们在搜索框中进行搜索时同时有大量的服务器在为我们工作,但所有服务器

的工作细节我们完全不用知道,我们面对的只是一个简洁的搜索框。

这一框架中计算和虚拟化层实现对计算资源和存储资源虚拟为用户提供弹性化的计算和存储资

源。分布式文件系统为系统提供有副本策略的文件存储服务,文件存储的安全级别可分为:单

机级、跨服务器级、跨机柜级和跨区域级。该文件系统不但为系统提供了一个安全的存储平台,

而且由于其分布式和带副本策略所以可以为计算层提供存储支持,实现计算向存储的迁移,降

低数据在网络间的传递时间,并且在节点失效时可以实现计算和存储同时向备份节点的迁移, 从而在节点不可信的情况下实现系统的高可用性。虚拟化层、文件系统层和计算层构成了云计

算基础架构的软件核心层,也是现阶段我们需要主要攻克的技术层,通过软件核心层云计算中

的存储、计算和失效将被全部隔离,应用层将无法“看”硬件层的工作细节,

应用层通过云操作系统和API与云计算基础架构接口,由于其位于硬件核心层和软件核心层之 上,不同用户和应用程序在使用该平台时只能“看”到的是一台“可弹性伸缩的巨型计算机”,下

层的软件和硬件运行的细节情况都无法“看”到。

这一框架实现了云计算将所有节点的计算资源和存储资源细节隐藏于云端的功能,体现了云计

算“大象无形”的技术哲学之妙。 9.3

基于单向指针目录映射的分层用户隔离

在一个云计算平台上需要运行大量的应用程序,有大量的用户同时在一个平台上工作,他们的

任务多种多样:有个人存储业务,有企业级存储业务,有企业级应用业务,有SaaS应用业务, 有高性能计算业务。这些不同的业务需要在云计算平台上各自独立的运行而不能出现数据和计

算的交叉。由于云计算中心需要面对的应用种类、数量和规模是前所未有的,所以应用及用户

隔离技术是云计算中心需要考虑的问题。

在隔离技术上数据的隔离是最为重要的,我们提出一种目录映射的单向指针分层用户隔离的方

法供读者参考,目录结构如图9.2所示。

图9.2 目录映射的单向指针分层用户隔离

这种目录映射方法采用单向指针树状结构组织,对系统的访问权限与该应用的根目录所处的层

有关,目录节点的上层节点能获得下层节点的指针,而下层节点是不允许反向访问其上层节点

的,同层节点也是不能进行相互访问的,只有文件系统的根目录具有最高的文件访问权限,拥

有根目录权限的应用具备访问系统所有文件的权限,但为了系统数据的安全一般系统根目录权

限不会分配给任何应用使用的。所有的中间节点均只是文件夹的性质,所以只存储下一级的目

录或叶子节点指针而不会真正存储文件在分布式文件系统中的具体存储方式和位置,只有叶子

节点的数据结构才存储某一文件的具体存储位置和方式。在这种情况下每一个应用在进行文件

访问时都会从它权限所在的目录层顺着单向指针直到叶子节点才能获得该文件的存储信息。 这种文件目录组织模式有效地实现了用户数据的隔离,这种隔离是由目录映射的单向性完成的,

而不会在数据的物理存储位置进行隔离,不同应用的数据在物理存储位置上是无需采用隔离措

施的。这种模式也为每个应用创建自己的文件隔离提供了方便,因为某个应用被分配到某一目

录层以后它们下级目录可以由自己自由创建并分配给不同子应用使用,由于目录指针的单向

性,

下级目录的应用是不可能逾越该应用的目录结构的。这种自我分层可以一直做下去,这样就为

应用提供企业创造了灵活的用户管理和隔离方法,特别是类似SaaS的应用。

例如,某SaaS应用在云系统中被分配了一个空目录层作为这个SaaS应用的根目录,按指针的单

向性原则这个目录是没有访问该云系统中其他任何应用目录权限的,SaaS应用的根目录所有者

只具有创建和访问虚线内目录的权限。由于SaaS应用需要为每个用户创建存储空间,因此这个

应用会在自己的目录层下创建很多的子目录,而子目录之间也是不能相互访问的,不同的用户

之间数据也是隔离的,但SaaS应用的根目录可以实现对所有子目录的控制和管理。而SaaS应用

的子目录也可根据需要创建自己的下一级目录或叶子节点,只有到了叶子节点才会真正存储文

件在系统中的真实保存位置。这一目录分配过程如图9.3所示 图9.3 SaaS应用目录分配机制示例

其他应用的目录分配和管理与此类似,通过单向目录管理机制可以实现多种不同的复杂用户在

系统中和谐共存,使文件系统为云计算提供灵活的存储管理机制,从而适应不同的应用领域。 9.4

云文件系统的物理存储管理

当某一应用在我们的云平台上访问一个文件时,最终必须顺着指针首先访问到目录映射的叶子

节点,才能获得文件的实际存储信息。叶子节点存储着该文件的全部元数据,通过叶子节点的

信息我们可以对存储在云系统分布式文件系统的文件进行访问和处理。在云计算系统中,对于

非常大的文件往往会采用文件分块的方式进行存储,这些大文件会被系统按一定的策略分为若

干个数据块,并将这若干个数据块存储于云系统的不同节点上,相关的存储系统会写入文件目

录树中的某一个叶子节点中,为系统下次对该文件的操作提供信息,这些工作由文件系统中的

文件数据分块及副本备份策略管理来完成,该层向目录树屏蔽具体的文件分块及副本策略,只

是将最后的分配结果写入某一叶子节点中。

前面的目录树并不会实际地存储文件,所有文件真正写入磁盘中是由文件数据分块及副本备份

策略管理来完成的,只有执行了这一层的工作文件才会真正写入机群系统中完成文件的物理存

储过程。文件数据分块及副本备份策略管理层在文件系统中的地位如图9.4所示。 图9.4 物理存储管理

对于文件是否分块我们应该作具体的分析,文件大小很小的文件是不需要做分块处理的,这在

前面我们已经讨论过,Google的文件系统GFS和Hadoop的文件系统HDFS由于每个分块比较大,

只适合管理大文件并且对频繁的数据读写支持的很差,事实上无法满足云计算用户多样化的需

求。云计算的文件系统必须要考虑对大文、小文件以及频繁读写的文件同时支持策略。 9.5

云存储的安全级别划分

云计算时代个人和企业所有大量的数据不再存储在自己的硬盘中,大部分数据会通过网络存储

于云计算系统之上,数据的安全性成为了用户非常关心的问题。由于同一个云计算系统中可能

存在不同类型的客户:有企业,有个人。不同用户对自己数据的安全性要求不一,而且支付能

力也不同,所以云计算系统应该为不同用户提供不同级别的数据安全保障,体现云计算按需服

务的理念。

在应用场景中我们已经讲过云计算中的计算节点是不可信的,云计算中心可能是垮区域的,所

以文件数据分块及副本备份策略层还需要完成的任务是对文件的安全级别管理,这里的安全级

别我们暂时不考虑文件加密的问题,只要是考虑节点失效时的安全管理。在文件数据分块及副

本备份策略层的支持下文件分块后会同时在不同的地方保存文件的副本,以使系统在节点失效

时能恢复数据块,并成功重组文件。文件的安全分级方法如图9.5所示。

图9.5 云计算文件的安全分级

图中我们将文件安全级别从低到高分为单机级,跨服务器级,跨机柜级,跨数据中心级。单机

级就是每个数据块只存储在一个服务器上,这意味着只要有任何一个存储有该文件数据块的服

务器失效就会导致文件破坏,我们前面算过这个概率是很大的,所以对于分块存储的文件一般

不会采用这一级别的安全策略,但对于小型文件未实行分块存储的可以考虑采用这种安全级别。

跨服务器级就是每个数据块会在不同的服务器上做备份,当其中一个服务器失效时则自动访问

其他的备份存储块,保证数据的完成性。

跨机柜级就是数据分块及副本备份策略层在备份数据块时会自动将数据块的备份向不同机柜的

服务器存储,以防止机柜失效后破坏数据,由于机柜内的服务器往往会共用网络交换设备,一

旦网络交换设备出现故障有可能会造成整个机柜通讯终断,无法获得数据,跨机柜级的安全

略能进一步提高数据的安全性。

跨数据中心级就是数据分块及副本备份策略层会将数据块副本存储在不同地区的数据中心,两

个中心之间可能会相隔千里,这种安全级别的文件在遇到重大灾难和重大事故时也能保证数据

的完整性,这种安全级别数据存储代价较大,一般适用于银行、电信和其他核心数据等相当关

键的数据存储应用上。不同安全级别之间一般情况下是向下继承的,也就是说跨数据中心级的

安全策略同时也会实现跨机柜、跨服务器级,安全级别越高存储代价越高,费用也越高,在云

计算系统中用户可根据自己的情况定制不同级别的存储服务,数据分块及副本备份策略层将根

据定制服务的级别采用不同的策略来存储你的文件。 9.6

计算和存储的整合

存储只是人们对信息的保存,对信息的处理也是云计算时代的一个重要工作,分布式的存储方

式为实现计算向存储的迁移提供了可能。计算和存储的整合是云计算的一个特征,现在云计算

领域有很多的企业将计算与存储隔裂的观点是不妥的,没有实现计算和存储整合的系统原则上

不能称为云计算系统,当然计算和存储可以由不同的企业来提供但不同的企业之间也必须有接

口来整合计算和存储。

在信息时代我们所面对的问题中有数据密集型的问题,有计算密集型的问题,也有数据和计算

同时密集的问题,我们以数据和计算同时密集的问题为例来看在云计算中计算和存储的整合模

式,如图9.6所示。

图中分为两条线,一条中是单纯的数据读取,它的工作过程我们前面已提到:文件读取任务下

达后用户应用首先获得自己在目录结构中的权限并通过单向指针取得对下层目录的管理权,搜

索到某一叶子节点获取具体的文件存储信息,根据这一信息与相关的节点服务器建立数据连接

获得各数据块,按叶子节点的描述,用户应用将文件重组还原完成文件的读取工作。 图9.6 计算与存储的整合流程

另外一条线是带计算任务的应用,我们用这种应用来代表数据和计算同时密集的任务:系统首

先获得计算任务,该任务按第一条线文件读取的方法到达叶子节点获得各数据块的存储信息, 此时计算任务立即在文件存储服务器就地启动计算工作,完成后只向主节点传送相关结果并不

向主节点传送文件数据块,主节点汇总后生成最后的结果返回用户应用,这一过程中没有了文

件的传送和重组过程,计算和存储都在一个节点上面,实现了计算向存储的迁移,节省了数据

传输的时间,对于大文件这一策略效果非常明显。 9.7

计算和存储的迁移

在基于不可信节点的云计算系统中,我们不但要考虑计算与存储的整合,还必须在节点失效时

考虑计算和存储的迁移。一般的云计算系统(如Hadoop)实现存储的迁移,但对计算和存储同

时迁移则做的不够好,实现计算迁移的基础是数据块必须采用副本策略,这样计算迁移时才能

重新找到所要处理的数据。一般来看信息通过网络进行迁移是比较慢的,而计算的迁移可以由

系统很快完成,在有副本策略的系统中,只需要找到副本所在地,将计算迁移过去就完成了存

储和计算的迁移工作,所以效率非常高。 计算和存储的迁移操作如图9.7所示。

在图10.7中机群监控系统不断对各节点的工作状态进行实时的监控,一旦发现有节点失效立即

发出节点失效报警,通过管理节点比对当前的任务列表,如果恰好有一个计算任务在失效节点

上则进行节点失效处理,由于我们在云计算系统的采用了数据块副本策略,管理节点会根据该

节点数据块的副本存储情况按照失效处理策略找到一个存有当前处理数据块副本的节点,并在

该节点上重新启动对该数据块的处理工作,完成存储和计算的同时迁移,这样就不会造成整个

工作任务的重启。整个迁移过程由系统自动完成,用户不用干预。实现存储和计算迁移的基础

是文件的数据块必须有分布式的副本存储策略,没有副本的数据块将无法完成迁移工作。这一

迁移过程可以用图9.8来描述。

图9.7 节点失效时计算和存储的迁移图9.8 计算和数据块迁移

图9.8演示了节点失效后计算和存储的迁移,在上面数据块的迁移过程中数据块并不会在节点间

传递,所有不会占用数据传输时间,而计算的迁移可以很快的完成,因此整个迁移过程是一个

很快的过程,采用这种方法后当节点失效时就不会像MPI一样造成整个任务的终止退出。这种

迁移方法向用户屏蔽了节点的失效现象,从用户看来云计算系统是一个永不失效的大计算机。 9.8

任务的可并行性和分类分析

云计算基础平台在运营的过程中会面向不同的用户提出的不同的存储和计算的需求,有单纯信

息存储需求、有海量数据处理需求、有高性能计算需求、有用户日常信息处理需求、有图形图

像处理需求,是否采用多个节点同时来存储和处理一个问题,我们是需要考虑该任务的可并行

性特性的。如何将串行的程序进行并行化到目前为止还没有找到一个通用的方法,不同的问题

往往需要进行不同的分析,这是并行计算的软件技术一直落后于硬件发展速度的原因,同时由

于没有通用的并行化方法使并行程序能够解决的问题很少,只有少数的一些行业如气象、军事、

石油等领域有专门的计算软件,这造成了并行计算技术一直未能向普通用户普及,这一问题在

云计算技术上同样是存在的,云计算最后的成功将取决于是否满足了普通用户的需求,普通用

户需求的多样性在我们还没有找到串行程序并行化的通用规则时必须要找到另外的解决办法。

由于大多数普通用户对计算的需求相对是很小的,如文字处理、日常办公、Web应用等,这类

问题占用存储资源和计算资源相当的小,用户向云计算系统发起这类服务请求云系统完全没有

必要启用并行计算的方式来处理,根据我们的测试在计算量并不大的时候采用并行计算不但计

算时间不会减少反而由于网络通讯所用时间造成计算时间增加。对于需要较大计算量和存储量

的应用,我们就必须考虑其分布式存储和并行计算的问题了,这也是体现云计算按需提供计算

力和存储力的核心部分。为了很好地分析这类问题我们首先看一看串行程序的并行化技术。 串行程序的并行化我们现在还没有找到一个通用的模型来自动解决,对于一个计算过程来讲, 循环结构是在程序设计中出现的较多,而且是主要占用系统计算资源的一个结构,往往程序运

行时大部分时间是花在执行循环程序上了,循环次数及嵌套层数的增加会使问题的计算时间按

指数上升,成为程序运行中的主要计算瓶颈。因此研究循环程序的并行化问题是我们在进行程

序并行化工作中最为重要的一个方面。 循环结构1

for(i=0; i<1000; i++) { „;

}

循环结构2

for(i=0; i<1000;i++)

for(j=0; j<1000; j++ for(k=0; k<1000; k++) { „; }

上面的两个循环只是由于嵌套层数相差了两层,执行的时间就有可能相差大约100万倍,因此在

进行任务划分时对循环结构的处理是并行化过程中的重要一环。这当中数据之间的相关性对并

行起着重要影响。 1

.数据的相关关系和并行化

我们在研究循环程序的并行化时必需分析计算数据之间的相关性,从而讨论计算执行时的数据

划分方法。只要数据之间存在着相关关系,我们在进行程序并行化时就要特别注意。分析计算

程序中语句间的依赖关系我们称为相关分析(Dependency Analysis),语句间的相关关系可分为

数据流相关、数据反相关、输出相关3种相关关系。如语句Sj 在语句Si

之后执行,其中A、B、C、

D、E为变量,那么这3种相关关系可描述如下。 (1)数据流相关。

如某计算问题有以下两个基本语句。 Si

:B = A + C Sj

:D = B*E 其中,语句Si

的左边变量B也出现在语句Sj 的右边变量集内,且Sj 要从Si

取得其计算出的值,则称 语句Sj

与语句Si

流相关(Flow-dependent),此时Si 必须在Sj

之前执行并计算出变量B的值之后才能 完成语句Sj 的计算工作。

(2)数据反相关。

如某计算问题有以下两个基本语句。 Si

:D=B*E

Sj

:B=A+C

以上两个语句执行次序刚好和数据流相关的情况相反,语句Si 的右边变量B也出现在语句Sj 的左

边变量集内,这种情况我们称为语句语句Sj 反相关于语句Si

(Anti-dependent),这种情况下语句 Si

未取用B值之前不能执行语句Sj ,否则B值将发生改变。 (3)输出相关。

如某计算问题有以下两个基本语句。 Si

:B = A + B Sj

:B = A*E 这种情况下Si 和Sj

左边的变量一样,则称语句Sj

输出相关(Output-denpendent)于Si

考虑到以上3种相关关系,我们得到程序并行化时的一些原则。

(1)数据不存在相关关系的计算可并行执行,也可串行执行。如下面的语句Si 和Sj

,它们的数

据之间无任何相关性,我们可以同时执行这两条计算语句。 Si

:A = C + B Sj

:E = D*F

(2)存在流相关或输出相关的计算不可并行执行。 (3)存在反相关的计算,只要保证Si 中的B值先读和Sj

中计算所得到的B值后写,则允许其并行 执行。 2

.相关距离与相关方向向量

令a = (a1,a2„,an)和b = (b1,b2

,„,bn)是n层循环内的n个整数下标向量,假定a和b存在数据相关性, 则相关距离向量D = (D1,D2,„,Dn)定义为b-a;而相关方向向量d = (d1,d2,„,dn)定义为: 例如,如下3层循环嵌套: for i=l1 to u1 do for j=l2 to u2 do

k=l3 to u3 do

A(i+1,j,k-1)=A(i,j,k)+C end for end for end for

其中b=(I+1,j,k-1), a=(i,j,k),则数组A的三维迭代之间的相关距离向量D=(i+1-i,j-j, k-1-k)=(1,0,-1),

相关方向向量d=(<,=,>)。

相关方向向量对计算循环体间相关性十分有用,其相关性是通过相关方向向量而不是“=”号的外

层循环传递的,相关距离向量指明在同一存储单元的两次访问之间循环迭代的实际距离。它们

对开发并行性起到指引作用。

根据以上分析我们从任务是否并行处理的角度把云计算中的一些任务分为以下几类。 我们前面讲到计算和存储整合,数据块的副本等问题,其实在一个云计算系统并不是所有的数

据和任务都要分布式的存储或分布式的计算,对于类似日常办公应用来说,由于数据量小,计

算量也小,对于这类应用中的数据我们没有必要对文件执行分块操作,也没有必要对这类数据

的处理启用并行计算方法,而对于高性能计算和搜索引擎服务来说就必需采用分布存储及并行

计算才能有效地完成该任务。所以对云计算系统所驻留的各项应用我们在接入时就要分类,不

同分类的应用系统在执行时采用不同的处理方式,而不是所有的应用全部采用分布式和并行计

算方式来处理,这样处理会大大降低系统设计的难度,大量普通用户的常规应用将走常规的系

统资源分配方法向其提供服务,只有对于部分计算密集或存储密集的任务才采用复杂的计算和

存储的整合技术进行处理。 9.9

简化的服务器级粗粒度计算和存储资源分配方案 任务类型数据量计算量是否并行计算是否分布存储 日常办公应用小小否否 单纯存储应用大小否是 高性能计算大大是是 SaaS应用大小否是 搜索引擎大大是是

信息服务大小否是

我们前面所讲的计算和存储的分配是一种较为复杂的分配方案,本节我们提出一种简化的服务

器级粗粒度计算和存储资源分配方案作为前面方案的补充。对于采用类似Google服务器这样廉

价服务器的系统可以以单个服务器作为最小的资源分配单元,完成粗粒度的资源分配,对于被

分配了多个任务的服务器由操作系统负责在单个服务器上的调度,这一点现有的操作系统已经

很好了。由于服务器的价格可以被控制很低,这种分配方式可能大大降低虚拟资源池的技术难

度,底层硬件级的调度交由操作系统完成,服务器级的粗粒度调度由云计算系统负责,云计算

系统负责监控整个系统的计算和存储负载情况,并向发起资源请求的用户转让服务器的控制权,

目前用户大多数的资源请求单个低端服务器(如图9.9所示)应付应该卓卓有余,真正需要采用

机群来解决的问题并不是很多,计算密集问题可采用特殊对待的方式来解决。 图9.9 我们研制的低端云计算服务器

对于信息存储请求,系统根据信息的安全级别做不同数量的备份,对于一般应用不再做文件的

分割,这样不但能提高数据的安全性,也为客户的数据访问提供并行的数据访问通道,文件的

存储信息和元数据由云计算系统负责维护,并根据负载情况向用户分配服务器资源。安全级别

高或并发访问要求高的文件将采用更多的节点对其进行副本备份,管理节点在用户访问请求提

交后检查自己的文件存储信息,将其中一台存储有用户请求数据的服务器信息传递给用户,由

用户直接访问该服务器并获得该服务器的计算和存储资源。由于同一个文件被存放在多个服务

器上,不同的用户访问同一个文件时会根据负载情况被指引向不同的服务器,这样可以实现对

文件访问的跨用户级并行数据传输。这一简化方案避免了文件分割和重组时的时间开销,由管

理服务器来负责对系统进行协调,可以有效适应视频播放、游戏等应用的需要。对于一些特殊

的应用需要计算向存储迁移时,本方案可由管理节点向用户返回所有存储有该数据副本服务器

的信息,并协调各服务器对数据的不同部分进行分布式的处理。这一方案并不会增加对存储空

间的要求。

图9.10描述了这一方案的基本情况,将单个服务器作为最小资源分配单元后,该方案使传统的

操作系统和云计算系统的任务划分非常明确,云计算系统不担负对单个服务器硬件底层虚拟化

和调度的工作,因为这一点传统的操作系统已做的很好了(如任务调度、分时并行),云计算系

统只负责跨服务器级的粗粒度资源的管理和虚拟化,在节点失效时管理节点也能将任务迁移

其他的备份服务器,保证服务的正常进行。

图9.10 服务器级粗粒度计算和存储资源分配方案示意图

这种架构做到最后有可能每个节点不再是一个传统意义上的服务器,而只是由单片机系统组成

的计算单元,如图9.11所示。现在的单片机系统甚至可以顺畅地支持客户的视频播放请求,这

种方法将每个单片机模块作为基本的资源单元,进一步降低了单个资源请求的费用。这些单片

机模块可以像砖块一样根据需要进行堆叠,系统的可扩展性可以得到空前的提高,而硬件虚拟

化的技术难度可以大大降低,云计算系统只负责在服务器的粒度上对资源进行分配和管理,完

成资源池的粗粒度分配。

图9.11 廉价服务器和单片机堆叠示意 9.10

数据的云计算系统之旅

为了了解云计算基础架构的工作原理,本节以一个文件数据的视角和感受在云计算系统中作一

次快速的旅行(如图9.12所示)。这趟旅行会让大家对云计算有一个全新的认识,我们假定这个

文件数据是要用于计算的一组海量数据。下面是这组数据的旅行日记。 图9.12 数据的云计算系统之旅

我一直生活在普通的数据中心,这次是我第一次在云计算系统中工作,心里充满了好奇和担心。

当用户按下存储按钮时我就开始了自己在云计算系统中的旅行。

首先我碰到的就是系统的分类管理模块,他将我标志为需要分割存储的数据类型,看来我要被

大卸八块了,我害怕极了。

系统将我带到了文件系统中的存储模块,存储模块按照存储策略将我分为了很多小的已编号的

数据块并将分割信息存储在了一个表中,于是属于我的各个小数据块穿过服务器、机柜和网络

到达了系统的不同地方,根据存储模块的安排我们在系统中多了许多相同的拷贝,我想这个云

系统真是浪费,这得多要多少存储空间呀。不过虽然我被分为很多小块存在不同的地方但文件

系统使用了障眼术,我的用户并不知道刚才发生的一切,他看到的还是一个完整的我。 我在系统中呆了没多久,突然文件系统通知我有任务了,原来我的用户需要访问我并计算出他

所需要的结果,于是我的各个数据块立即行动起来准备重新组合,这是我以前的经验,然而系

统却未让我们行动,而是由计算和存储整合模块将一段程序派到了我各个数据块存储的地方直

接进行计算,这样真省事,按以前的做法以我这么庞大的身躯光数据传送就要花很长的时间, 还要走很远的距离,云计算系统真是服务上门呀!

计算程序正在忙着工作,系统突然响起了警报声,我们都吓了一跳,发生了什么事呀?原来是

存储我的一个数据块的服务器坏了,系统管理员正在更换维修,看来前面的工作白做了,就等

着服务器修好重做一次吧,少不了要挨用户一阵批评。

然而我迟迟没有得到停下来的命令,计算和存储整合模块已经以很快的速度向我的这个数据块

副本所在的服务器派出了计算程序并早已开始工作,不到一会儿对所有数据块的计算就完成了,

我们向系统汇报了各自的计算结果,系统汇总计算后就发给了我的用户,看他的样子他根本不

知道刚才发生了系统故障,我暗自高兴。

这时我才知道文件系统为什么会生成那么多我的副本,原来有这么重要的作用。看来我已经习

惯呆在云计算系统了,在云中的感觉确实非常好。

云计算技术的提出为人工智能提供了新的技术实现方法,然而云计算并不是解决人工智能问题

的终极技术,自然界是一种指数级复杂度的信息系统,只有具备适应指数级计算扩展能力的计

算系统才可能是终极的计算技术,云计算系统从计算架构上看还只是一种具备线性计算扩展能

力的系统,这一点与传统的机群技术并没有太多区别,计算能力的扩展只能依赖计算节点数目

的蛮力扩展,这种扩张方式是无法解决指数复杂度解空间搜索任务的。不确定性技术的采用以

及不确定性机群计算有可能会提高云计算系统计算扩展能力,本章将讲解云计算与智能的关系

以及一些新的智能算法。 10.1

云计算的智能与人类智能的比较

云计算架构的核心问题就是计算与存储,云计算将计算与存储集中到云计算中心,这种做法其

实就是构造一个超级的智能的体。智能产生的原因就是海量的存储和高速的运算,这两者缺一

不可。人类智能的出现也是由于大脑具有的信息存储和在信息存储基础上的信息处理能力。因

此云计算是具备一定的智能特征的(如图10.1所示),所以我们说云计算技术是实现智能的一种

新的技术方法。

图10.1 云计算与智能

从图中我们看到云计算和智能总的框架是几乎相同的,从目前的技术发展来看最大的差别来自

于计算部分,智能体的计算通常都是一种不确定性计算模式,具备完成指数复杂问题计算的能

力,但并不是一种精确的计算,这是符合自然界的运行规律的,而云计算系统的计算是一种精

确性的计算,当遇到指数复杂度问题时是无法解决的。云计算和人类智能的对比有以下几条。 (1)人类智能在大脑细胞单点失效时是不会受到很大影响的,云计算在计算和存储节点单点失

效时也是可以保证正常运行的。

(2)在进行信息存储时人类大脑会自动对信息的重要性分级,非常重要的信息级别很高,因此

很难被遗忘,即使在多年以后都能记忆犹新,而普通信息则相对遗忘很快,如大街上随机路过

人的长像,我们几乎过目就忘,因为这类信息的安全级别很低;在云计算系统也有类似的信息

分级,对安全级别很高的信息会做大量的备份,甚至是跨区域的备份。

(3)人类大脑的信息处理机制通常是非精确性的不确定方法,如我们对人相貌的识别;而云计

算系统的计算机制一般是确定性的精确计算方法,但可以通过采用人工智能算法模拟人类的运

算机制,但目前还做的并不好,特别是从系统架构上云计算系统还是一个确定性的系统。 (4)人类智能能完成指数级复杂度问题的非精确求解,云计算系统还无法实现。

(5)人类智能将存储和计算完美地整合在一起,几乎可以说是融为一体的;而云计算在计算和

存储的整合上一直是一个需要解决的问题,目前实现的并不好。 (6)人类智能在海量信息和高速计算的基础上能实现创新意识;而云计算系统在海量信息和高

速计算的基础上却完全没有创新计算能力,这可能也是由于其计算的确定性造成的。 (7)人类高速计算的源泉是不确定性导致的隐含并行性;而云计算依靠的计算节点的并行性。 云计算是将计算设备隐于云端,而人类的智能却是将计算本身隐藏起来,真正是大象无形。 以上分析和对比可以为设计更先进的云计算架构提供帮助,如果模拟人类智能设计基于不确定

理论的云计算系统,有望能进一步提高云计算系统的应用能力。 10.2

云计算提升终端智能

云计算的出现为实现智能计算提供了一种方便的做法,云计算中心强大的计算力和存储力为实

现终端的智能提供了保证。特别是对于很多的“笨终端”,如手机、嵌入式系统、家用电器等, 由于自身的计算能力和存储能力有限,要实现强大的智能几乎是不可能的。人工智能的实现除

了算法的设计之外还需要依赖强大的计算能力和存储能力,智能计算需要对庞大的解空间进行

搜索,由于组合爆炸的原因,使很多智能计算问题都是指数复杂度的问题,即使对算法进行了

优化依然需要大量的计算才能获得结果。实现智能的另一个方面是大量知识的发现和存储,

多智能系统的实现都需要海量知识数据的支持,数据挖掘技术就是一种典型的知识型智能,它

从海量的数据信息中发现有用的知识和规则,所以知识的获取是建立在对大量数据分析的基础

上的,因此这一技术的实现需要有庞大的存储系统支持,对于大量的“笨终端”来说实现庞大的

信息存储是不现实的。

云计算系统具备了智能体的两大特征:强大的计算能力和存储能力,人类的智能也来自于人的

大脑高速的计算能力和海量的信息存储能力,因而云计算系统事实上构成了一种“智能体”,这

种“智能体”在云计算模式下可以通过网络向各类用户提供智能服务,云计算技术的使用为“笨终

端”提供了几乎无限的计算能力和存储能力。今后我们使用的手机、家电等系统将可以依赖云计

算系统实现智能水平的飞跃。

“云家电”等概念将成为云计算改变人们生活的例证,所有“云家电”的大脑都在云家电中心,家

电的工作状态都在云家电中心的监控和管理之中。一般来讲很多家电都是一种嵌入式的系统, 传统家电的智能水平是很弱的,数据的存储能力更是非常小,有了云计算系统的支持,家电的

智能将主要来自于云计算中心,所有的家电终端通过网络与云计算中心进行信息的沟通,向云

计算中心传递当前的工作状态,利用云计算中心的强大计算力和存储力为终端提供智能计算支

持。有的厂商甚至会开发出专门用于云计算的“笨终端”——“云终端”,这种终端计算能力相当

的弱,只负责和用户进行交互,几乎所有计算都提交给云中心完成,今后终端智能的实现方式

如图10.2所示。

图10.2 云计算时代的终端智能

各种终端在云计算时代将从云计算中心获得前所未有的计算和存储支持,为实现大量的高复杂

度的应用提供了可能,许多终端的运行模式将发生很大的变化,有可能会造成很多相关产业的

变革。云计算变革的火种将从计算机领域燃向其他各相关产业,如家电产业、通信产业、工业

控制等领域。 10.3

云计算智能与Monte

Carlo 方法

我们在前面讲MPI时已提出过采用Monte Carlo方法计算积分和值,其实Monte Carlo方法

在人

工智能算法中的应用是十分广泛的,我们讲过人类智能的产生来自于运算的不确定性,所以几

乎所有的人工智能算法都采用了Monte Carlo方法来构造一个不确定的算法体系来模拟人类大脑

的计算机制,如遗传算法、蚁群算法、模拟退火算法等。

由于Monte Carlo方法是一种随机的方法,因此特别容易实现在节点间的并行化,各节点可以相

对独立地运行,对于云计算系统实现计算和存储的整合特别有利。任何一个属于蒙特卡罗方法

的应用都可以运行在云计算环境中。人类智能同样也选择了不确定性的方法,实现了隐含并行

计算能力,具备了强大的智能。Monte Carlo方法是一个典型的可并行化的方法,精确度的丧失

换来了计算的并行性,高的精确度和高的隐含并行计算能力是不能同时达到的,类似于物理学

上的测不准关系,这个原理也可称为计算的测不准关系,这是大自然给我们计算机科学设置的

不可逾越的边界。

既然智能算法大量采用了Monte Carlo方法,而Monte Carlo方法又是一种可并行化的算法,可并

行化的算法可以充分发挥云计算系统强大的计算和存储能力,智能算法在云计算时代会有很好

的应用前景。

遗传算法就是一种典型的采用了Monte Carlo方法的算法,种群的进化过程可以在各个计算节点

独立地进行,节点间的信息通信量是相当小的,各节点的计算能力得到充分的利用,并且由于

Monte Carlo方法的采用使遗传算法具备一定的隐含并行计算能力。下面我们要讲到的一种智能

算法也是采用了Monte Carlo方法,有实现在各节点独立计算的能力,适合在云计算系统中实现 智能。 10.4

云计算时代不确定性智能算法示例—— 模拟谐振子算法

智能的产生与随机数和不确定性有着神秘的联系,Monte Carlo方法对随机方法的采用使算法有

了很强的并行化能力。对于自然界的模拟其实就模拟实现自然界对信息指数级的处理能力,这

类算法包括遗传算法、蚁群算法、模拟退火算法、量子算法,有时将这些算法通称为自然算法,

这类算法都不同程度使用了随机方法。单靠自然选择原理自然界很难出现高级智能生物,自然

界自身的指数级信息处理能力才是更为根本的原因,所以大量的智能算法都采用模拟自然界的

策略。这类智能算法由于具有良好的并行化能力有望成为云计算系统的一个重要应用领域,了

解这类算法可以为我们在架构云计算系统提供新的思考方向。本节将介绍一种我们近期提出的

新的智能算法——模拟谐振子算法。

模拟谐振子算法(Simulated Harmonic Oscillator,SHO)是模拟自然谐振子运动的物理规律而演

化的一种通用的随机搜索算法。此算法既具有局部搜索能力,又具有全局搜索能力。它在整个

解空间范围内广泛随机搜索近似最优解,而且以一定的规则接受差解,使邻域解在局部山峰间

平行跳跃,从而有效地控制了算法在全局范围内搜索的随意性,也成功地避免了算法陷入局部

搜索的陷阱。 10.4.1

简谐振动的描述 1

.经典谐振子

模拟谐振子算法的思想来源于力学中的简谐振动。一个简谐振动就是一个系统。做简谐振动的

物体的加速度跟物体偏离平衡位置的位移大小成正比,方向与位移的方向相反,总指向平衡位

置。即简谐振动遵守虎克定律:

其中称为倔强系数,取正值; 是系统所受的力,称为恢复力。图10.3为简谐振动的模型图。 图10.3 简谐振动模型图

图10.3中描述了简谐振动的3个特殊状态。第一个状态为弹簧质点在正中央的平衡点(振源), 此时质点的受力、加速度和位移皆为0,但质点的速度最大;第二个状态为弹簧质点受到向右的

恢复力F,而向左移动,恢复力大小沿平衡点到左端点的方向是逐渐增大的,加速度也是逐渐增

大,但与速度方向相反,速度在平衡点时最大,速度沿此方向是越来越小,当质点到达左端点

时速度减为0。第三个状态与第二个状态关于平衡点对称。 根据牛顿第二定律的简单计算,我们能得到以下结论。 (1)振动频率。 其中,m为谐振子质量。 (2)动能。

其中A为振幅和F为相位。 (3)弹性势能。 (4)系统总能量为定。 2

.量子谐振子

如果我们采用量子物理的眼光来看谐振子,也就是微观振动,谐振子的Schrodinge方程可写为

令: ,

则Schrodinger方程的解为:

图10.4描述了谐振子在不同能级下的波函数图像。 图10.4 谐振子量子波函数图像 为Hermite多项式。

谐振子的能级分布为:

当谐振子系统位于能量最低的基态时波函数为高斯函数,此时可认为解将会以高

斯分布方式出现,所以我们的算法系统最终就是要达到系统基态,这样找到的解才最有可能为 最优解。

根据以上的描述,我们将算法分为了经典振动过程和在基态附近的量子振动过程,经典振动过

程主要完成在大区域的解的搜索,量子振动过程主要完成在基态附近向最优解的趋近,使系统

尽可能处于能量最低的状态,这样最优解才会以高斯分布的概率出现。这是我们对谐振的算法

的物理理解。 10.4.2

模拟谐振子算法描述

在简谐振动的数学描述中已证明系统总能量为:

在这里,系统总能量分为两部分:势能与动能。单独考虑弹性势能,弹性势能的取值范围应该

为,任意一个时刻的弹性势能大小为。当弹簧质点在平衡点时,弹性势

能最小为0;当弹簧质点在任意一个端点时,弹性势能最大为系统总能量。由于系统弹性势 能的大小与弹性质点离平衡点的相对距离成正比,由此联想到:可以根据弹簧质点到平衡点的

距离,将系统划分为多个能量等级,如图10.5所示。 图10.5 简谐振动弹性势能变化

由于简谐振动系统中,弹簧被压缩与被拉伸的过程中弹性势能变化是关于平衡点对称的,为了

便于分析考虑,这里只研究弹簧被拉伸的情况。

在图10.5的简谐振动系统中,假定振幅为A,系统的势能被划分为A个等级,每个能级间距为一

个单位长度,设某个位置状态的势能能级用表示,其中下标表示某个能级处质点离平衡点 的相对位移。

从平衡点到右端点的势能能级大小依次为: , , , „ , ,

将势能能级进一步转化,投影到(0,1)单位区间上,即势能能级同除以: 从而推知单位势能能级’为:

, , ,

„, , „,

两个单位势能能级之间的差值称为能级差,依次为: , , „ , „

从能级差值可以推知,从端点到平衡点,相邻两能级的能级差是逐渐减小的,如图10.6所示。 图10.6 弹性势能能级差变化

在弹簧质点与平衡点的距离成等差数列形式变化的情况下,简谐振动系统的能级势能却是以 递减的方式进行的。离平衡点越近,能级差越小,反之,能级差越大。

简谐振动系统中,弹簧质点由端点运动到平衡点的过程中,质点的位置状态与势能状态一一对

应,而且质点的运动是连续的,所以质点一定会经过系统的每一个位置状态,必将遍历系统的

整个势能空间。如果将质点的位置状态对应于优化问题中的某个解状态,则理论上通过遍历所

有质点位置状态可以遍历优化问题中整个解空间,且收敛性为1,必能求得最优解。 假设求解一个计算问题,将整个解空间投影于图10.6的空间上。则每个能级差区域内含有多个

过程解,每个能级差区域的大小从右至左也是逐减的,且遵循简谐振动中能级差的划分规则, 但是所有的过程解的大小是杂乱无规律可循的。这样就完成了简谐振动系统中质点的位置状态

与计算问题的解状态对应的关系。在算法的初始化阶段通过指定次数的简单的随机抽样计算目

标函数,确定近似最大解与近似最小解,两者相减的值f即为此问题的解差,此解差f 对应于简谐振动中的最大势能UA

。在整个解空间随机求出两个解和, 的

值可以表示两解之间的相对距离,将此差值投影于单位长度上,即进行处理,假定

是当前近似最优解,在不断的计算中会不断地靠近最优解,最优解对应于简谐振动中的基 态,所以可以近似地看成新解与最优解之间的距离,而就是在单位长度

上,新解与最优解的相对距离。确定了新解的能级区间,就可以确定新解的优劣,从而确定了

对新解的选择策略。

在谐振子算法中当步长大于Ls

的阶段, 若新解比旧解差时, 即时, 算法在 时接受新解。其中可近似看作谐振子的最大势能。

表10.1描述了一个组合优化问题的求解过程和简谐振动过程之间的对应关系,我们的算法设计

就是基于这一类比的。

表10.1 模拟谐振子算法与组合优化问题的关系 10.4.3

模拟谐振子算法流程

将弹簧质点的位置坐标对应于问题的解,振幅大小对应为问题的解空间范围,势能U对应为目

标函数值F,谐振子基态对应问题获得最优解时系统的状态。模拟谐振子算法就是模拟谐振子的

数学描述优化问题模拟谐振子算法 随机抽样解位置状态 评价函数目标函数势能函数 最佳抽样最优解基态

整个样本空间抽样整个解空间最大能级处 变换抽样空间邻域解空间能级改变

运动方法获得问题的解:首先可以随机或是利用人为先验知识确定初始解S,振幅A和初始步长 L0

均依赖于具体问题而定,然后对当前解重复过程:“产生新解→计算目标函数差→接受准则判 断→是否调整步长\\接受准则”,算法终止时的当前解即为所得的近似最优解。 模拟谐振子算法的计算过程分为3个阶段,第一个阶段为在解空间以一定的次数查找端点和振

源,即近似的最差解和最优解,从而获得系统的近似最大势能。后两个阶段以算法所定义的基

态步长LS

为分界线:步长大于基态步长时为宏观搜索阶段,对应于物理学中的经典谐振子的振 动,采用接受准则对差解进行取舍,这一阶段的步长在范围

内生成,不同问题步长的生成方法不同;步长小于基态步长时为微观搜索阶段,对应于物理学

中的量子谐振子的振动,这时算法对差解采用直接抛弃的策略,系统总体处于平衡态附近的量

子振动状态,算法不会再在解空间做大的跳跃。这里的步长是一个逻辑单位,最小为1,代表一

个最小的变化单位,在旅行商问题中步长的作用主要体现在新解的生成环节。 1

.模拟谐振子算法的基本步骤

第一步:初始化,振幅A,初始步长L0 ,基态步长LS

,步长变化规则。

第二步:在一指定的循环次数下,随机生成解,确定谐振子端点End和振源Init,目标函数值最

大的为端点,最小的为振源。

第三步:产生新解,计算目标函数增量,其中为目标函数值。 第四步:阶段Ⅰ经典振动阶段,步长范围为,则接受准则如下。 若,则接受新解为当前解,并记忆最小解;

若,且,则接受新解为当前解;否则,抛弃此新解。

如果未完成指定的计算步骤,变化当前步长L,范围为,转到第三步。

第五步:阶段Ⅱ量子振动阶段,步长,替换最小值为当前解,接受准则为:

若,则接受新解为当前解;否则,不接受

第六步:对于量子振动阶段若满足终止条件,则输出当前解为近似最优解,结束程序。 2

.算法说明

(1)初始化振幅A和初始步长L0 ,振幅对应问题的规模,初始步长L0 划分问题的能级,通常设 为振幅的倍数。基态步长Ls 为小于初始步长L0

的整数,通常取值较小。步长的变化规则依赖于

具体问题而定。在这里步长为一个逻辑概念,并不是指具体的长度。

(2)算法通过随机生成指定数量的解,代入目标函数,值最小的作为振源,值最大的作为端点。

(3)产生新解的方法有很多,如2?opt、3?opt、随机两两交换法、随机插入法等,在TSP问题

中不同的阶段新解生成方法不同。

(4)目标函数的选取依赖于具体的问题。如在旅行商(TSP)问题中目标函数选取为所有城市

间的距离,在连续和非线性优化问题中目标函数选取连续和非线性函数值。

(5)接受准则依据当前所处的不同阶段,即步长L范围的不同,而采用不同的接受准则和不同

的产生邻域解方法。阶段Ⅰ可以看成全局范围内的横向搜索,这时步长大于Ls ,系统生成

区间的一个步长, 这一阶段的计算次数由用户指定。这时的接收准则采用 来完成,阶段Ⅱ可以看成局部范围内的纵向搜索,这时系统处于能

量较低的状态,算法采用直接抛弃差解的策略。

(6)步长的变化由步长变化规则而定,步长变化规则依具体问题而定。因为简谐振动存在周期

性,所以步长变化并不遵循递减或递增的方式。在TSP问题中,步长的变化规则在第I阶段是在

范围内随机生成,而在连续和非线性优化问题中步长变化是逐步衰减的。终止条件一般 取为连续若干个新解都没有被接受时终止算法。 模拟谐振子算法的计算流程如图10.7所示。 图10.7 模拟谐振子算法流程 10.4.4

模拟谐振子算法分析 1

.算法参数的初始化

模拟谐振子算法的初始化主要包括:设置振幅A、初始步长L0 和基态步长Ls

,确定步长变化规则

以及确定谐振子端点End和振源Init。

在简谐振动系统中,振幅A是个已知参数。在模拟谐振子算法中,根据问题的不同,振幅A的选

取也不同,但振幅选取也应是问题的已知条件。例如,在TSP中,振幅取值为问题的规模(城 市个数);在连续和非线性优化问题中,选取某个变量的取值范围为振幅。

确定了振幅,也就确定初始步长,初始步长的取值一般为振幅的倍数。根据初始步长的大小来

划分势能能级。基态步长应取接近于0的正整数。一个步长对应一个能级差。

若将整个解空间看成简谐振动的一个周期,则步长应该逐步衰减。而简谐振动是具有周期性的,

若将整个解空间看成简谐振动的多个周期但非重复性取值,则模拟谐振子算法的整个解空间仍

然为一个完整但不重复的解空间。那么,步长可以为随机步长,即步长变化可以为不规则跳跃,

也可以逐步衰减。在实际应用中,步长的衰减方式依具体问题而选择。

谐振子端点和振源都是由随机产生的一个初始解,经过次数的随机取解而粗略确定的。在此计

算的过程中,最大的目标函数值对应的解即是端点,最小目标函数值对应的解即是振源。端点

模拟的是最大能级,振源模拟的是初始近似最优解,算法的其余步骤会逐渐校正近似最优解。 2

.新解产生的方法

产生新解的方法有很多。根据求解目的的不同,搜索策略不同,新解的搜索邻域也不同,相应

的产生新解的方法也不同。模拟谐振子算法使用的方法有:均匀随机法、2交换(2-opt)法、两

两随机交换法、随机插入法。模拟谐振子算法的随机性主要体现在新解的产生上。

均匀随机法使用在确定端点和振源的过程中。端点和振源是在整个解空间内确定的,分别代表

着整个解空间内的最大值和最小值。首先在全局范围内随机产生一个初始解后,由于新解的邻

域是整个解空间,需要在全局范围内以等概率的形式产生一个候选解。在整个解空间以等概率

产生的新解的方法称为均匀随机法。

从初始步长到基态步长之间,使用的是2?opt法产生新解。假设有一个序列{1,2,„,n},定义其

所有可能的排序为整个解空间。随机产生1和n之间的两个相异的数u和v作为逆序的两个端点,

对u和v之间的序列做逆序处理,序列长度即为步长,若原序列{1,2,„, u, u1 ,u2 ,„„ v2 ,v1 ,

v,„„,n}变为: {1,2,„, v, v1 ,v2, „u2 ,u1

,u,„,n}

这种逆转u和v及其之间的子序列顺序而产生的新序列的方法称为2?opt法,其中u和v为小于序列

长度的正整数。其中两随机数u和v之差对应当前步长,关系式为: 。

随机两两交换法与2?opt法相似,只交换两个随机数u和v的位置,而不用逆置u和v之间的子序列。

随机两两交换是当前步长为2时采用的邻域解搜索方法。

当前步长为1时,随机插入法搜索邻域解。随机插入法同样随机产生1和n之间的两个相异数u和v,

将位置u处对应的元素插入到位置v处,从而产生新解。 3

.谐振能级接受准则

模拟谐振子算法采用了一种新的接受准则——谐振能级接受准则,判断新解是否被接受。谐振

能级接受准则控制着算法的收敛方向,是模拟谐振子算法的核心所在。谐振能级接受准则如下 式:

其中Ls

是基态步长,L0

是初始步长。为新解与当前解之间的势能函数差(在最小化问题中)

或当前解与新解之间的目标函数差(在最大目标函数中)。End为端点, 为端点对应的 势能,s为当前解, 为当前解对应的势能。 L0

对应着能级最大处,也就是L0

值的大小代表着整个势能空间范围,Ls 代表着某一个较低的低能

能级,Ls

的大小代表着从基态到基态步长间能级总和,称作近似基态能级。理论上近似基态能 级的势能大小接近基态势能大小。表示近似基态能级占整个势能的比例,这里的平方是 因为势能是与距离的平方成正比的。之差可以近似为整个势能空间范围,

为新状态的势能, 为当前解对应的势能,因为当前解是算法运行到此刻的最好解, 可以近似为基态,称为伪基态。是新解与伪基态的差值,可以看成新解势能 与基态的能级差。如果,即新解与整个势能的比例小于近似基态能

级占整个势能的比例时,接受新解。换句话说,如果新解相对势能在近似基态能级范围内,则

接受新解,即使新解比当前解差。这时新解从能级上讲比旧解处于更底的能量,符合我们的算

法寻找系统基态的目标,因为系统的基态正是最优解所在的位置。 4

.算法优点

模拟谐振子算法巧妙地将简谐振动思想应用于求解复杂问题,实现简单、易行,且具有通用性,

并且算法的时间代价小。

模拟谐振子算法将整个解空间划分为多个逻辑能级,能级越高,解的邻域搜索范围就越大;能

级越低,解邻域的搜索范围就越小。从最高势能能级到近似基态能级之间对解的搜索可以看作

对解空间进行全局范围内的搜索(全局搜索),同时能快速地收敛于近似基态,在局部山峰间以

一定的概率平行跃迁,从而很好地解决了搜索陷入局部陷阱的问题,但又不会跳离局部搜索增

加全局范围内的无效搜索,它只会从一个局部山峰跳跃到另一个局部山峰,对局部山峰群的搜

索也是全局搜索能力的一种表现,所以此算法兼顾全局搜索与局部搜索能力。

简而言之,模拟谐振子算法既可以完全横向地搜索局部山峰,而且可以对各个局部山峰进行纵

向深入搜索,将全局搜索与局部搜索完美结合。 10.4.5

模拟谐振子算法应用于旅行商问题

本节主要将模拟谐振子算法应用于旅行商问题的求解,验证该方法的可用性、通用性和实用性。

这一算法可以成功地应用于离散的和线性的优化问题——旅行商问题,而且完美地解决了连续

的和非线性优化问题——多变量函数求解问题。 1

.旅行商问题描述

旅行商问题(Travelling Salesman Problem,TSP),国内习惯称为货郎担问题。此问题起源于

EULER提出的骑士旅行问题,TSP是近代组合优化领域的一个典型难题。TSP问题已由Gaery证

明是一个NP问题,是一个具有广泛应用背景和重要理论价值的组合优化问题。

TSP是给定n个城市和每两个城市间的距离,任选一个城市出发,遍历所有的城市并回到起点城

市,每个城市不能重复,求所有可能路径中最短的路径。最早的旅行商问题的数学规划是由 Dantzig等人于1959年提出的。

设是距离矩阵,其元素表示城市I、j间的距离,则对变量D的约束如下。 (1)每个元素是非负整数。 ;

(2)对角线上的元素为0。 ;

(3)是对称矩阵。 ;

(4)任意三个元素满足三角不等式。 TSP的一个解,可表达为一个循环序列 整个解空间S为:

S={n个城市的所有循环序列}

解空间规模为。

路径长度f(w) = ,且。

路径长度是TSP的目标函数,TSP问题的目的是求最短路径,即求。

由于TSP可能路径数为,以路径间的比较为基本操作,则需要进行基本操作数是 。用运算能力为1M flops(每秒一百万次浮点运算)的计算机进行遍历求解,在n=10 时只需0.18s,而在n=20时,需用1929年才能找到最优解,如表10.2所示。 表10.2 TSP中规模与计算时间关系表

注:表中数据是用1Mflops计算机算出的。 2

.模拟谐振子算法求解旅行商问题

由表10.2可知,如果通过遍历求解一定规模TSP的最优路径,时间代价是惊人的。所以求解NP

问题时,常常是采用优秀的算法特别是模拟自然界的智能算法求近似最优解。时间代价和近似

解的精确度是衡量一个智能算法的优劣最重要的两个指标,这里在应用模拟谐振子算法求解 TSP问题上,也从这两个指标入手进行分析。我们的TSP数据来源为TSPLIB。 3

.谐振子算法求解旅行商问题程序分析

我们用Visuod++语言给出了模拟谐振子算法有关的各个过程,主要包括计算路径函数、初始确

定端点和振源函数、步长大于基态步长的新解接受函数、步长为2时的新解接受函数、步长为1

时的接受函数。

(1)计算路径距离函数,在TSP问题中就目标函数。

程序10.1

int HarmonicOscillator::Distance(int (*s)[CITY_NUM],vector x_new) {

int sum;

vector::iterator pst,ped; sum = 0;

n 10 30 50 80 100

计算时间0.18s 1.4×1015世纪9.6×1046世纪1.4×10101世纪1.5×10140世纪 /*计算尾和头的距离*/ pst=x_init.begin(); ped=x_init.end()-1; sum = s[*ped][*pst]; //计算所有城市间的距离 pst = x_init.begin(); ped = x_init.begin()+1;

for(;pedsum = sum + s[*pst][*ped]; }

return sum;

}

此函数用来计算TSP问题中某一序列的路径距离,即算法的目标函数值。两个参数分别是路径

矩阵和产生的路径。返回值为此路径序列的距离,即新解的目标函数值。 (2)初始化端点和振源函数。 程序10.2

void HarmonicOscillator::NewSort(int (*s)[CITY_NUM]) {

int i=0,j,flag,tmp; int sum,tmp_endValue;

multimap mtmp;//用map自动排序,属于临时容器 vector tmp_x,tmpend; vector::iterator pst,ped; multimap::iterator mpos; multimap::iterator pos,lp,rp;

int n=0;

for(i=0;imtmp.insert(make_pair(rand(),i));

}

for(i=0,mpos=mtmp.begin();mpos!=mtmp.end();i++,mpos++) //排完序后,插回x_tmpopt {

x_init.push_back(mpos->second);

}

x_opt = x_init;//x_opt为类的公有变量,表示近似最优解,x_init表示当前振源 sum = 0;

sum = Distance( s, x_init);

x_optValue = sum;//x_optValue为类的公有变量,表示当前解的目标函数值 x_endValue = sum;//x_endValue为类的公有变量,当前最大解的目标函数值 x_tmpValue = sum; /*计算振源与端点*/ tmp = 0; flag = 1; i = 0;

j = 0;

while(imtmp.clear();

pst = x_init.begin();

for(i=0;imtmp.insert(make_pair(rand(),*pst++)); }

for(i=0,mpos=mtmp.begin();mpos!=mtmp.end();i++,mpos++) {

tmp_x.push_back(mpos->second);

}

/*计算刚得到的一个新振源的目标函数值*/ sum = 0;

sum = Distance(s, tmp_x);

if(x_optValue>sum || x_optValue==sum) {

x_optValue = sum;//得到振源对应的目标函数值 x_init = tmp_x;//得到振源 x_opt = tmp_x; i = 0; } else { i++;

if(sum >tmp_endValue||sum==tmp_endValue) {

tmp_endValue = sum; tmpend = tmp_x; }

}

tmp_x.clear();

if((++j)>MAXINITSTEP)//MAXINITSTEP为宏定义,表示振源与端点的计算次数最大值 break; }

x_end = tmpend;//得到端点

x_endValue = tmp_endValue;//得到端点对应的目标函数值 mtmp.clear();

}

此函数随机产生一个初始解,然后从此解出发,在整个解空间均匀随机地产生新解,并在这些

新解中确定目标函数值最大和最小值,即确定端点和振源。端点的值我们会在接受函数中用到,

可用于近似计算势能的最大值f(End)。这一阶段的运行次数由MAXINITSTEP指定,而且当目标

函数值最大和最小值在一定次数内未发生变化时也可停止计算,这个次数由MAXINITPOINT指

定,这两个值均为用户预先设定。

(3)步长大于基态步长时的寻优过程函数。 程序10.3

void HarmonicOscillator::MarchMore(int (*s)[CITY_NUM]) {

vector tmp,tmp1;

vector::iterator pst,ped; int a,b,d,i,j,k;

int m,n;

int sum;

int newmarch;

int countx=0,county=0; double x,y; j = 0; k = 0;

while(j/*用2-opt方法对解进行扰动*/

a = rand()%CITY_NUM;//CITY_NUM为宏定义 d = 0;

b = 0;

while(d<3||a==b) {

b = rand()%CITY_NUM; if(ad = (CITY_NUM - a)+b; }

newmarch = d;//当前步长 for(i = 1;im = (a + i)%CITY_NUM;

n = (b - i+CITY_NUM)%CITY_NUM; tmp1[m] = tmp[n]; }

/*计算上面产生新解的目标函数值*/ sum = 0;

sum = Distance(s,tmp1); /*谐振能级接受准则*/

if(x_optValue>sum || x_optValue==sum)//新解比当前解好的情况下 { j = 0;

x_optValue = sum; x_opt.clear();

x_opt = tmp1; //更新近似最优解 march = newmarch;//记录当前步长 if(sum < mix)//记录最小解 {

mix = sum;

x_mix = tmp1;

} }

else//新解比当前解差的情况 {

y = ((double)(sum-x_optValue)/(x_endValue-x_optValue)); x = 4.0/(CITY_NUM*CITY_NUM);//基态步长取值为2 if(y>0&&x-y>0) {

x_optValue = sum; x_opt.clear(); x_opt = tmp1; march = newmarch; county++; }else j++;

}

tmp1.clear();

if((++k)>MAXMORESTEP)//MAXMORESTEP为宏定义,表示此过程的计算上限 break;

}//ENDWHILE

}

此函数的作用是步长大于基态步长时求解近似最优解,并记录此寻优过程中遇到的最小解。采

用2?opt方法随机产生新解。函数的核心是谐振能级接受准则,新解优于当前解时接受,劣于当

前解时,按大于0的概率接受新解为当前解。由于谐振能级接受准则的运用,算

法能以一定的概率接受差解,而且此差解又被约束在局部最优解中,所以既能跳出局部陷阱, 又能保持解的质量。这一过程的计算次数由MAXMORESTEP 来指定, 如果解在 MAXMARCHMORE次内都没有变化也退出这一阶段的寻解过程。 (4)步长为2时寻优过程函数。 程序10.4

void HarmonicOscillator::MarchTwo(int (*s)[CITY_NUM]) {

vector tmp;

vector::iterator pa,pb; int a,b; int all;

int i=0,j=0; a = 0; b = 0;

x_optValue = mix;

x_opt = x_mix;//将最小解替代近似最优解

while(itmp = x_mix;//替换当前解为最小值 /*两两随机交换法*/ a = rand()%CITY_NUM; b = rand()%CITY_NUM; while(a==b)

b = rand()%CITY_NUM;

swap(tmp[a],tmp[b]);//产生新解 all = 0;

all = Distance(s,tmp);

if(x_optValue>all || x_optValue==all)//新解优于当前解时 { i=0;

x_optValue = all; x_opt.clear();

x_opt = tmp;//更新当前解 }

else i++;

if((++j)>MAXTWOSTEP)//MAXTWOSTEP为宏定义,表示此过程最大计算次数 break; }//while_end tmp.clear();

}

此函数为步长为2时的寻优函数。步长为2时采用的是两两随机交换的方法产生新解。此时假定

当前的局部山峰为全局最优的局部山峰,且对此局部山峰进行垂直搜索。 (5)基态寻优过程函数。 程序10.5

void HarmonicOscillator::MarchOne(int (*s)[CITY_NUM]) {

vector tmp,tmp1,tmp2; vector::iterator pa,pst,ped; int i=0; int j=1;

int k=0,m = 0;

int change;//从数组中提出的插入元素 int sum; int mix;

while(ktmp = x_opt; /*随机插入法*/ i = rand()%CITY_NUM; pa = tmp.begin(); change = *(pa+i);

tmp.erase(pa+i);

pa = tmp.begin();//此时的tmp只有(CITY_NUM-1)个元素,pa指向要插入的位置 j = rand()%CITY_NUM;

tmp1 = tmp;//tmp1只有(CITY_NUM-1)个元素的数组 pa = tmp1.begin();

tmp1.insert(pa+j,change);//产生新解 sum = 0;

sum = Distance(s,tmp1);

if(x_optValue>sum || x_optValue==sum) { k=0;

x_optValue = sum;

x_opt.clear();

x_opt = tmp1; //更新当前解 }else k++; tmp1.clear();

if((++m)>MAXONESTEP) //MAXONESTEP为宏定义,表示此过程最大计算次数 break; }

tmp.clear(); }

此函数是进一步在局部山峰内垂直搜索当前最优解,采用的随机插入法产生新解。经此函数处

理后即得到最后的当前解,即全局的近似最优解。 4

.实验结果分析

(1)模拟谐振子算法的终止条件。

在此试验中模拟谐振子算法的终止条件采用的是分阶段终止条件。在确定振源和端点、步长 以及近似基态能级中都有各自的算法终止条件,终止条件由用户指定。 模拟谐振子算法中需要设置的参数有以下几个:振幅A、初始步长L0 、基态步长Ls 以及终止条件。

在试验中,振幅A和初始步长L0 均取为城市的规模N,基态步长Ls 取值为2。终止条件取值如表10.3

所示,这些参数是我们优选后的参数。 表10.3 模拟谐振子算法参数列表

其中MAXINITPOINT、MAXINITSTEP用于确定振源和端点的时终止条件,MAXINITPOINT为 控制解无变化次数的上限,MAXINITSTEP为确定振源和端点阶段最大计算次数的阈值。 MAXMARCHMORE 、MAXMORESTEP 是步长时的终止条件, 同样

MAXMARCHMORE为此阶段中解无变化次数的上限,MAXMORESTEP为此阶段最大计算次数 的阈值。MAXMARCHTWO、MAXTWOSTEP分别为步长L=2时的解无变化次数上限和最大计 算次数阈值。MAXMARCHONE、MAXONESTEP分别为步长L=1时的解无变化次数上限和最大 计算次数阈值。

(2)模拟谐振子算法的性能评估。

为方便后面算法的分析我们对以下的几个值进行定义。 ① 最优解的平均百分比。

② 标准差S:标准差是方差的算术平方根,用于不确定性的一种测量。表示一组数值与平均值

的分散程度。一个较大的标准差,代表大部分的数值和其平均值之间差异较大;一个较小的标

参数城市规模N=21 城市规模N=48 城市规模N=120 振幅A 21 48 120 初始步长L0 21 48 120 基态步长Ls 2 2 2

初始化终止条件MAXINITPOINT 1000 5000 50000 MAXINITSTEP 10000 10000 100000 [Ls

,L0]终止条件MAXMARCHM ORE

10000 100000 1000000 MAXMORESTE P

50000 200000 1000000 步长为2终止条 件

MAXMARCHT WO

1000 5000 100000

MAXTWOSTEP 10000 20000 500000 步长为1终止条 件

MAXMARCHO NE

500 1000 100000

MAXONESTEP 5000 5000 100000

准差,代表这些数值较接*均值。标准差的计算公式为: ③ 变异系数又称“标准差率”,是衡量资料中各观测值变异程度的另一个统计量。当进行两个或

多个资料变异程度的比较时,如果度量单位与平均数相同,可以直接利用标准差来比较。如果

单位和(或)平均数不同时,比较其变异程度就不能采用标准差,而需采用标准差与平均数的

比值(相对值)来比较。

标准差与平均数的比值称为变异系数,记为C.V。变异系数可以消除单位和(或)平均数不同对

两个或多个资料变异程度比较的影响。 变异系数的计算公式

④ CPU计算时间的平均百分比。

这里的标称值= 同规模n次试验结果所需时间的平均值,本节中标称值为80次计算所需CPU计

算时间的平均值。

我们采用表10.3中的参数对城市规模数为21、48、120的不同情况分别做了20次实验,得到的值 如下。

表10.4中的数据充分体现了模拟谐振子算法有很高的解质量,在规模不大的情况下模拟谐振子

算法都寻找到过真实的最优解。 表10.4 模拟谐振子算法解的质量 规模路径长度(km) 解(%) 平 均 最 好

最差最优平均 (%) S CV 21 2 7 0 7 2 7 0 7

2707 2707 0 0 0 48 5 1 1 0 5 0 4 9

5194 5046 1.2683 35.83120 36.90 120 7 2 4 9 7 0 7

8

7367 6942 4.4223 6

80.314382 3

18.16

表10.5记录了模拟谐振子算法在各个规模下的时间代价,在不大规模的情况下,时间代价皆保

持在秒级。对解NP问题来说,这么小的时间花费是非常令人鼓舞的。 表10.5 模拟谐振子算法的CPU时间

(3)模拟谐振子算法寻优过程的图形化分析。

本试验选用的是表10.3中城市规模为48的一个实例的结果图形。TSP寻优的整个过程如图10.8所

示。从图形可以看出寻优过程分为3个阶段。 图10.8 TSP寻优过程(N=48)图 (1)确定振源和端点。

(2)经典振动阶段,全局寻优。 (3)基态时的局部寻优。

图10.8描述了整个以上3个阶段。这3阶段的寻优过程分别对应图10.9~图10.10,这3幅图对3个

阶段进行了分别的描述,也可认为是对图10.8的分阶段放大图。 规模CPU时间(ms) CPU时间(%) 平 均 最

最长标称平均 (%) S CV 21 1 2 0 3 1 1 7 7

1239 1225 ?1.796 18.055 ?10.05 48 2 7 1 9 2 6

7

9

2760 2791 ?2.578 28.1585 ?10.92 120 9 2 3 7 5 9 2 0 0

1

95126 92784 ?0.441 38.7298 ?87.82

图10.9 振源和端点搜寻阶段

首先随机产生一个初始解(城市路径)为:{0 40 9 45 43 12 44 35 1 19 38 5 15 14 21 22 23 28 27 11

17 7 34 26 10 42 18 3 36 8 39 25 41 47 33 6 46 31 4 32 20 30 16 2 24 37 13 29 },目标函数值即距离

总和为21050。

由初始解在整个解空间搜索出振源和端点,如图10.9所示。其中端点为:{1 46 42 0 22 38 31 39 26

23 7 40 45 32 34 10 21 12 29 3 30 15 36 24 35 19 14 5 37 8 17 41 13 44 27 33 4 28 6 11 2 47 25 16

43 9 18 20 },目标函数值为25102。振源为:{14 37 25 2 33 6 43 12 23 11 0 4 21 10 28 1 41 44 22 47

35 24 19 34 29 42 46 20 15 39 3 17 30 36 16 26 7 8 13 32 31 27 40 18 45 38 9 5 },目标函数值为

16118。此过程中振源的取值过程对应着当前近似最优解的变化。

步长在时,遍历邻域内的近似最优解。所得的目标函数值为5127,搜索了936个局部 山峰,即垂直搜索了936个局域最优解。如图10.10所示。 图10.10 能级大于基态能级时的搜索阶段

图10.11是基态能级寻优过程,对应的步长L取值为1和2时。在步长为2时,近似基态搜索得到最

后的近似最优解为{44 29 3 18 2 42 24 22 33 40 43 0 12 15 10 47 28 6 27 45 17 46 25 5 35 13 8 20

16 26 31 21 7 32 4 30 11 9 14 23 36 39 38 41 34 19 37 1 },目标函数值为5102。在步长为1时,近

似基态搜索得到最后的近似最优解为{42 29 3 18 2 24 22 33 40 43 0 12 15 10 47 28 6 27 45 17 46

25 5 35 13 8 20 16 26 31 21 7 32 4 30 4 30 11 9 14 23 36 39 38 41 34 1 19 37 44 },目标函数值为 5085。

图10.11 基态能级搜寻图

图10.12展示了在求解TSP问题时,在整个寻优过程中,产生新解的目标函数值。从此图可以清

楚看到新解的取值过程也是分为3个阶段。首先在整个解空间内等概率地搜寻振源和端点,粗略

锁定振源,即粗略确定全局范围内的近似最优解。然后由此振源作为局域寻优的初始解,在步

长决定的邻域解空间内搜寻近似最优解。当步长到达Ls 时,以局部寻优中最小解作为基态能级 邻域内的起始解,以下山法进行寻优。 图10.12 邻域解取值过程图 10.4.6

模拟谐振子算法在连续和非线性优化问题中的应用

模拟谐振子算法的应用并不局限于离散的和线性的优化问题,而且可以应用于连续的和非线性

优化问题。下面举两个例子:例1是多个变量是相关联的,例2中多个变量相互独立。 例1.求满足约束

的函数的最大值。

这是一个非线性量的非线性目标函数且带有非线性约束的优化问题,用理论方法求解有一定的

困难,可以用模拟谐振子算法求解。 由约束知y的取值范围为如下:

根据约束中的等式求得x、z的等式如下:

因此,可在内随机产生y的值,然后根据上式求得、的一组值,当满足约束时再求 目标函数的值。

随机产生一组变量值为初始解,然后分为3个阶段求解:首先确定振源和端点,然后遍历局部近

似最优解,最后在基态能级内寻优。设置初始步长为10,基态步长为1。 求出近似最优解为: 当 则。

而实际的最优解为 则。

可以看出模拟谐振子算法与实际的最优解两者几乎没有偏差。 文献[12]中使用模拟退火算法求得近似最优解为: 当 则。

可以看出模拟谐振子比模拟退火算法求解的效果更好。

例2.求函数的最小值,其中。

这是一个多极值函数,最小值。注意到两个变量x和y只有范围约束,而无关系约束, 即两个变量相互独立。

设置初始步长为1000,基态步长为1。对函数模拟10次平均最小值为0.626453,而根据文献[12]

使用模拟退火算法求得平均最小值为1.45276。很明显,模拟谐振子算法求解的质量优于模拟退

火算法。

10.4.7

模拟谐振子算法的隐含并行性

隐含并行性(Implicit Parallelism)的概念来源于遗传算法。遗传算法的基本思想是模拟自然界

遗传机制和生物进化论而形成的一种过程搜索最优解的算法。其特点是几乎不需要所求问题的

任何信息而仅需要目标函数的信息,不受搜索空间是否连续或可微的限制就可以找到最优解。 1975年,John Holland 出版了《自然与人工系统中的适应性行为》。首次系统阐述了遗传算法的

基本理论和方法,提出了遗传算法的基本定理—模式理论,从而奠定了遗传算法的理论基础。 Holland模式定理为:低阶,短长度的模式在群体遗传过程中将会按指数规律增加。当群体的大

小为n时,每代处理的模式数目为。Holland称遗传算法这种处理能力称为内在并行性 (intrinsic parallelism)。说明了遗传算法其内在具有并行处理的特质。 1989年,David Goldberg出版了《搜索、优化和机器学习中的遗传算法》。全面系统地总结了当

时关于遗传算法的研究成果,结合大量的实例,完整地论述了遗传算法的基本原理及应用,奠

定了现代遗传算法的基础。Goldberg将内在并行性定义为隐含并行性,用数学的方法系统地证

明了遗传算法的隐含并行性。并指出遗传算法之所以能以较少的计算获得较大的收益,究其原

因是因为遗传算法具有隐含并行性,也是遗传算法优于其他求解过程的关键所在。

和遗传算法一样,许多智能算法如模拟退火算法和模拟谐振子算法都能在多项式时间内近似不

精确地解决NP问题,有效地搜索出全局最优解。采用概率化的寻优方法,自适应地优化调整搜

索方向,不需要确定的规则。也具有用较少的计算获得较大收益的特性,我们有理由猜测在模

拟退火算法和模拟谐振子算法中也同样存在着隐含并行性,借此寻求一种能解释智能算法的通

用模式,也许有一天我们会有一个通用的智能算法构造体系,统一所有的智能算法模型。 10.5

云计算中的人工智能

我们在研究云计算时一直将注意力全部放在的云计算的架构上,希望能找到一个较为有效的分

布式计算模型,像Map/Reduce这样的框架的提出就是为了这个目的。但大家往往忽略了研究算

法本身是否适合在云计算的分布式环境下运行的问题。这是一个问题研究的两个思路,是框架

适应算法还是算法适合框架。

我们前面讲过采用随机数的Monte-Carlo方法是一种可以有效实现并行计算的一种算法结构,而

且符合自然界不确定性的本质,大量的人工智能算法都或多或少的采用了随机方法,这说明云

计算技术在实现智能上是具有优势的,许多的智能算法可以很顺利地在云计算系统实现分布式

的计算,从而充分利用云计算系统的强大计算能力。

我们所提出的模拟谐振子算法同样可以以一种很简单的方式实现在机群上的分布式计算,比如

我们在求TSP问题时可以在各个云计算节点上启动相同的谐振子计算方法,因为TSP问题和其他

的优化问题都是典型的计算密集型问题,问题本身的数据量几乎可以忽略,所以在计算过程中

几乎可以不用在各节点间进行任何的数据通信,在计算完成后将所有节点计算出的最短距离作

为问题的近似解即可。我们之所以能采用这么简单的方式实现问题的并行化就是因为谐振子算

法是一种采用了随机技术的智能算法,虽然在各个节点启动了相同的计算方法,但整个计算的

历程是完全不同的,各个节点会根据不同的随机序列进行完全不同的解空间搜索,从而获得不

同的结果,取各节点的最优解作为结果就充分地利用了各节点的计算能力。其他的人工智能算

法如遗传算法、模拟退火算法等均可采用这种简单的方法实现计算的并行化。我们几可以猜想

人工智能算法除了隐含并行性之外,真实的并行能力也是其重要的特征之一,随机技术的采用

不但实现了人工智能算法的隐含并行性也为其提供了真实的可并行能力。

云计算技术为人工智能技术的发展提供帮助,人工智能计算也可能会成为云计算一个重要支撑

技术,推动云计算的发展。

随着互联网信息技术的飞速发展,云计算再度升温,逐渐成为了各企业和公司之间竞争的热点,

纵观世界,各个大厂商,Google、微软、IBM、Amazon等,甚至一些不知名的小公司也杀入到

云计算领域,这是未来一个很有前途的领域,他们之间存在着怎样的区别和联系,同时又赋予

了云计算怎样的新含义?谁又将在这一场不流血的战争中稳固自己的地位?在本章中我们一起

来看看天空中飘着的朵朵不同的云。 11.1

云计算技术流派分析

现有的各个云计算平台技术流派主要可以划分为3个:以数据存储为主的存储型云平台,以数据

处理为主的计算型云平台以及计算和数据存储处理兼顾的综合云计算平台。这3个流派各自代表

了不同云计算厂商云业务的侧重点,同时也已成为各大云计算厂商争夺市场份额的3个主战场。 11.1.1

存储型——

数据密集云计算平台

存储型——数据密集云计算平台就是主要以提供数据存储、搜索服务为主的云计算平台,通过

为客户提供安全便利的云存储服务来赢取客户。云存储是利用云计算中服务器集群强大的存储

能力为客户保存数据,用户不需要知道自己的文件存储是存储在一个服务器节点还是多个节点

之中,也不需要知道节点是否可信,这些都将由云服务器来处理解决。

云存储的实现并不存在技术上的障碍,它需要云设备、云软件、云服务等有机地集合在一起, 为用户提供无障碍的云服务。同时云存储需要真正适合云环境的文件系统架构来支撑文件存储

的合理性与有效性。然而现有的如GFS、HDFS、FastDFS等分布式文件系统并不能完全满足云 计算环境下的存储需求。

现有的云计算提供商基本都提供基本的云存储服务,这些存储服务都是基于各自提出的分布式

文件存储系统。Google拥有如今最大的信息库和知识库,因此对海量数据的存储有自己的独特

之处,它所提出的GFS文件存储系统能够实现对文件实时监控、容错检测、自动恢复等功能, 是建立在不可信节点的存储条件下的一个相对很优良的文件系统。它对于大型文件的管理是很

高效的,优化的程度也很高,其对与小文件的存储并没有提供有效的优化方案。这点使得它并

不能完全适应云计算环境下用户海量的小文件存储。FastDFS是一个开源的文件系统,它在大容

量存储和负载均衡上做的很优秀,但是在小文件存储上仍然没有合理地优化。 11.1.2

计算型——

计算密集云计算平台

计算型——计算密集云计算平台就是主要以数据计算、处理服务为主的云计算平台,为用户提

供相应级别的高性能计算环境。用户可以根据自己的需求选择相应的计算能力,并支付相应的 费用。

通过云平台的高性能计算能力,用户与企业均能够获得与可以与现有大型机相媲美的计算能力,

进行大规模的数据处理计算,为企业和个人减少成本开支。 现有的云平台厂商也都在自己的云计算平台中提到这个方案,但是没有提出具体的实现策略。 云计算平台可以通过并行计算、网格计算等策略实现云集群的高性能计算,为用户提供灵活、 便捷的高性能计算服务。 11.1.3

综合云计算平台

综合云计算平台指的是将云计算的存储与计算进行有效的整合,在合理利用云集群存储节点的

存储空间的同时,并不浪费各个节点的计算能力,通过相应的策略实现集群存储和运算能力的

整合,对数据进行处理计算。

现有云计算平台基本没有提出这种存储与计算完美相结合的策略,这也是在未来云计算大战中

取得胜利的重要武器,有待各家继续研究开发。 11.2

国际云计算公司分析

国际云计算领域现在几乎所有的一线IT企业都参与进去了,各公司依据自己传统的技术领域和

市场策略都提出了自己的云计算架构,从各个方向进军云计算。但我们认为还没有一款真正可

以实用化的系统推出。云计算是一个综合性的技术,Google现在的云计算系统还是在测试和改

进阶段,依托搜索引擎所提出的云计算架构肯定无法满足所有应用的需要。

现在的国际企业由于都有很好的技术背景,他们通过深挖技术基础把大量以前的产品和技术的

云计算特征挖掘出来,如软件的虚拟化、分布式存储系统,提出自己的云计算产品线,但目前

还没有一个真正系统的云计算产品线出来,预计会在未来两年左右会出现。 11.2.1

云计算技术的提出者Google

Google是云计算的提出者和先行者,虽然Google获得这一先机并不是一开始就想到的本意,而

是在发展过程中获得的意外成功。搜索引擎技术本身就是一种典型的云计算应用,多年的搜索

引擎技术的积累,使Google在云计算技术上处于领先的地位:Map/Reduce的采用、GFS文件系

统的提出、Google廉价服务器的使用都使Google在云计算中占有了先机,从而迫使其他企业慌

忙应战,毕竟Google在云计算的理念是与主流公司的战略是相反的,Google是一个典型的没有

“端”的系统,用户通过一个简单的搜索框就能完成对海量信息的检索,享受成千台器的同时服

务,这迫使微软发起了保卫“端”的战役;Google的服务器战略是够用就行,这与IBM等服务器

提供商倡导的高性能和不断升级的思想完全背道,再加上Google庞大的服务器数量,对主流服

务器提供商构成了巨大的威胁。

Google推出了Google应用软件引擎(Google App Engine),这种服务让开发人员可以基于云计算

环境编写应用程序,并可免费使用Google的基础设施来进行存储。Google云计算的优势在于,

所有的应用程序都可以存在于云计算中,用户永远都不需要安装任何东西,不需要管理软件升

级和安全补丁。Google App Engine(简称GAE)是一个由Python应用服务器群、BigTable数据库

及GFS (Google File System)数据存储服务组成的平台,它能为开发者提供一体化的、提供主机

服务器及可自动升级的在线应用服务。开发者只需要编写应用程序,而不用担心应用运行的平

台资源,因为Google会提供应用运行及维护所需要的一切平台资源。Google不仅仅要为用户提

供现成的在线应用套件,它还希望利用自身的数据库系统优势,使自己成为在线应用的真正统

一平台。只不过平台还受到很多因素的限制,如编程语言,暂时只支持Java与Python。 GAE利用沙盒将不同的应用程序隔离在一个与网络、服务器硬件、操作系统和物理位置无关的

安全、可靠、稳定的环境中。应用程序只能通过提供的网址抓取和电子邮件服务访问互联网中

的计算机。 11.2.2

“ 端”

的霸主微软

多年来微软几乎统治了用户的桌面系统、成为“端”的霸主,建立起了微软的软件帝国,云计算

的出现使软件帝国感到了前所未为的危机,云计算在基本理念上是可以完全抛弃“端”的,虽然

这只是理论上的可以完全抛弃,为了不逆潮流否定云计算,微软提出了“云+端”的云计算构想,

强调“端”在云计算中的重要性,试图在进军云计算的途中自己的传统地盘也不丢失。微软云计

算平台称为Azure Service Platform

微软的Azure服务平台是一个应用在云计算云端的技术,通过它向应用开发者提供一系列特定的

服务来时实现云计算。如图11.1所示,Azure服务平台既可以在云端下被调用,也可以在本地系

统被调用。

图11.1 Azure服务平台架构图

Azure服务平台的组件能被在本地运行的各种系统中的软件调用,其中包括Windows、移动设备

和其他平台。我们可以在VS.MET 2008 以上的版本+Cloudservice+AzureSdk 下实现云计算开 发。

由于在软件领域的技术和市场积累,以及用户的认可,微软会成为云计算技术的一个有力竞争 者。 11.2.3

蓝色巨人IBM

的蓝云

2007 年IBM公司发布了蓝云(Blue Cloud)计划。用IBM自己的话说,这套产品将“通过分布式

的全球化资源让企业的数据中心能像互联网一样运行”。蓝云包括虚拟化Linux服务器、并行工

作负载日程安排和IBM的Tivoli管理软件。IBM的云计算几乎包括了它所有的业务和产品线。 与前面的各家公司比较起来,IBM的起点又有不同,蓝云计划建立于以往对于大规模计算应用、

部署的经验之上,基于自身在网格、分布式存储、动态负载上领先的技术。这一切先期的准备

使得IBM的云更能得到客户的信赖。IBM的云不是SaaS的演化产品,而是从企业内部的需求逐

渐上升为企业对于未来互联网及公众需求的一种智慧领悟。

IBM在高性能并行机集群技术上有着领导性的优势,世界上最快的高性能计算机大多出自IBM,

拥有从“深蓝”集群、“蓝色基因”到网格计算的数十年大规模计算方面的丰富经验。这使得蓝云

的提出理所当然。IBM的每一步都是在迈向云计算,只不过从高端走到了通用,从云端走向云

中将更能赢得云中客户的信赖。不过IBM需要面对的是其高端服务器战略与Google采用低端服

务器战略的冲击。

IBM有自己的特色,它为企业和用户在自己已有的IT环境中建立自己的私有云,并提供与公有

云之间的无缝连接及测试环境的部署。

它为企业提供开发并测试一体化的云计算解决方案,在保证业务的安全性与弹性的同时,保持

了企业最佳的业务运营水平。与此同时,IBM也提供可供客户及合作伙伴直接使用的云服务和

软件。

总的来说,IBM是从理论到实践扎实发展过来的蓝云,带给客户的更多的是一种能够摆脱现状

的解决方案,不管是构建自己的云还是使用IBM的云,他都能给你带来一种从硬件到软件,到

测试,到维护最后到管理的方案。而且IBM是目前唯一一个可以提供从硬件、软件到服务的全

部自主生产产品的厂商,这更加巩固了搭建的云平台的稳定。 IBM发布了蓝云计划(Blue Cloud),并推出一系列产品,可以让企业用户的数据中心通过一种

分布式、全局可访问的资源组织方式,像互联网一样进行运作,提供计算服务。在第一阶段, IBM主要针对X86服务器和基于IBM POWER处理器的系统;第二阶段,则会针对System z大型

主机上的虚拟机。蓝云计划不只是为了运行并行工作负载,也是为了让数据中心的使用更高效。

IBM蓝云的体系可以说是整合了IBM的技术资源而推出的,是一项较为务实的计划,依托IBM 在服务器领域的传统优势,有望在未来云计算市场成为一支重要力量。 11.2.4

云计算的市场先行者Amazon 公司

从市场的角度来看Amazon无疑是一个先行者,也是一个成功的尝试者,Amazon公司云服务的

提出,是建立在其跨越全球的硬件和软件基础设施上的,其初衷是为了利用剩余的计算和存储

资源。亚马逊的“云”名为亚马逊网络服务(Amazon Web Services),目前主要由4块核心服务组

成:简单存储服务、弹性计算云、简单排列服务以及尚处于测试阶段的数据库服务。换句话说,

Amazon现在提供的是可以通过网络访问的存储、计算机处理、信息排队和数据库管理系统接入

式服务。要提供这些服务,需要建造庞大的IT基础设施,而这些都需要亚马逊强大的数据中心

做支持,用户只需按照他们所消费的服务付费。

在基础设施服务上Amazon主要在弹性计算云(EC2)、简单储存服务( S3)、简单数据( SimpleDB)

组成,他实现了一个远端存取数据库、亚马逊的简单排队服务(SQS)。

Amazon是一家电子商务企业,它一进入云计算就力图使其产生商业价值,并取得了效果,这一

点对推动云计算的进步是功不可末的,从市场角度上也给了许多企业信心。 11.2.5 Salesforce 从SaaS

走入云中

Salesforce.com 作为SaaS的代表,是一家以其客户关系管理(CRM)软件和云计算平台著称的 企业。在SaaS技术呈现出走向衰落的时候云计算成为了它下一步的重要战略选择,由于SaaS技

术和应用理念与云计算有很多的共通点,所以Salesforce走近云计算的速度是相当快的,它很快

地推出了Sales Cloud、Service Cloud、Custom Cloud、Cloud Platform for CRM、Cloud Infrastructure

for CRM,这些产品基本就是其原来SaaS产品的云计算翻版,可以说是从概念上首先进军了云计

算,争夺云计算的大旗。

他们提出了对“云计算”最简洁、最易理解的定义。构成“云计算”定义的是3个关键词,分别是“0”、 “1”、“无限”。“0”意味着什么都不想投入;“1”意味着只想要一个,就是说不想要非常混乱、零

散、非常多的系统,只要一个管用的系统;“无限”意味着当需要的时候总能拥有它,不希望自

己的应用受到任何的限制。

Salesforce.com拥有大量传统SaaS应用的客户,从SaaS向云平台的升级具备一定的客户基础。从

总体战略上看Salesforce已基本全力进入云计算领域,但从目前其技术体系看应该还是非常典型

的SaaS体系,Salesforce这种做法应该是典型的高调入云战略。 11.2.6

热爱白皮书的Sun

如果要说远见,Sun应该是当之无愧的,Sun创立之初的理念和口号是:“网络就是计算机”。这

一点和云计算的理念是基本一致的。2005年,Sun就推出了效用计算的服务,utility computing,

CPU是每小时1美元,存储是1GB使用1个月1美元。这其实就是今天大家所说的云计算服务,只

不过名字不同而已。2009年初,Sun收购Q-layer,从而获得了虚拟数据中心(Virtual Data Center)

能力,它提供了开发个人或者团体构建和运行云计算数据中心所需的一切。虚拟数据中心提供

了一个统一整合的界面来部署在云中任何操作系统上运行的应用软件,这些操作系统包括 OpenSolaris、Linux 和Windows。除了以API和命令行界面通过网络浏览器来分配计算、存储和

联网资源外,它还具备拖放功能。Sun的云存储服务支持WebDAV协议,可非常容易地实现对兼

容于Amazon S3 API的文件访问及对象存储。2009年3月Sun公司宣布推出其开放式云计算平台,

即开放式云计算基础架构,该平台融入了Sun公司的行业领先软件技术,包括Java、MySQL、 OpenSolaris和开放式存储等。作为公司建立开源社区的努力和承诺的一部分,Sun还宣布推出系

列核心Open API(开放的应用编程接口),公布了对云计算平台广泛的合作伙伴支持,并展示了

Sun Cloud的创新功能。Sun正在开放其云API供公众评测和评论,这样其他人在建设公共云和私

有云时可以在设计上很容易保证与Sun Cloud的兼容性。

从提出“网络就是计算机”开始,Sun就是思想上的先行者,这一口号也是Sun引以为自豪的思想,

凭借这一口号Sun认为自己是云计算思想的真正最早提出者,为了巩固自己在思想上的领先性

Sun公开发布了一批云计算技术白皮书,如《云计算基础设施和体系架构指南》等。Sun深知

城需先攻心的道理,通过白皮书来奠定自己在云计算中的地位不失为一种好的战略方法。 11.2.7 EMC

云计算的核心是虚拟化

美国EMC 公司是全球信息存储系统、软件、网络和服务等领域的领导者,向全球各种规模的 企业和机构提供自动化网络存储解决方案。2003年12月,EMC公司宣布以6.35亿美元收购 VMware公司。VMware于1998年成立于美国加州的PaloAlto,主要研究虚拟化技术。不久前又

公布了和思科的合作。至此EMC将云计算最为关键的两个技术依托(网络性能、虚拟化技术) 全盘整合到自己的云计划中。从而提供了一套完整的产品、服务和解决方案。

EMC有两方面技术,一方面是信息基础架构,包括信息管理技术、内容管理技术、安全技术等,

另外一方面是虚拟架构技术,包括VMware(EMC推出的任何存储平台产品,都必须是“Virtual Awareness”,就是说,是具备虚拟化意识,适用于虚拟化环境的存储系统)。

虚拟化是云计算技术的一项核心技术,EMC凭借在虚拟化技术中的领先优势,在云计算系统架

构中获得先机,云计算的出现为EMC的虚拟化技术找到了一个更为广阔的应用领域,对于EMC 来说是一个千载难逢的重要机会。如果EMC能保持其在虚拟化技术中的领导地位,肯定能在云

计算时代有所建树。

11.2.8

渔翁得利的思科

我们知道思科公司是世界级的网络设备提供商,现行网络中的大量设备都是由其提供,未来云

计算时代用户和企业对网络的依赖更为严重,同时思科一直以来就想直接进军云计算。 思科将云计算定义为,云计算是基于整合的架构下、利用虚拟化的资源、通过IP网络提供规模

化业务的实现方式。

思科的云计算平台被命名为思科统一服务,其系统结合了思科CRS-1核心网络路由器、Nexus 7000数据交换机以及其名为统一计算的系统(UCS),其中UCS是集成了刀片服务器、交换机存

储、虚拟化管理等多方面技术及产品的整体解决方案。作为即将推出的统一交付服务的一部分,

思科将推出新的更高速模式的CRS-1的数据中心计算技术,这其中还包含虚拟化、通过WAN网

络与服务供应商对等以及网络互联应用等。这款平台将大大优化其所提供的服务及IP网络资源

等,为客户带来具有更佳客户体验的语音、数据以及视频,并为其降低运营成本。 不管思科在云技术本身上是否取得成功,思科的网络设备提供商的身份都将使其成为渔翁得利

者。Sun公司的“网络就是计算机”的说法就说明了在云计算时代网络的重要性。云计算时代大量

的应用严重依赖网络,用户的软件、数据都存在于服务器端,云计算中的大量应用也对网络

带宽和可靠性提出了相当高的要求,这一切都是思科在云计算时代的机会,不管是哪一家云计

算服务提供商获得了胜利,对网络的需求都是不变的,因此思科肯定也会积极地推动云计算的

发展,这一技术趋势是对思科有利的趋势。 11.3

国内云计算公司分析

云计算能够极大地促进社会、经济、科技的发展,在国际各大公司对云计算的热烈追捧下,国

内的一些公司对建立云中心很感兴趣,也都开始关注云计算市场,同时也逐渐形成了自己的云

计算架构。

国内云计算企业普遍实力不足,有热情的企业规模不够,有规模的企业热情不够,整个国内环

境观望气氛浓厚。有部分企业虽然已开始进军云计算但并未全面进行推广,如盛大网络、东莞

的广东电子工业研究院,可以说大家都意识到了云计算未来的发展前景,但又不敢贸然进入, 希望等形势进一步明朗化后才重兵进入。大量企业将主机租用、SaaS应用等业务先称为云计算,

抢占市场,实质性、基础性的工作还做比较少,很难和国际主流公司抗衡,这种情况有可能会

让我们丧失一次在IT领域重振雄风的机会。面对这难得的技术变革,我国的IT企业一定要抓住 战机。

我们认为国内其实有几类企业有望真正进军云计算市场。

第一类是移动、电信运营商,他们拥有强大的网络优势、服务器规模庞大、资金实现雄厚,有

从事大规模数据中心建设和运营的经验,且在我国具有网络垄断地位,这为其云服务的前期推

广提供了方便,中国移动推出大云应该是其试水之作。但谨慎的心态还是很明显,只是在对自

己内部数据的挖掘在做一些测试工作,也许也是在等待机会。

第二类是现有的大型电子商务企业,他们同样拥有强大服务器资源,如阿里巴巴,重要的是他

们拥有很好的用户基础,用户访问量相当巨大,这类企业往往从SaaS入手,逐步进军云计算。 第三类是大型的主机租用服务商,他们拥有大量的服务器资源,又有软硬件租用的市场经验, 但弱点是软件的研发能力不足,可采用成熟的云计算平台和进行资源整合。

第四类是计算机制造企业,这类企业均愿意进军云计算市场,但大多雷声大雨点小,如神舟数

据、清华同方。

11.3.1

拥有基础设施的世纪互联

基础设施是云计算的一个重要方面,也是投入最大的地方,具备服务器的资源肯定会在云计

市场中有一定的优势。世纪互联就是这样的一种情况。世纪互联创立于1996年,是中国最早的

ISP/IDC服务商之一,是目前中国规模最大的电信中立互联网基础设施服务提供商。世纪互联总

部设在北京,主营业务包括互联网数据中心服务(IDC)、互联网内容分发/加速服务(CDN)、 方位的增值服务和完整的行业解决方案。其云计算服务平台CloudEx与Amazon类似,锁定在基

础设施层的IaaS服务,提供弹性计算、云存储和云备份等服务。

CloudEx的开放策略主要体现在业务和技术两大层面。在技术层面,作为云计算基础设施服务提

供商,为广大的应用开发商提供开放的API;在业务层面,作为云计算服务提供商,为客户提供

品质高价格优的互联网基础设施服务。主营云产品:云主机,云备份,云存储。

世纪互联的云计算还带有强烈的主机租用的特点,要想完全进行云计算还需要在技术上进行很

大的改进,或者与相关企业进行技术资源的整合。不过世纪互联的案例代表了一批此类企业进

军云计算的模式。 11.3.2

阿里巴巴下决心入云

阿里提出的商业云,超出于亚马逊的资源服务和谷歌的统一服务平台之处就在于,他将自己所

占领的庞大的商务资源也融合进了云中。第一次将用户、市场、运营、业务接口、数据托管能

力融合到一个生态框架中,让ISV(独立软件开发商和服务商)更加专注和轻松,也让数千万电

子商务用户享有一个应用丰富并安全可靠的在线化工作和生活平台。

阿里的电子商务云计算中心与其他云计算中心的最大区别,就是它不仅为用户提供存储、网络

服务,以及租用云的计算,还提供适合国内用户的各种电子商务服务。

阿里下一步的计划是继续开放更多的核心数据和业务接口给第三方调用,同时将国内一些优秀

提供商的服务能力整合到平台,以接口和资源的方式供其他厂商调用,快速构建起庞大、共赢

的在线软件生态链即软件互联平台。

阿里旗下的阿里软件一直是执行阿里集团云计算业务的部门,在国内SaaS市场具备一定的领导

能力,前期由于战略的不确定,对是否放弃SaaS概念一直踌躇不定,最后终被下猛药撤掉阿里

软件成立阿里云,专注于云计算技术和业务,这表明阿里集团高层应该是已下定了决心的。阿

里集团用户庞大的服务器资源、庞大的用户群、充裕的资金,这一切为阿里云的发展提供了保

障、也是其相比其他企业的优势所在。阿里云正在大量招兵买马构建自己的云帝国。 11.3.3

中国移动的BigCloud

在云计算风起云涌的时代,毫无疑问,最受威胁的就是电信运营商的市场。电信运营商应该认

真考虑从传统的IDC服务商向云服务商的快速转型,只有这样才可以保证传统数据中心老大的

位置不会被云服务商抢走。

首先应该是认识的转变,基于互联网的云计算,带宽的充裕和网络的稳定尤为关键。而作为自

己的独特优势,电信运营商拥有别的云计算公司无法比拟的宽带和网络资源,应该充分利用优

势,快速从云服务的使用者充当起云服务提供者的重任。

加之手机网络移动业务的迅猛发展,与人们关系越来越亲密的手机将成为云计算的另一受用者。

基于便携性和体积大小的限制,手机的计算、处理能力都已经处于瓶颈,也只有云才能满足广

大用户对手机性能的要求。

作为中国电信运营商的龙头中国移动已经率先迈出了这一步。推出了名为“BigCloud—大云”平

台,BigCloud是基于开源技术建造的实验性云计算平台,这一平台带有明显的试水作用,未来

中国移动会采用哪种架构还不得而知。

中国移动进行云计算的优势是很明显的:大量的移动终端用户就是云终端的使用者,手机是一

种典型的云终端类型;中国移动作为网络运营商有着带宽优势;资金实力强大、服务器资源丰

富、拥护数量巨大的用户及用户信息。这些优势如能有效利用中国移动在云计算时代的成功应

该是可以看见的。 11.3.4

国产旗帜友友云计算平台

友友云计算系统号称是第一款具有中国自主知识产权的云计算底层平台产品。这对于中国自主

地掌控自己的资源、资金和技术,国计民生的重要行业的发展来说具有重要意义。 友友云的核心产品主要分为:友友数流平台(Bitsflow)、分布式虚拟存储系统(DataCell)、网

格计算平台GAP、网络虚拟机(NetVM)、友友企业地图。

友友的成功面临资金、技术和市场的挑战,我们祝愿中国本土的云计算企业能在挑战中顺利地

生存下来。

11.3.5

曙光高性能与云计算

一直以来,曙光始终专注于服务器领域的研发、生产与应用,依托超级计算机的扎实功底,

足自主研发,通过不断技术创新,构建出拥有完全自主知识产权的全系列精品服务器,能全面

满足用户从超级计算机到普通PC服务器的各项应用需求,在互联网、金融、电信、生物、气象、

石油、科研、电力等多个行业有着大量成功应用。

在当前云计算的大浪潮下,曙光依靠其雄厚的硬件环境和技术实力也致力于云计算平台的研发。

曙光公司为用户提供的天潮5000A高性能计算集群硬件系统包括计算子系统、存储子系统、网

络子系统、管理诊断子系统以及基础架构子系统。

该系统具有优异的计算性能、超大的存储空间、超低功耗、双重保险的水冷散热、杜绝浪费的

资源整合和卓越的管理系统、

曙光依靠自身过硬的技术,凭借自身优秀的产品和科学的解决方案,在中国的云计算平台领域

占据一席之地。当前曙光已帮助广东电子工业研究院部署了一套云计算应用系统,但在云计算

软件系统上曙光还没有太大动作。 11.3.6

展览也要云

随着互联网技术迅速发展正在兴起的云计算概念,使会展行业也不再满足于客户到现场进行参

观的传统模式,大量的展览需要在网络上建立虚拟的会展现场,让更多的观众能参与到展览中

来,从而延伸会展经济的产业链。

中国贸促会在多年主办实体展览经验的基础上,建立了平面动漫、三维立体和流媒体三种虚拟

展览表现形式的演示网站。由于大量的图形、3D画面和流媒体的使用,导致传统的系统架构无

法满足用户访问时的负荷,因此,云计算技术很自然地成为了解决这一问题的钥匙。中国贸促

会基于云计算技术建立了自己的演示网站,成为了先吃螃蟹的机构。他们率先将虚拟化展览通

过云计算技术搬到了网络上,使实体展览的影响力通过互联网得到了无限的延伸。云计算技术

的采用大大加速了用户访问虚拟展览的体验,人们进入网络提供的虚拟环境同样可以实现和参

观实体展览同步的体验。云计算技术从计算力和存储力上保障了这一体验的顺畅实现。 图11.2是中国贸促会的一个测试系统。随着展览的虚拟化,企业和访问者借助云计算技术能够

实现与实景和真人购物逛街和聊天的全新体验,从而使实现电子商务的需求成为自然和乐趣。 通过云计算技术的整合,现在互联网的产业链和赢利模式将会在云计算系统中被一网打尽。 图11.2 中国贸促会览网云虚拟展览测试系统

11.4

开源云计算平台分析 开源总是意味着激情,开源的云计算平台由于发展的时间还不长,总体来看还较弱,如Hadoop 的版本还处在0.20,这表明技术还相当不成熟,不过在各个正规企业观望的时候也许开源技术

就会获得长足的发展,说不定未来统制云计算技术有可能会是开源平台。表11.1对几种开源云

计算技术做了一个简单的描述。 表11.1 开源云计算系统 项目名称责任者描述

AbiCloud Abiquo公司一款用于公司的开源的云计算 平台,使公司能够以快速、简 单和可扩展的方式创建和管理 大型、复杂的IT基础设施(包 括虚拟服务器、网络、应用、 存储设备等)

Hadoop Apache基金会该计划是完全模仿Google体系 架构做的一个开源项目,主要 包括Map/Reduce和HDFS文件

系统

Eucalyptus 项目加利福尼亚大学创建了一个使企业能够使用它 们内部IT资源(包括服务器、 存储系统、网络设备)的开源 界面,来建立能够和Amazon EC2兼容的云。

11.5

国际国内云计算平台提供商对比研究

不同的云计算提供商都以自己不同方式应用、发展着云计算:例如:Amazon的弹性计算云 (ElasticComputeCloud,EC2)是基础设施即服务(IaaS)的应用典范;Rackspace在价格上与

Amazon展开竞争,它的优势是Linux的虚拟服务器价格比Amazon低得多,节约成本;Skytap主

要从事软件测试和开发,而不是vanillaWeb主机;IBM的ComputingonDemand主要针对高性能计

算,诸如汽车和航天工业模拟计算、生命科学领域的染色体组建模等;常规主机提供商Savvis 和Unisys 允许用户将物理服务器和虚拟服务器混合起来匹配使用; PropertyRoom 使用 DedicatedCloudCompute运行它的在线拍卖服务; Savvis提供如弹性计算云那样的多承租 (multitenant)式OpenCloudCompute,使得大量用户使用共享硬件运行虚拟机成为可能,Rackspace

也在尝试同样的方法;Amazon的新VirtualPrivateCloud将模式延伸得更远,新VirtualPrivateCloud

允许用户创建一套隔离的弹性计算云资源,再通过一个VPN连接到他们公司的设备。表11.2~ 11.5从技术和类型对各大厂商进行了划分和类比。 表11.2 云厂商的技术比较

MongoDB 10gen MongoDB是一个高性能、开 源、无模式的文档型数据库, 它在许多场景下可用于替代传 统的关系型数据库或键/值存 储方式

Enomalism弹性计算平台它提供了一个功能类似于 EC2的云计算框架。Enomalism 基于Linux,同时支持Xen 和Kernel Virtual

Machine(KVM)。与其他纯IaaS 解决方案不同的是, Enomalism 提供了一个基于 Turbo Gears Web 应用程序框 架和Python 的软件栈

Nimbus 网格中间件Globus Nimbus面向科学计算需求,通 过一组开源工具来实现基础设 施即服务(IaaS)的云计算解 决方案

各家云技术比较

技术特性核心技术企业服务开发语言开源程度 微软整合其所用软 件及数据服务 大型应用软件 开发技术

Azure平台.NET 不开源 Google 储存及运算水 平扩充能力 平行分散技术 MapReduce , Google

AppEngine,应

Python,Java 不开源

目前的云计算类型可以划分为基础设施提供商、云计算平台提供商和云服务提供商。下面根据

各厂商所主营的云计算业务对一些厂商进行分类划分。 按基础设施提供商划分。

基础设施:提供实现云计算的虚拟化服务器、网络、存储等硬件设备以及系统软件。 表11.3 基础设施提供商的比较 续表

BigTable,GFS 用代管服务 IBM 整合其所有软 件及硬件服务 网格技术,分 布式存储,动

态负载 虚拟资源池提 供,企业云计 算整合方案 不开源

Oracle 软硬件弹性虚 拟平台 Orackle 的数 据存储技术, Sun开源技术 EC2 上的 Oracle 数据 库,

OracleVM , Sun xVM 部分开源

(Sun)

Amazon 弹性虚拟平台虚拟化技术 Xen

EC2 、S3 , SimpleDB 、

SQS, 开源

Saleforce 弹性可定制商 务软件 应用平台整合 技术

Force.com Java, APEX 不开源

EMC 信息存储系统 及虚拟化技术 Vmware 的虚 拟化技术,一 流存储技术 Atoms 云存储 系统,私有云 解决方案 不开源

阿里巴巴弹性可定制商 务软件 应用平台整合 技术

软件互联平

台,云电子商

务平台 不开源

中国移动坚实的网络技 术丰富的带宽 资源

底层集群部署 技术,资源池 虚拟技术,网 络相关技术 BigCloude- 大 云平台

不开源

云计算类型公司名称简介

基础设施提供商Dell 公司收购Message One等多家软件 公司增强软件实力,试图从软 硬件两方面向云计算发展

HP公司据透露,HP公司将全面发布自 己的云计算策略

云计算类型公司名称简介

基础设施提供商IBM公司在2007年发布了“蓝云计划”产

品,已经建立了多个云计算中 心,提供丰富的产品帮助企业 按云服务提供商服务划分。

云服务提供商:公司提供云服务,用户通过Web浏览器获取而不是安装在本地的应用程序来提 供。

表11.4 云服务提供商的比较

按云计算平台划分。coloraterial

云计算平台:公司提供虚拟化服务器,用户可以在上面运行现有的程序或者自己开发新的应用

程序,不必维护操作系统,服务器软硬件或节点失效等而操心。 表11.5 云计算平台提供商的比较 建立自己的私有云

Sun公司从网格计算到云计算,Sun公 司号称只有自己和IBM有能力 提供全面的云计算产品

云计算类型公司名称简介

云服务提供商Amazon 公司提供的弹性云计算EC2, 已在世界范围内得到了相当高 的认可,许多公司采用这个平 台来搭建自己的云计算服务

Google Google 公司提供的Google 文 档、Google地图等多种应用都

是基于云计算环境的,当然也

提供云服务

Enomailism 公司发布了弹性计算的平台, 能为企业提供大型服务器基础 设施,以及解决建立自己云技 术相关的复杂性问题

ENKI 公司提供类似于Amzaon的服 务,为企业提供应用所需要的 云计算平台

Cloudworks 通过Web为中小企业提供计算 机、软件和数据外包服务

Salesforce.com 公司提供SaaS服务,具备一系 列用于云计算的开发工具包

世纪互联公司能提供云计算产品、云存 储产品等。

云计算类型公司名称简介

云计算平台提供商微软在发布Azure之后,微软公司已 经构建了自己的云平台,试图 打造互联网环境下的

“Windows”

经过长时间的实践和发展,云计算是在整个IT行业中孕育而生的。在网络设备商、移动通信运

营商、服务器提供商和应用程序开发商的通力协作下才可以最终形成云。他们在自己传统的业

务基础上,充分利用自己擅长的技术,跟着国际云潮流的步伐转型发展,所以要想真实了解他

们需要从他们前身开始。下面我们对以上20个提供商的前身进行了行业归类及百分比,如图11.3

和图11.4所示。

图11.3 各大厂商的前身分类图11.4 传统行业转型云计算的比例情

我们可以看出基于IDC托管服务的企业向云计算转型的最多,不管是跟潮流还是基于自身的发

展,充分体现了未来IaaS虚拟化服务器租赁市场的潜力;而基于传统SaaS等商务软件谋生的企

业也向更具有弹性的电子商务云转型;几大软硬件综合型企业更是不甘落后,而且更具有占领

云市场的潜质;传统的存储系统供应商则受到了多方面的压力,不光有以上企业的共同排挤, 云计算分布式存储技术瓶颈更是造成他们足滞的原因;而现在唯一还没有发威的通信运营商则

将成为未来云计算的最大黑马,它具有后台强大的服务器供应和未来云计算发展的关键技术- 思杰收购了XenSource之后,在虚拟 化方面迈进了一大步,使得开 发云计算平台有了足够的技术

储备

红帽近期发布了自己的虚拟化战略 的同时,也宣布了自身的云计 算战略

Parallels Parallels是提供操作系统虚拟 化和软件虚拟化的公司,有着 自己的云计算战略

Platform Computing公司该公司在HPC领域有着很强的 技术力量,正将自身定位从网 格计算过渡到云计算

VMware公司被EMC收购,VMware公司已 经成为一家云计算公司的子公 司

网络技术,让我们拭目以待。 11.6

产业综合分析

11.6.1

云计算与网络设备商的关系

互联网的发展离不开网络基础设施。可以说要发展互联网要先发展网络基础设施。而云计算又

是架构在互联网之上的服务,也许未来云计算发展的最大瓶颈也在于此。

云计算是通过虚拟化将资源整合,然后通过互联网将服务应用提供给终端用户。在这两个方面

网络基础设施是非常关键的。在虚拟化的时候,同时也将网络基础设施虚拟化到云里面。而在

给用户提供服务的时候更是离不开网络基础设施,总的来说:网络基础设施承载了将支撑云服

务的服务器、存储、安全和软件等设备和技术连接在一起的任务。

云计算最终要和用户交互,用户最关心的是响应速度快、网络稳定。保证在云计算下网络稳定、

快速、网络设备必须在资源、架构和应用上进行调整。目前国内外的一些网络设备商已经推出

了服务于云计算的网络设备。

对于网络设备商来说,单纯做网络基础设施的厂家也可以研究云计算,并推出适合于云计算的

网络设备,从而在云计算中也可站一席之位。甚至有可能的话可以考虑和一些厂商合作,共同

获益。不管是云计算的需要还是未来互联网的发展,网络设备商还有着一条任重而道远的路要

走。云计算服务对网络基础设施的需求及网络提供商所能提供的服务如表11.6所示。 表11.6 云计算服务对网络基础设施的需求

续表

云计算服务的需求相应网络技术及功能代表厂商

消除数据交互瓶颈,弹性平台通过超高性能交换平台极大地

降低时延,同时在架构上与计 算、存储、虚拟化等设备和技 术紧密结合,能够按照需求实 现高可扩展性,进而优化计算 (服务器)与交换的接口

思科、Force10、H3C、Juniper

存储端口整合通过数据中心网络整合解决方 案及虚拟化技术,改善和优化 存储与交换的接口

博科、思科、F5、Force10、 H3C

虚拟化支持通过在交换及优化设备上结合 虚拟化技术,实现灵活、按需 扩展的平台架构

思杰、F5、Force10

云计算服务的需求相应网络技术及功能代表厂商 本地/广域网流量管理,网站接 入体验的改善

通过应用交付网络、负载均衡 技术、4~7层交换等技术优化 思杰、F5

11.6.2

云计算与移动通讯运营商的关系

国内主要的移动运营商有中国移动、中国联通、中国电信。云计算一大特性,就是能够很好地

整合资源,节约成本,更加快捷、方便、灵活地响应客户的需求。如果移动推出了云计算,那

么他们就可以在低成本的云服务器里响应客户,提供更多的应用,每年可能节约上千万的成本,

有了这个钱就可以更好为客户服务,提供给客户优惠政策。

移动通讯运营商的业务繁多,用户遍及全国。其网点也遍及全国。我想没有哪个公司有这么齐

全的网点分布,如此多的网点在以前会认为是个很麻烦的东西,难于管理和维护,而对于云计

算来说它就是优势,微软现在正花巨资在全球各地到处找地方建立数据中心。如此大规模的网

点分布可以很快地响应全国任何地方的用户需求,需要将这些网点统一起来,作为云的基础架

构来推出云服务。不过问题就出现在通讯运营商现有的业务调整上,将他们移到云上、无缝转

接,是相当困难的,毕竟现在的云计算才开始起步,需要考虑的因数太多。目前中国移动已经

推出了自己的BigCloud计划。 11.6.3

云计算与服务器提供商的关系

Google的云计算是架构在廉价的服务器之上的,而现有的商用服务器都是相当昂贵的。比较常

见的服务器提供商有IBM、惠普、Dell、Sun、联想、浪潮、曙光、宝德等。现在企业、网站、 科研单位的服务器一般都使用厂商提供的专有服务器,而服务器的维护和升级很麻烦,有些公

司还卖服务器的服务,随着业务需求的扩展、公司规模的扩大不,正得不考虑重新选购性能更

加稳定、安全性更高的服务器。而这种服务器的价格一般是很高的,对用户来说是一笔高昂的

费用。云计算的到来对服务器生产商产生了极大的冲击,如果云计算这种模式在未来能够很好

运行,那么服务器厂商就必须要重新定位自己的发展。因为只要在保障网络畅通的情况下,以

前要花很多功夫,甚至还要找个人看好自己的服务器的情况就不存在了,用户只需要按需订购

自己的服务,而该服务是可伸缩的,可以随时更改服务,业务扩展了,再订购几台服务器就能

很好达到自己的需求。

服务器提供商如何定位自己呢,一些公司看好云计算,自己也在大力发展云计算。而一些公司

在观望,想看看云计算的发展前景。如果云计算真的到来,没有准备的厂商也就只有放弃这块

市场。在这里不得不提Google的服务器提供商,本来Google的服务器就是廉价的服务器,而其

提供的厂商更是大量如拥有这种廉价的服务器以及生产线,对他们来说也是一个机遇,他们已

经有发展云计算的基础了。未来云计算系统中有可能大量使用的就是这种廉价服务器。 基础设施平台,改善虚拟化带 来的复杂性

管理及可视性通过网络资源动态调整和自动 化管理,实现实时的按需定制, 同时降低总体运营和管理成 本,并具备深层虚拟化可视性 大多数厂商都支持 11.6.4

云计算与应用程序开发商的关系

现在的应用程序开发商、开发的软件有太多的局限,有系统要求、CPU、内存、磁盘等限制, 云计算让他们跑在云里,用户只需浏览器,使得开发商更加考虑软件的人性化,不必考虑去其

他的限制因素。开发商最头痛的盗版问题也很好地得到了解决。而开发商只需要转变开发模式,

使得开发的程序能够在云里运行就行。

对于软件的收费情况,开发商可能需要和云提供者商酌。现在很多软件都是客户个性化的定

制。

不同的用户会需要不同的软件,这个问题最好的解决方案就是PaaS(平台即服务),用户向云提

供商说明我要什么软件,由提供商为用户开发。或者效仿业界有名的SalesForce公司,提供一个

Force.com平台,提供一套非常简单的API,由客户自己开发,那么对应用程序开发商而言,就

是一个噩耗,应用程序开发商的生存空间都将变得非常小。当然,如果是知名的开发商,有用

户基础,值得信赖的话,可能就是客户委托你来开发,然后自己和云提供商谈合作的问题。 例如,对于游戏软件的开发商,云计算最有可能影响其开发模式和应用模式,2007年的统计显

示有13%的高性能计算机应用于游戏产业,这一比例超过了电信、气象等传统的高性能机群的

应用领域,这一点是较为出乎人们预料的,如图11.5所示。游戏企业拥有大量的服务器资源, 又是计算和存储的重要消耗领域,云计算体系的出现也会深刻地影响游戏软件的开发商和运营 商。

图11.5 高性能计算机群的应用领域分布

在云计算时代应用程序开发商的生存方式将会有所改变,技术的变化、收费模式的变化都是需

要这些开发商去适应的。__

因篇幅问题不能全部显示,请点此查看更多更全内容

Top