MySQL5 Master/Slave 同步配置

要求:
 

1.首先装好系统Redhat AS4.0 ;

2.Mysql-max-5.0.16-linux-i686解压缩不需要编译,直接安装就可以:
   shell> groupadd mysql
   shell> useradd -g mysql mysql
   shell> cd /usr/local
   shell> tar zxvf  /data/soft/mysql-max-5.0.16-linux-i686-glibc23.tar.gz
   shell> ln -s mysql-max-5.0.16-linux-i686-glibc23  mysql
   shell> cd mysql
   shell> scripts/mysql_install_db –user=mysql
   shell> chown -R root  .
   shell> chown -R mysql data
   shell> chgrp -R mysql .
   shell> bin/mysqld_safe –user=mysql &
具体的操作在其包里的INSTALL-BINARY文件中;

3.如果设置了iptables,请将3306端口打开;

4.两台服务器的ip:
192.168.1.56

192.168.1.57

 
 
具体过程:
 

1. 建立需要同步的用户和需要同步的数据;登陆到192.168.1.56服务器的数据库上:
    shell>mysql -uroot -p123456
    mysql>CREATE DATABASE bak;      //建立数据库
    mysql>GRANT REPLICATION SLAVE ON *.* TO tongbu@’192.168.1.57′ DENTIFIED  BY ‘123456’;     //建立同步的mysql帐号tongbu,密码为123456,指定只能从192.168.1.57上使用tongbu登陆,并可同步mysql中任意库
    mysql>flush privileges;

2. 登陆到192.168.1.57服务器的数据库上:
    shell>mysql -uroot -p123456
    mysql>CREATE DATABASE bak;
    mysql>GRANT REPLICATION SLAVE ON *.* TO tongbu@’192.168.1.56′ DENTIFIED  BY ‘123456’;
    mysql>flush privileges;

3. 把mysql/support-files下面的mysql配置文件复制到/etc目录下,
   # cp /usr/local/mysql/support-files/my-large.cnf   /etc/my.cnf
    其中.cnf文档如下:
     my-small.cnf     内存少于或等于64M,只提供很少的的数据库服务
     my-medium.cnf    内存在32M–64M之间而且和其他服务一起使用,例如web
     my-large.cnf     内存有512M主要提供数据库服务
     my-huge.cnf      内存有1G到2G,主要提供数据库服务
  
4. 修改192.168.1.56上的my.cnf文件,在这里我们把它命名为1号服务器
     #  vi /etc/my.cnf         
      在[mysqld]添加一下内容:
       log-bin=mysql-bin
       master-host=192.168.157         
       master-user=tongbu               
       master-password=123456           
       master-port=3306                 
       binlog-do-db=bak                 

   因为mysql默认是作为主服务器,因此不需要指定 server-id =1 这项

5. 修改192.168.1.57上的my.cnf文件,在这里我们把它命名为2号服务器
   #  vi /etc/my.cnf  ,首先在my.cnf文件中找到 server-id这一项,然后修改成:
       server-id =2
      在[mysqld]添加一下内容:
      master-host=192.168.1.56
      master-user=tongbu
      master-password=123456
      master-port   =3306
      master-connect-retry=30
      replicate-do-db=bak
      log-bin
      binlog-do-db=bak

    解释:
     master-host=192.168.1.57 表示本机做1号服务器时的master为192.168.1.57;
     master-user=username   这里表示2号服务器上开放的一个有权限的用户,使其可以从1号机器连接到2号机器并进行复制;
     master-password=password 表示授权用户的密码;
     master-port=3306  master上MySQL服务Listen3306端口;
     master-connect-retry=30  同步间隔时间30秒;
     replicate-do-db=bak   表示同步bak数据库;
     log-bin               打开logbin选项以能写到slave的 I/O线程;
     binlog-do-db=bak    表示别的机器可以同步本机的bak数据库.

  
6. 为两个数据库中的bak数据库建立或者导入相同的表。

7.  重新启动Mysql.
   # /usr/local/mysql/support-files/mysql.server restart

8.这一步非常关键,致是我在这里走了很多冤枉路,不知所措!
    登陆到192.168.1.56 数据库:    mysql>stop slave;
    mysql>CHANGE MASTER TO
          MASTER_HOST=’192.168.1.57′,
         MASTER_USER=’tongbu’,
         MASTER_PASSWORD=’123456′

   登陆到192.168.1.57 数据库:
        mysql>stop slave;
        mysql>CHANGE MASTER TO
          MASTER_HOST=’192.168.1.56′,
          MASTER_USER=’tongbu’,
          MASTER_PASSWORD=’123456′

在192.168.1.56查看mysql:
mysql> show processlist;
+—-+————-+——————–+——+————-+——+———————————————————————–+——————+
| Id | User        | Host               | db   | Command     | Time | State  | Info             |
+—-+————-+——————–+——+————-+——+———————————————————————–+——————+
|  1 | system user |                    | NULL | Connect     |   71 | Waiting for master to send event   | NULL             |
|  2 | system user |                    | NULL | Connect     | 1150 | Has read all relay log; waiting for the slave I/O thread to update it | NULL             |
|  3 | root        | localhost          | NULL | Query       |    0 | NULL  | show processlist |
|  4 | tongbu   | 192.168.1.57:32787 | NULL | Binlog Dump |   16 | Has sent all binlog to slave; waiting for binlog to be updated        | NULL             |
+—-+————-+——————–+——+————-+——+———————————————————————–+——————+
4 rows in set (0.00 sec)

在192.168.1.57查看mysql:
mysql> show processlist;
+—-+————-+——————–+——+————-+——+———————————————————————–+——————+
| Id | User        | Host               | db   | Command     | Time | State | Info             |
+—-+————-+——————–+——+————-+——+———————————————————————–+——————+
|  1 | system user |                    | NULL | Connect     |   37 | Connecting to master | NULL             |
|  2 | system user |                    | NULL | Connect     |   37 | Has read all relay log; waiting for the slave I/O thread to update it | NULL             |
|  3 | tongbu      | 192.168.1.56:32829 | NULL | Binlog Dump |   33 | Has sent all binlog to slave; waiting for binlog to be updated        | NULL             |
|  4 | root        | localhost          | NULL | Query       |    0 | NULL   | show processlist |
+—-+————-+——————–+——+————-+——+———————————————————————–+——————+
4 rows in set (0.00 sec)

如果看到这样的信息,说明双向同步成功了,否则检查以上步骤!

9.现在可以在bak数据库中,插入记录。检查同步情况!

实现MySQL数据库数据的同步方法介绍

1. 安装配置

两 台服务器,分别安装好MySQL,都安装在 /usr/local/mysql 目录下(安装步骤省略,请参考相关文档),两台服务器的IP分别是192.168.0.1和192.168.0.2,我们把192.168.0.1作为 Master数据库,把192.168.0.2作为slave服务器,我们采用单向同步的方式,就是Master的数据是主的数据,然后slave主动去 Master哪儿同步数据回来。

两 台服务器的配置一样,我们把关键的配置文件拷贝一下,默认的配置文件是在 /usr/local/mysql/share/mysql目录下,分别有 my-large.cnf, my-medium.cnf, my-small.cnf等几个文家,我们只是测试,使用my-medium.cnf就行了。MySQL安装完后,默认的配置文件是指定在数据库存放目录 下的,我们用的是4.1.X的,所以配置文件就应该在 /usr/local/mysql/var 目录下,于是把配置文件拷贝过去:

 

两台服务器做相同的拷贝配置文件操作。

 
 

2. 配置Master服务器

我们要把192.168.0.1配置为主MySQL服务器(Master),那么我们就要考虑我们需要同步那个数据库,使用那个用户同步,我们这里为了简单起见,就使用root用户进行同步,并且只需要同步数据库abc。

打开配置文件:

找到一下信息:

添加两行:

重启192.168.0.1的MySQL服务器:

 
 
        3. 配置Slave服务器

我们的slave服务器主要是主动去Master服务器同步数据回来,我们编辑配置文件:

找到下面类似的信息:

把上面的server-id修改为2,同时添加一些信息:

重启192.168.0.2的MySQL服务器:

 
 
        4. 测试安装

首先查看一下slave的主机日志:

检查是否连接正常, 看到类似这样的信息就成功了

在Master查看信息

查看Master状态:

查看Master下MySQL进程信息:

在slave上查看信息:

查看slave状态:

查看slave下MySQL进程信息:

你再在Master的abc库里建立表结构并且插入数据,然后检查slave有没有同步这些数据,就能够检查出是否设置成功。

最后,如果有兴趣的话,可以研究一下双击热备份,或者一台Master,多台slave的同步实现。

IBM程序总监的角色

Grady Booch 曾采访过卡内基· 梅隆大学软件工程研究所(SEI) 的资深研究员Watts Humphrey,本篇文章来源于采访的文字记录。Humphrey 谈到他在IBM担任程序总监的工作经历,包括如何处理邮件(在20世纪60年代这也是一个难题)、如何说服老板、如何在整个IBM程序部门推行项目计划概 念。
 
 

升任IBM程序总监

 

大约在1965年的秋天,IBM刚开始装载Model 50的时候,有一天,研究组组长Gardner Tucker对我说,“Watts,请给我写一份关于你认为应该如何管理编程的白皮书。”我说:“好啊。”于是我就洋洋洒洒地写了一份长篇大论。我当时的 确非常关心编程管理。和商业活动完全不同,我们需要制订计划以完成各种工作。我们曾制订了TSS系统计划(即分时系统),但是由于市场的压力,我们没有及 时修订计划,这是我的失败。市场压力是实实在在的,但是我也可以选择顶住压力, 制订一个更好的计划,而我们当时没有这样做。这真是我的失败。不管怎样,我给GardnerTucker写好了这篇文章。不久之后,我就接到了 Learson的电话,提拔我为程序总监,这时才得知,原来他们解雇了之前的总监。

 

Booch:不祥的兆头。

 

Humphrey:嗯,事实上那家伙被解雇的原因和管理毫无关系,而是因为他和他的秘书鬼混。我认识他,他人不 错,住在Chappaqua,有10个孩子,就这样他还是要和秘书鬼混。当时IBM有一个“门户开放政策”,员工可以给Tom Watson写信,公司里的任何人都可以直接联系Tom Watson或者董事长。现在应该不是这样了,但当时肯定可以。那个年轻的生产经理
给Tom Watson写信说:“我妻子是程序总监的秘书,她和总监鬼混,这事让我没法跟你的主管们竞争了,我希望你能摆平这件事。”于是Tom Watson做了一个门户开放的调查,发现生产经理说的是真话,所以就解雇了程序总监。程序总监走的时候把秘书也带走了,接着他和老婆离了婚,又和秘书结 了婚,干别的事情去了。我不能透露他的名字。但是我还记得去看过他的前妻,挺凄惨的。我就在这种情况下得到了那份工作,我敢确定那是因为我写的那份白皮 书。

 

Booch:你还记得白皮书里都写了些什么吗?里面有什么建议或者预测?

 

Humphrey:哦,我记得我写了两个关键需求,一个用于计划的制订,一个用来管理评论和全套程序的规则的结 构化流程。由于当时对质量的认识还不够,白皮书中没有列出质量这项内容,但是我确实让计划周期进行下去了,该做的事也都在做,所以我被招来了。这些事的顺 序我记不清楚了,不过一开始是会见Vin Learson。我在位于White Plains的程序总监办公室办公,配有两个秘书和一个助理,他们一天到晚都在整理我的邮件。

 

Booch:那时肯定是手写信件了。

 

Humphrey:是手写信件。他们每天都把信件做一个总结。每天的信件总结就是用一小段话记录每封邮件的内 容,整个总结大约有3~4页纸。我每天收到的信件堆起来足足有三英尺高。他们告诉我前任总监每天晚上都把所有的信件带回家,他所有的时间都用来干这个。我 说:“那好,我们来这样做。我只看我的领导、领导的领导、一直到Tom Watson写来的信。小组中其他人可以直接给我写信,我不看副本。如果有直接写给我的信,就立即给我,如果是别人信件的副本,我只要看看总结就行了。”

这样一来我突然没有任何信件了。于是我就有时间来处理事情和解决问题了。我的意思是,前任总监被信件困住了。我没有时间应付这些东西,而且他们大多 数没什么意思。很多人写信问我:“我下一步该怎么办?”我就说:“如果你确实遇到了这样的问题,就给我打电话。”我偶尔也会接到这样的电话:“这个我该怎 么做或那个要怎么做?”我回答说:“弄清下一步该做什么是你自己的工作, 如果我们需要知道, 你弄清后就告诉我们,不然就告诉你们领导。我不会告诉你该怎么做。”

 
 

Learson 的委任会议

 

Humphrey:基本上我很快就摆脱了那种循环。我记得一开始是Learson把我叫去的。那可能是第二周 吧,因为我记得第一周的第一天我去参观了几个实验室。我看到实验室的人首先就问:“你们的责任是什么?”他们说不知道。老实说他们知道要提供一些东西,他 们列出了这些东西的清单和完成日期, 很卖力地做着。但是那些基本上都是上面的规定,是按要求做的。市场通告决定着他们所做的每一件事,没有人对应该做什么有任何计划。我对他们说:“假设你们 要按正确的方式来做这个工作,你们会怎么做?”他们给我描述了一个逻辑性很强的做法,如果有计划、有要求、有时间表的话应该如何去完成所有的步骤。我就 问:“那你们现在怎么不这样做呢?”他们说:“我们没有时间。”我说:“这简直是疯了,难道你们没有时间按正确的方式做,却有更多的时间按错误的方式做 吗?”

他们说:“ 对,是这样的。”我说:“ 你们知道,这不合情理。”我离开之后又去了几个大实验室,其中一个是在San Jose,都有同样的经历。回来的时候我一直在想应该怎么办。大约就在那几天我接到了Vin Learson的电话,他要在我Poughkeepsie的办公室开会(我在White Plains和Poughkeepsie各有一个办公室)。Learson召集我和我所有的高级管理人员早上8点在纽约Poughkeepsie办公室开 会。于是我就去了。Learson是乘直升飞机来的,而我是开车,路上堵了一段时间,迟到了大约十分钟,我到的时候他正在滔滔不绝地发表长篇大论。屋里大 约坐着30来个经理人,他正在喊着“你们在置公司于死地,你们会把业务给毁了”之类的话。我进去坐下看着这一切,慢慢了解到原来是因为程序计划已经失败三 次了。

他们正在做硬件, 而软件什么时候能交付,没有人想过,也没人相信。市场一片混乱。顾客很失望,不想再买任何东西了,整个市场死气沉沉。不过有趣的是我们当时正在卖TSS Model 67,因为人们相信它。就这样,Learson捶着桌子发表完了他的长篇大论。Learson人长得高大,很有魄力,直觉和判断力都很强,而且很聪明,但 他还是捶着桌子说:“该死的,我必须在两周之内拿到计划表。”

他环顾四周,所有人都把目光投向了我。天啊,我刚上任还不到一两周就要制订这个计划。我看着他说:“Vin,如果你想要的话我今天就可以给你一份计 划表,但是那样的话明天我又可以给你一份不同的计划表。如果你想要一份可行的计划表,请给我60天时间。”他在屋里走来走去,逐一询问那些经理人:“你觉 得怎么样?”每个人都回答说:“是的,要60天。”于是他转过来对我说:“好吧,该死的。”然后又捶了一下桌子冲出门外。显然,我成了这次会议的挽救者。

 

Booch:很厉害,你说的那些话没有人敢说。

 

Humphrey:之前也从来没有人说过。我能那么做是因为我了解Vin,他的要求是不可能达到的。我的意思是 说,有些实验室是在法国和英国,我不可能在两个星期之内跟所有人交流。制订计划表是一项艰难的工作,所以突然之间我从一个无名小卒变成了英雄,而且我确定 Learson是故意这么做的。

他想把我推出去,因为我是“敌人”。还记得TSS Model 67是360的敌人吧。我那时负责分时组,正是360的竞争者。所以我是以敌人的身份被安排来负责360程序的,Learson想把我塑造成一个英雄,并 且他知道应该怎么做。我在担任系统和应用工程总监时,Learson常常要我去他的办公室开会,我不得不去开那些会,完全不知道他们在说什么,也不知道为 什么要我去那儿。

等会议结束那些家伙离开之后,Learson看着我说:“你说他们想干什么?”我说:“我不知道,他们说想这样。”然后他说:“那不是他们想要的, 他们想要的是这个。”他能看破所有这些东西,很了不起。我记得有一次他对我们大发脾气,起因是我们想招系统工程师(我当时既是系统工程总监,又是程序总 监)。我去向他解释为什么需要招人,而每次他都会用事实和数据来作回应——我不知道他从哪儿弄来的这些东西——但是他显然比我知道得多,所以他总是能赢。 后来我和同事说起这事,他们就去查访。一天,有个员工对我说:“我知道是怎么回事了。有个家伙在市场组的地下办公室工作,而他以前是给Learson办事 的,是Learson的老朋友。所有记录和数据他都了如指掌。我估计Learson的信息是从他那儿弄到的。”

 

Booch:他是你的眼线。

Humphr ey: 是的。我说:“噢,好,那我们去找找他。”于是我们给他打电话,然后过去和他聊了聊。我跟他提了我们的建议和理由,把整个事情也都跟他讨论了,并阐释了我 们的一些想法,他表示赞成。他觉得那些想法很有道理。我说:“那太好了,谢谢你。”等到下次去见Learson的时候我说:“顺便说一下,我跟某某人聊了 聊,他说如何如何。”Learson只是笑了笑,讨论结束时他就接受了我的意见。所以,他真的很精明。他只是想要知道我能不能做到这些,而事实证明我可以 做到。他确实是个了不起的人。

所以, 作为程序总监,我发现员工没有按正确的方式来做事的原因在于他们别无选择。因此问题不在他们,而在于我。他们没有按正确的方式做事的原因是他们编程只需做两件事:写代码和测试。对吧?

 

Booch:对。

 
 

仅仅是写代码和测试

Humphrey:这就是他们全部的工作。关于要做的东西他们可以列出很长的清单, 但对于交付产品来说, 最重要的只有两点, 而与他们相关的只有一个问题, 那就是交付产品。这样造成的后果是, 如果我让他们仅仅写代码和测试,他们一天到晚就只能做这两件事,没有时间做别的了。所以我意识到问题的关键在于没有一套合适的要求来规定他们应当如何交付 产品。于是我找到Frank Cary,他是集团总裁,管理所有开发项目。我说:“Frank,这就是我们的问题所在, 如果要解决它就必须制订计划。现在我将解决这些问题, 并且保证在重新宣布任务的时候对每件事都有计划。我想公开所有的计划,并通知营销组织60天内我们会制订新的计划。”他同意了。

我就照我说的去做了。为此,我向每人发了一份电报。现在,工程师们可以按照他们的想法来编写和测试程序。但是我们不打算发布任何信息,也不打算交付 任何东西。我们不会做任何事,不会做任何程序,甚至不做任何投资,除非我桌上有一份计划。他们必须在60天内回到我这儿,跟我一起审核所有重要的计划。我 不可能看完所有的细节,但是每一份重要的计划他们都必须亲自和我一起审核,我想保证每份计划上都有将为之工作的每个人的签名。我不想他们为不同意这些计划 的人制订计划。

就这样我发布了这个指令,我告诉你,它的影响之大,绝对是世界性的。人们开始制订计划了。我们需要去请一些制订生产计划的人来跟我们的程序员座谈, 以展示计划是怎么回事。这些人将成为程序员的计划顾问。生产部门向程序员讲解计划,这很有用。然后我们就有了很好的计划,他们把计划拿给我审查,我边看边 说:“首先我要的是一份可行的计划。”这时我突然改变了做法,因为之前这些事我们需要逼着他们来做。我跟他们讲:“你看,之前的总监被解雇了(他们不知道 内情,但我知道),我可不想被解雇。你们没有完成计划可能只是尴尬而已,但是我可就要玩完了。我不想被炒掉,所以你们必须制订可行的计划。”于是他们就开 始检查计划,我在旁边督促,让他们展示计划是怎样可行的。比如有没有足够的资源?时间安排是怎样的?我没有缩减一份计划,甚至还扩充了一些,并且规定每份 计划有90天的缓冲。

 

Booch:那这是集团有史以来所做的最认真的一次计划,可以这么说吗?这对他们来说是从未有过的。

 
 

实现计划

 

Humphrey:他们从来没有制订过计划。他们根本不知道计划是什么东西。我们开了一个课程。我把AI Pietrasonta从联邦系统分部请来为我们讲课。我记不清是为期一周还是两周的计划课程了。在接下来的几年里,我们对1000名经理人进行了计划培 训。包括来自销售部门和其他部门的所有人都必须接受培训。那个课程很好,AI讲得相当不错。几年前他去世了,我有一本书是献给他的,不知道你认不认识他。 不管怎样,我在每堂课上都会讲这些,周五的下午我还要讲。这样一来就能引起每个人的重视,所以大家制订了这些计划而且都做到了。两年半以来,我们从来没有 逾期过一天,不可思议吧?

 

Booch:真是太棒了。那些90天缓冲后来进行得怎么样?

 

Humphrey:这个我要说说。起初,Frank Cary同意我停下手中的一切事务来执行公开计划表这件事的时候,他对我说:“你必须向获得百分奖的营销部门讲清楚我们到底在做什么。我们一共有4个百分 奖团队,他们都是公司里最好的销售人员。他们要开一个3000~4000人参加的团体会议,你去给他们做个演讲,告诉他们我们在做什么。”于是我把遇到的 性能、计划等各方面的问题以及解决这些问题的方法都列了出来,一共大约准备了1个小时的演讲内容。然后我就去给这些百分奖团队开会,演讲道:“我们公开了 所有的计划表,并且将在60天内制订新的计划,下面是我们正在做的事情。”我就这样和他们讲,向他们描述执行上的问题,以及用于度量性能的度量系统和其他 事情。我讲得挺不错,一共讲了四次。后来有一些销售人员来投奔我,MikeArmstrong就是其中之一。你知道MikeArmstrong吗?

 

Booch:名字挺熟,但是我真的不了解他,给我讲讲吧。

 

Humphrey:他是我住在康涅狄格州Darien时的邻居,IBM高管之一。在一次重组中,有人升职了,他 却没有,于是他离开了IBM,在休斯飞机公司(Hughes Aircraft)担任了一段时间的主管,然后又去了老AT&T做CEO。他管理着那家公司,当中还遇到过一些问题,但是不管怎样,他是个好人, 也是个不错的老板。他后来好像在技术人员方面遇到了麻烦,但是当我在IBM遇到他的时候他告诉我他做过普通的销售,并且说:“我们第一次有了可以销售的东 西。”我在百分奖团队的讲话完全改变了销售队伍。他们说:“现在我们终于有了可以相信的东西。”他们回去之后颠覆了整个市场,因为他们相信我,对我有信 心。虽然我没有告诉他们具体的计划,但是我们把一切都公开了,我们确实在60天内有了新的计划。对于我规定的90天缓冲,那些团队都说:“我们认可你的 90天,我们会完成计划并且一直遵守它。”最初的几个发布时间都提前了90天。突然之间整个市场面貌都不同了,我是说突然之间大家都在计划表之前完成编 程,那是大不一样了,这样他们的东西好卖了,同时也完全改变了我与销售部门的争论局面,因为现在人们相信我了。这时如果我说还要花费一年或半年的时间,也 没有人会反对我。

敢问路在何方——项目经理成长手记

作者以某教育网系统建设项目为背景,分享自己真实的实战经验与心得,对项目经理的成长有很好的指导意义。

 
 

唐僧师徒赴西天取经,不畏艰险,锲而不舍,历经八十一难最终修成正果。这是一段伟大的旅程,敢问路在何方——路在脚下!世上没有不能到达的目标,最 远的路途就在脚下,这是西游记让我们深深感动的地方。西游记绚丽多彩的魔幻世界其实是现实社会的投影,平凡的人们为了生存和发展都会历经磨难。作为一名 IT业的项目经理,我深刻地体会到:这是一个充满挑战和艰辛的职业,但也是一个自我发展和提升的途径。一帆风顺的经历不会增长才干,帮助个人成长的其实是 困难和障碍以及克服它们的过程,只有经历风雨,才能迎来彩虹。

 

本文以我负责的某大型教育培训网站(简称教育网系统)建设项目为背景,结合项目实战经验谈一些体会。这个项目是我初任项目经理时经历的,现在回顾起来,当时所遇到的问题以及解决过程还历历在目。

 
 

甲方不提供硬件测试环境,争取提前试运行发现问题

 

该项目要建设一个在线学习和教育管理网站,提供在线学习和考核的平台,实现培训工作的信息发布和组织管理。平台所使用的课件由其他系统制作,本系统 需提供课件上传管理功能。系统采用Oracle数据库、WebLogic应用服务器,通过F5实现负载均衡,使用基于J2EE技术的B/S架构,要求能够 运行在Unix平台上。

 

接手这个项目后,我首先对系统的运行环境做了初步了解。客户方的机房有多台IBM AIX小型机和PC机。WebLogic应用服务器将部署在 AIX小型机上,在一台AIX小型机上会同时部署多家公司的应用系统,每个应用系统在WebLogic中都通过建立独立的域(Domain)来进行管理。

 

任何应用系统在上线前都应进行严格的测试,而且测试环境要与实际运行环境一致,因为应用系统的功能、性能在不同操作系统环境下的表现是不一样的,因 此为了保证系统的稳定运行,需要准备AIX小型机作为测试环境。但是我们以前承接的项目使用的基本都是HP和SUN的服务器,没有AIX服务器。

 

我意识到这是一个重要风险,必须妥善应对。客户的机房有一些测试设备可供使用,我与销售经理沟通,看有无可能得到客户许可使用机房的测试设备。这个 项目当时还处于售前阶段,正在签署合同。销售经理反馈回来的结果是,客户不负责提供测试环境,并且在合同中对此增加了明确的条款:甲方不负责提供任何测试 设备和环境。我在客户这边碰了壁,只好另外想办法,首先想到的是从公司获得支持。

 

项目启动后,我在项目计划中上报了这个风险,希望公司帮助调配一台测试用机,或者采购一台AIX小型机,在各个项目之间共享,解决多个项目可能会遇 到的同样问题。项目管理部很快打来电话,询问了详细情况,表示公司调配有一定困难,其他项目并没有闲置的小型机,目前也没有采购机器的预算,希望项目组尽 力设法解决,并强调一定要妥善处理,不能因此发生问题。

 

回想我当时的心情真不好受,感觉孤立无援,但是我从这个过程中也学到了重要的一课:项目经理的作用不只是发现问题、提出问题,更重要的是解决问题。系统测试的硬件环境不具备,客户和公司都不能提供支持,这是一个必须解决的难题。

 

这个问题放在现在是很好解决的,可以花少量费用短期租赁,但当时IT租赁业还没有发展起来,可以提供设备的大公司价格很高,而价格较低的小公司设备 又不全。我询问了两个关系不错的合作伙伴公司能否借用,对方当下没有正好闲置的机器。看来这个风险不能避免,那就要从如何减小风险的影响程度上寻找对策。 我一方面继续寻找机器,一方面积极与客户沟通,最终得到客户的支持,允许我们提前到正式环境下部署,在系统大范围试运行前先小范围试运行一段时间,这样就 为解决可能面临的问题赢得了时间。

 
 

排查问题定位原因,但遭咨询方质疑

 

在我的推进下,系统得以提前部署到正式环境中,但不久就发现了一个严重的问题:课件的视频文件通常在几百兆左右,在上传到AIX平台时,速度非常慢,只有40KB/s,以至于浏览器页面失去响应,只有十几兆的小课件可以上传成功,稍微大一点的课件就传不上去了。

 

我组织项目团队深入分析了这个问题,通过比较测试环境与正式环境的不同之处,定位问题的原因可能来自“网络环境”或者“操作系统”,此外应用程序上传组件在正式环境下能否正常运行也有待验证,根据初步分析,我们制定并实施了以下问题排查措施:

在客户方环境下使用FTP工具上传大视频文件,并使用网络监测工具观察上传过程是否正常,结果上传速度很快,网络监测也完全正常,基本排除了网络因素;

 

在客户方Windows环境下搭建WebLogic应用服务器进行测试,在上传代码中增加日志输出功能,打印分段传输文件过程中每段的用时和传输速度,结果上传速度很快,可以确定上传组件正常运行;

 

对操作系统的问题,为进一步缩小问题范围,我们在公司搭建了HP Unix测试环境,上传速度仍然很快,这样基本确定问题是由AIX操作系统带来的。

 

我组织项目团队成员继续奋战,查阅了AIX操作系统的大量资料,在团队技术骨干的分析和论证下,最后定位问题原因在于一个AIX操作系统的网络传输 参数。于是我们写了一份分析报告提交给用户,说明了排查的过程和结论,请求客户方允许我们调整AIX操作系统的一个参数,问题就可以迎刃而解。

 

但是事情并不像预期的那样顺利,客户方请的咨询公司认为我们的报告证据不足,认为问题是应用系统的错误造成的,应修改应用系统,不应调整参数,而且 由于AIX系统上运行着多家公司的多个应用系统,调整参数可能对其他系统产生影响,因此咨询公司坚持在没有得到权威结论前不同意调整参数。

 

我们一时找不到AIX系统验证我们的结论,但是客户方要求我们尽快解决问题,迫于时间压力,我们只好采用了权宜之计,修改了技术方案,从系统设计上 做了调整,增加了一种课件上传管理的方式,避开了直接通过应用系统上传,这样做会增加一些操作步骤,但能够满足课件后台维护的要求,客户也认可这种修改方 案,这个问题基本得到了解决。

 
 

用事实回应质疑,赢得甲方肯定

 

问题虽然得到解决,但我的心里却很不踏实:我们的排查结论是否正确还没能在AIX系统上进行验证,这次绕开陷阱的做法只是权宜之计,对系统今后的推 广和产品化等工作会带来隐患,也许我们在未来还会再次遇到这个陷阱。此外,由于咨询公司多年服务于客户方,有重要的地位,他们的意见会左右客户方对我们的 评价。这是我必须彻底解决的又一个重要问题:如何用事实证明我们的实力和价值。

 

我一直没有放弃多方寻找问题的解决方法,也一直保持和合作伙伴的联系。当时我还负责另一个项目,需要第三方测试,为此请了专业的第三方测试机构。他 们拥有各种品牌、型号和配置的服务器,这让我看到了转机。在第三方测试工作开展的过程中,我与测试机构的负责人建立了良好的关系,在我提出需要免费借用设 备时,对方很爽快地答应了。

 

我们很快在AIX操作系统上搭建了应用系统,进行了期待已久的测试。选定几个不同大小的视频文件样本,在网络传输参数tcp_nodelayack 为缺省值0的情况下进行测试,结果与在客户方现场的表现一样,文件上传速度为40KB/s左右,50MB以上的文件就不能成功上传。当把该参数改为1,再 用样本文件测试,结果上传速度显著提高,达到4MB/s。我们详细记录了验证过程,写了一份报告发送给客户方和咨询公司,用事实证明了应用系统没有问题, 排查结论是正确的,赢得了客户方对我们工作的肯定。

 
 

软件供应商中断业务,拒绝提供支持

 

教育网系统正式上线运行取得了很好的效果,客户方决定在其20个分支机构推广,经过方案论证,确定以建成的教育网系统为中心,在20个机构采用分布 式结构部署系统。客户方很快召开了全体会议,要求分支机构尽快完成硬件准备工作。我们了解到,分支机构的设备很多是以前客户方总部统一采购的,AIX小型 机占主导,有些分支机构的业务量较大,资源比较紧张,就为此又购置了AIX小型机。

 

硬件准备好后,客户与我方签署了“软件开发服务”合同,要求分别根据分支机构的个性需求对教育网系统进行改造和完善。在系统推广的工作中,又出现了 一个棘手的问题:系统需要使用R公司的视频服务器R Server用于播放课件,R公司在中国已经中断了基于AIX的R4及以上版本的产品销售、服务和技 术支持,即使是R4也仅在AIX 4及以下版本的操作系统上进行过严格测试,而分支机构购置的AIX小型机都是AIX 5以上版本,所以根本无法得到可靠 的视频服务器。总部通过一段时间积累了很多课件资源,这些资源都是基于R公司独有的视频文件格式,并需要与分支机构共享,所以不可能转移到其他视频服务 器。

 

针对以上问题,我组织项目团队进行了分析,根据我们对R公司视频服务器的技术积累和掌握程度,可以确定:在AIX 5版本上运行未经严格测试的R4并没有问题,我们可以考虑采购R4替代高版本产品用于AIX 5。下面的问题就是如何说服R公司破例出售给我们R4。

 

我为此与R公司进行了多次沟通,详细说明了我们遇到的问题,希望得到支持,R公司的负责人在与美国总部沟通多次后明确表示这是总部确定的销售政策, 不能破例,而且R4缺少某些新特性,对项目开发、实施不利,强烈建议我们改用其他操作系统,采购最新版本。但这就意味着客户方花费几十万购买的小型机不能 投入使用,这是客户绝对不能接受的,事情一时陷入僵局。

 

这个问题并不孤立,还连带一些潜在问题。根据用户数量的发展情况,系统总部及其分支机构以后很有可能需要做视频服务器的集群,因此并不是只解决目前的问题就可以了,一定要未雨绸缪,否则未来仍然会面临这个问题。

 

在这个项目中,我方按照“软件开发服务”合同的要求,只负责软件部分,并不负责软硬件系统集成,但这个问题不解决,就无法顺利推动项目进展。突破责 任的界限与职责范围,站在项目整体利益的高度,我必须设法使软件供应商改变拒绝的态度,全力支持,破例出售足够数量的R4软件使用许可,并与我们共同面 对、解决出现的问题,这是关系到系统是否能顺利推广的一个关键问题。

 
 

借助甲方力量,协调软件供应商共担风险

 

我仔细分析了现状,列出要解决的两个具体问题:第一是说服R公司出售R4低版本产品,第二是要保证不能因为采购了R4而造成未来有些业务需求不能实 现。我仔细分析了高版本新增的功能特性:在分布式环境中实现课件共享和支持移动设备。前者可以通过应用系统实现,我们已经在这方面有了扎实的技术积累,而 后者虽然目前客户没有需求,但是未来怎样没有把握。

 

这些未定因素需要尽早摆到桌面上,把风险提出来,引起相关各方的重视,最好能够促成客户方与R公司直接对话,这样在客户面前我们可以共担风险,而且也可以借助客户方的力量推动R公司按特例处理这个问题,避免我方独立面对客户,处于不利的地位,承担过重的责任和压力。

 

为此,我组织了由客户方相关分支机构(包括业务部门和信息中心)、项目监理方、R公司和我方参加的项目专题会议,在会议上我详细汇报了目前的问题、建议的解决方案以及我们和R公司已做的工作的进展情况,并听取客户方的指导意见。

 

客户方的业务部门明确表示:未来五年内不会考虑升级到更高版本,不会有移动设备视频服务的需求。这样,我顾虑的第二个问题就打消了。R公司在会议上 也表示虽然很难,但通过努力能够向美国总部申请一定数量的许可满足客户需求,如果在实施过程中出现任何问题,也将协调国内、国外的技术人员给予解决,将大 力支持系统的建设。

 

我安排专人对此次会议做了详细的会议纪要,与会各方都在纪要上签字并各自留存纪要副本,通过协调会,各相关方都充分意识到这个问题,并进行了深入的分析和探讨,最后明确了问题的解决方案并作出承诺,为项目的顺利进展扫清了障碍。

 

通过解决这个问题,我体会到:在项目实施过程中,项目经理一定要主动与客户方密切合作,加强沟通,客户方的充分参与能有效地协调供应商,增强项目经 理对项目的控制能力。此外,对于己方不完全掌握的技术,不能单方面过度承诺。我们要有高度负责的敬业精神,但同时也要善于通过沟通、协调与合作伙伴分担责 任。

 
 

总结

 

项目经理在项目实施过程中经常要承受来自各方面的压力,面对各种问题,例如缺少软硬件资源或者人力资源等,在孤立无援的情况下面对各方的不支持、质疑和拒绝,项目经理要施展自身的沟通协调能力,用事实证明实力和价值,改变各方的态度,为项目赢得更多的支持、认可和帮助。

 

困难和障碍是最好的老师,它能够引导我们在通往成功的阶梯上一步步向上攀登。宝剑锋从磨砺出,梅花香自苦寒来,项目经理朋友们:祝愿你们在取得“真经”的路上走得更远,祝愿你们的旅程更丰富、更精彩!敢问路在何方?路在脚下!

 
 

作者简介:

董轶,IPMP B级国际高级项目经理,IBM 360°精英讲师团成员,自1996年起从事软件开发,曾任软件架构师、售前咨询顾问、项目经理、项目总负责人,具有多年大型复杂项目的管理经验。

架构师接龙:百度架构师侯震宇VS. 百姓网技术总监潘晓良

主持人:冯大辉,现任丁香园 (http://www.dxy.cn)网站CTO。曾历任支付宝架构师、数据库团队负责人等职。

 

侯震宇:在编程模型上,您认为如何能够更好地利用多核以及多机环境?

 

潘晓良:我是把它分成两个问题来看的:一个是多核问题,另一个是多机问题。

 

对于多核问题,我是一个实用主义者,真的不想在上面有所投入。我把多核环境认为是操作系统应该完成的事情,相信微软和Linux的那些内核朋友们都 在为此而努力,因为他们是专家。但看着几个核的资源分布严重不均,一颗累死,十一颗闲死,资源实在太浪费了,怎么办?让系统工程师来搞定吧,就是多跑几个 进程,最简单的例子就是一个机器上起多个Memcached、多个Search、多个MySQL,既然操作系统无法把一个进程很好地分到多个核上去,那么 我们就用人为的方式来做一些,这虽然不能彻底解决多核效率的问题,但是至少缓解了一点。而且据我所知,很多公司都是这么做的。

 

对于多机环境,按我的理解,问题只有一个,就是数据访问必须是共享的,对于一个Pool中的Web服务器,它不能使用Session,也不能把数据 放到本地文件中,因为不知道下一次访问会不会命中自己,包括本地缓存,随着Pool中服务器数量的增加,命中率随之下降。虽然以上的问题可以通过负载均衡 的固定Session方式或者URL映射的方式来做,但是它可能造成服务器的压力分配不均,后面带来的问题可能更多。所以我们的方式就是禁止直接使用 Session等本地资源,使用上面一层的虚拟对象,由虚拟对象来控制数据访问,而使用共享的Cache来实现Session的基本功能。

 
 

侯震宇:在纯代码层面上,您的团队是否有规范以确保大范围的代码组织结构是统一的。比如有项目的lib、include目录和基础库等。你们是否实现了一个统一的编码编译环境?有什么困难?

 

潘晓良:对于百姓网来说,因为我们只有一个产品,基本上还没有多项目的问题,但是我想这个问题的关键还是在编码规范上,在于代码的质量和不断增长的代码数量之间的矛盾的问题。关于这个我们做了以下几个事情。

 

由Developer们讨论出来的编码规范。规范的事情是这么写也对,那么写也对,但就是要争取大多数一致,所以我们的规范是Developer们一起讨论出来的。

 

标明代码责任人。以前我们的代码是按照模块划分的,但是人会换模块,后来就会多出来很多无主代码,这些无人维护的代码,不仅容易出现Bug,而且增加了阅读成本,所以必须清理掉。

 

每日上线的时候把每个人的代码数量统计发出来。我们认为代码的少就是多,每个人有责任控制自己代码的数量,是多是少大家都要看见。

 

每周固定时间Pair Programming。代码质量的重要性大家都知道,但是给予的时间却不多,我们有固定时间段用于Pair,一来可以加强开发人员沟通,二来可以提高代码质量。

 

给实习生一个平台。实习生很有Passion,而且有很多自己的想法和独特的视角,其实他们在学校里面学了很多东西,只是缺乏应用,我们的实习生可以访问所有代码、修改任何一行代码,只要稍加指导,他可以做任何他愿意做的功能。

 

统一的编码编译环境非常重要,必须实现。互联网软件开发依赖的环境很多,数据库、搜索、缓存、定时脚本、消息队列、Web服务器等多种服务,要是自 己搭建肯定是事倍功半,一人发几台机器都不行,不仅资源浪费,而且环境不同,也会带来很多意想不到的Bug。我们在实现了统一环境之后,每个人都只需要用 一个笔记本开发就可以了,既节省了资源,也极大地方便了Pair Programming,方便了工具的统一和思想的交流,也方便实习生的学习和融入。

 

实施统一编码环境的障碍肯定不是技术,最大的困难还是人,首先需要团队的Leader支持,其次需要有好的方法分步骤实现。开发人员都会认为自己的 习惯很好,不愿意改变,所以只能先小范围尝试,让愿意改变的一部分人先满意,培养他们的幸福感,然后他们就会去影响其他人,再来几次Pair以后,就慢慢 都被同化了。

 
 

侯震宇:在大规模机器集群上,你们如何实现程序发布上线、配置的管理以及程序和机器的监控和健康检查?

 

潘晓良:百姓网是每日发布产品的,只要是工作日就会有版本发布,但我们不是从第一天就是这样的,我们是从每周发布一次,到每周发布两次,到现在每天 发布一次的,整体来说,每天发布让我们的迭代周期缩短,加快了产品更新的速度,但是也会带来很大的问题,比如Bug增加等问题。每日上线其实对我们来说是 一个很大的挑战,有很多工作需要做。

 

自动化打包。百姓网是使用PHP开发的,可能有人说不需要Build,但是打包过程可以做很多事情,压缩、去注释、代码统计等很多工作都是在这个时候完成的。

 

自动化测试。这个过程非常关键,必须通过所有的Unit Test和重要流程的测试之后才能发布,如果出现重要流程失败,则需要找相关开发人员找到问题,然后重新打包,这是基于打包全自动、够快的前提的。

 

部署上线。那个时候就是一个按钮的工作了,当然这个时候最重要的就是确认上线中是否有问题,即使再详细的测试,也不能保证线上环境能够顺利,所以上 线之后我们就要关注关键功能是否有问题,我们有一个Rollback的标准,达到这个标准则必须Rollback,如果达不到这个标准,则直接在线上进行 Hot Fix。

 

关于配置的管理,也存在于版本控制工具中,比如叫config.online.php,在自动化打包的时候,会被命名为config.inc.php,通常情况下,线上环境配置是不需要更改的,而在配置更改的时候,只需要修改它就可以了。

 

关于程序和环境监控的问题,我们基本上采用Cacti、Nagios这样的主动和被动监控工具,但是它们都是在系统级别上,除非是程序导致系统压力 有巨大变化的状况,程序中的问题就不能被发现,所以我们还有程序级别上的监控,最主要的是监控错误日志,主要是PHP错误,如果有错误,那么开发人员很快 就能收到邮件,可以及时修复。

 
 

侯震宇:在目前国内的网络环境下,一个分布式系统是否需要考虑多机房问题?如果需要,主要考虑哪些问题?

 

潘晓良:关于多机房,我觉得完全取决于业务需求,即访问速度是否影响了业务,如果影响了,那么南北机房应该是最有效的方式,但是我觉得这里面的成本 还是很高的,一个机房变成两个机房,就如同是一台Web变成两台Web,对于系统架构的影响比较大。百姓网是经历的这样的过程的,我们考虑多机房是完全基 于业务发展的需要,不过多机房也没有那么可怕,就是要多付出一些成本。

 

硬件维护成本。通常都是异地,有人驻扎还稍好,无人驻扎,正常的机器维护都会成问题,我们的解决方案就是使用刀片服务器,虽然硬件成本上升了,但是少了人员维护成本。

 

可用性风险。我不知道有多少公司会让两个机房有相同的承载能力,能够以一个机房之力承载所有请求,因为那意味着大量冗余,所以肯定是各自承担一部分 的压力,但是宕机的风险却加倍了,而且还引入了另外一个风险,就是机房之间通信的风险,网络的延时可能会对业务造成很大影响,如何消除延时或减小网络延时 对于业务的影响就是最关键的一点。

 

开发、部署、调试的成本。代码部分会产生一些修改以支持多机房,部署的时候两边都要走,即使是自动化发布,也需要写脚本,特别是调试的时候,更加需要知道是哪个机房的问题,我们曾经遇到过只有一个机房出Bug的情况,调试的时候等于说是增加了一种因素。

 

多机房看似只是多了一个机房,但是对于运维来说,很多工作就变得复杂很多了。

 
 

侯震宇:对于机器选型问题,是为不同的大型专有系统(如分布式存储)专门配置的机器,还是统一采购同一类型的机器将不同的系统共享一个物理集群?这两种方法有什么优缺点?如何选择?

 

潘晓良:不同类型的机器的好处是度身定制,物尽其用,比如存储的机器的硬盘大,缓存的机器内存大,Web机器可能就用最小的硬盘等,虽然看起来很 美,但是不灵活、不通用,多出来的大硬盘机器,其他地方用不到,反过来小内存的机器又不能给缓存的机器用,特别是在做系统调整的时候,很多机器因为不合适 而不能用了,反而容易造成资源浪费。

 

相同型号就是完全反过来,它有明显的好处——通用,放在哪里都能用,但是问题就是可能对于某些特殊应用不是很适用,做存储的话硬盘小了点,而做Web服务器可能硬盘又大了点。

 

对于这个问题,百姓网通常还是会选择用一种型号,然后再对不同类型的服务器去升级硬盘或者内存,而CPU等核心的内容基本上一致,这样就既能保留通 用性,又有一些灵活性。不过我们还是会在一些特殊应用上采购一些特殊机器设备,比如数据仓库,它们对于容量和计算的需求就会超过正常的机器的范围,可能就 有一些特殊的要求,我觉得这里面还是一个平衡的艺术。

 

不过我们觉得这种灵活性还是相对的,因为机器的升级速度太快了,通常1~2年就有一种新升级型号,之前的内存硬盘都有可能很难买,或者价格很高,这时候就宁可选择新型号,而把旧型号放到一些非关键应用上。

 

以上是我们在使用过程中的一些感想体会,不能说放到哪里都准确,欢迎技术朋友们发邮件过来指正,我的邮箱是 panxiaoliang@baixing.com。另外,我们也非常欢迎喜欢互联网的技术人员或者同学来百姓网工作实习,我们的职位发布在 http://jobs.baixing.com/。

架构师接龙:腾讯高级工程师邝宇恒VS. 百度架构师侯震宇

主持人:冯大辉,现任丁香园 (http://www.dxy.cn)网站CTO。曾历任支付宝架构师、数据库团队负责人等职。

 

邝宇恒:在架构设计上,你们是否已形成某种设计风格或设计惯性?如何评价这种风格或惯性的影响?

 

侯震宇:设计风格不敢妄谈,不过我们在设计上确实存在一定的惯性思维。比如哪些类型的服务应该使用数据库,哪些不应该使用。惯性思维是建立在成功经验积累之上的,这在很大程度上简化了我们的设计工作并降低了引入新技术(这里指与习惯不同的技术)可能带来的风险。

 

但惯性思维往往阻碍了我们的技术发展。比如长期以来我们认为数据库的性能是相对比较差的,不足以满足很多业务的大压力的读请求,于是我们在一开始系 统设计时就对服务架构设计了拆库拆表的支持,增加了系统的复杂度。这时惯性思维会让我们认为这样设计合情合理,不会进一步考虑是否有更好、更简单的设计。 但在SSD引入可以解决高并发的随机读问题后,原先的系统认识已经不存在了,设计可以大大简化了,这时我们的惯性思维是必须打破的了。

 

所以作为一个架构师,我们要非常清楚,所有的设计都是建立在一些假设条件和系统规模之上的。当系统规模变得超出早期设计的假设条件,或者一些外部新技术打破我们早期的一些认识时(如SSD的引入对存储系统的冲击),惯性思维就必须打破。

 
 

邝宇恒:对某个特殊需求,是采用修改定制已有开源软件,还是采用从头自主开发的方式实现,应如何权衡考虑?

 

侯震宇:这个还是要具体情况具体分析。要根据需求的重要性、紧迫性和特殊性以及可能适用的开源软件的成熟度、复杂度以及我们的开发人员的熟悉程度等方面综合考虑。特别是开源软件的成熟度和社区的活跃程度,如果这两项比较差的话,那我们对此开源软件仅仅会是关注。

 

这里我只谈谈我们对开源软件的态度和使用情况。一般来说,我们的工作思路是首先明确自己的需求是什么,然后再调研是否有合适的开源软件可以满足或部 分满足我们的需求。如果完全满足,我们会再看这个开源软件的成熟度和社区的活跃度,都没有问题的话我们就会直接使用。如果只是部分满足需求,我们会根据实 际情况选择引入修改代码或参考重新设计的思路,这要从此软件与需求的差距点具体来看。

 

举几个例子说明一下。比如数据交换协议,仔细分析一下我们的需求可能是什么样子。数据交换协议一般有三种类型的应用:第一,作为数据格式存储到硬 盘;第二,通信密集型服务之间的通信;第三,普遍意义上的网络数据交换,可能跨大服务平台。这三类需求其实对数据交换协议的要求是不同的。第一个应用的需 求是协议包越小越好而且尽量不要发生变化;第二个需求也是要求协议包比较小但还要考虑支持一些高并发;第三个要求足够标准化同时易读。开源Google的 ProtoBuf被很多人使用,但在第三个需求上就不是很适用,因为它不支持协议的自解析,这样我们可能会针对第三类需求自己开发一套协议。再比如从编程 框架来说,Boost很好很强大。但它支持的功能过于复杂,掌握起来不容易(这个掌握是要求出现任何问题都能很快定位并解决,同时有需求还可能进一步升级 开发)。我们会考虑参照它的一些思路做一个简化版的框架出来。再比如Hadoop,这是个超级大规模的开源项目,我们在大量使用,但它的部分功能已经不满 足我们的需求,这时我们必须对其进行部分改造,用C改写了大部分的Java代码以提升性能。

 
 

邝宇恒:在一个Web2.0应用中,希望能够支持对用户产生的所有内容的实时搜索,在基础架构上应如何支持?

 

侯震宇:如何支持Web2.0应用中的实时搜索,这是个大问题,很难简单说清楚。我们还是先把问题分解。从服务提供商来看分为Web2.0服务站内 搜索和专业的搜索引擎,从技术角度来看又可以分为强调实效性的搜索技术和Web2.0内容组织技术。我们先分别谈谈这些问题,然后再综合考虑看看是否可以 提供一个基础平台来简化这些服务的搭建。

 

Web2.0网站重在用户交互,其外在表现形式比传统的信息类网站要复杂得多,主要内容包括用户提交的数据和用户之间的关系。如果只分析用户提交的 原始信息数据,就退化成一个传统搜索引擎的问题,但由于数据类型太多而需要操作的技巧也很多。对于搜索引擎提供商来说,需要解决信息源的发现问题(可以通 过配一些最重要的种子站点简单解决)、页面解析问题(大部分Web2.0网站特效很炫,但对搜索引擎不友好)、页面质量判断问题(大部分Web2.0页面 的价值相对于传统信息页面如新闻页面来说,价值都不高)、索引及排序问题(哪些内容进入索引、哪些指标影响排序,这与传统的文本检索有差别)、时效性问题 (涉及到Spider的及时抓取和快速入库),这些都是经典的搜索引擎需要处理的问题。尽管Web2.0由于页面元素和页面组织形式与传统网页差别很大, 带来非常多的技术难点,但仍可以通过经典的搜索技术解决。

 

以上是从搜索引擎角度来看的,如果是Web2.0网站自身提供搜索的话,则涉及的技术要简单很多,但这两者都涉及到Web2.0内容的组织问题。 Web2.0网站除去用户提交信息外,最重要的数据是用户与用户之间的关系,如何组织这部分数据是Web2.0网站后端设计的一大难点。提供对用户关系以 及用户关系的衍生物的搜索,这不是传统搜索引擎技术所能解决的问题。这其实不能称为搜索(Search),而是对内部数据组织的一种查询(Query)服 务。比较经典的架构设计是将Web2.0网站的数据分成两大类:第一,用户提交的原始数据,这可能是帖子内容、一幅图片、一个评价等,这部分数据总量很大 但数据变化不大;第二,数据之间、用户之间的关系数据,这部分数据变化相对频繁且数据总量不算大。对于第一种数据,我们可以设计一个简单的存储系统,支持 相对弱化的Schema,存储在便宜的介质上(如硬盘);对于第二种,由于变化频繁而且查询量大,可以存储在访问高效的介质上(如内存或SSD),而这部 分数据的操作相对复杂,可以直接使用数据库如MySQL。这两种存储系统能够满足大部分Web2.0服务的要求了,再提供一套经典的内容检索系统对原始数 据进行索引并对外提供服务,带有实时搜索的Web2.0服务就基本成型了。

 

上面一直没有谈的一个问题是隐私问题,在网站内部设计就是用户访问权限问题。这不仅是个复杂的技术问题,同样也涉及法律问题。一个只对登录用户开放 访问权限的用户,搜索引擎提供商是无法收录其内容从而提供搜索服务的。对于Web2.0网站内部,判断哪些内容可以对浏览者开放也是比较困难的,特别是有 非常复杂的好友系统存在的情况下。不过只要对用户数据进行合理组织还是可以做到的,当然要对业务逻辑的复杂与服务性能做权衡。

 
 

邝宇恒:SSD的特性与传统硬盘差别很大,它的广泛应用,会对存储系统设计带来什么影响?

 

侯震宇:这个答案是肯定的。软件是跑在硬件上的,任何一次硬件的创新应用都会带来一次软件设计上的革命性升级。对存储系统来讲,性能上最重要的指标 是IOPS和吞吐。而SSD在随机查询上的延时与硬盘相比是非常低的,这对于提供高并发的在线类服务是非常有价值的,也会使存储服务考虑的问题发生变化。 举两个最简单的例子。比如上文提到的使用MySQL,很多应用因为响应效率的问题而进行的分库分表工作,在引入SSD之后又变回了一个简单的单机问题。比 如在Cache方面,由于内存容量的问题不得不考虑多机,而SSD在很多场合下是可以为Cache服务提供存储的,这也回到了一个单机问题。单机比多机和 分布式系统要简单很多。

 

存储系统需要考虑两个层面的问题:是单机或者单存储介质的问题,还是多机和分布式的问题。就存储问题本身来说,可以看作是个单机问题。硬盘读写时间 由寻道时间和吞吐来决定,在小数据量的情况下寻道时间占读写时间的大部分。以往我们在硬盘上做存储总是要考虑硬盘顺序读写以发挥硬盘的特性,这是由硬盘的 特性决定的。比如对写操作我们会考虑将多次随机写转变为批量的顺序写以提高系统的吞吐能力,对于读操作我们会尽可能地将一些数据按照其访问模式组织数据把 可能的多次随机读转化成一次顺序读。对于SSD来说,我们同样要根据其硬件特性来设计我们的存储系统。SSD随机读能力超强,写也不错,但擦除性能很差。 这就要求我们在写的时候要尽可能避免对块的擦除,将多次修改直接写盘然后Merge成对一个块的擦除,这样可以大大提升SSD的写性能。

 

SSD最大的价值是弥补了内存和硬盘两个介质之间在容量、价格、响应延时等方面巨大的鸿沟,把SSD作为一个大容量的内存使用或者作为IOPS很高 的硬盘使用在某些场合下都是可以的。Jim Gray的名言 “Tape is Dead, Disk is Tape, Flash is Disk, Ram Locality is King”是对不同存储介 质的发展的一个精辟的论断。当然即便SSD大规模使用,硬盘也不会消亡。硬盘在顺序访问大规模数据上是有优势的,比如MapReduce类应用。上面举的 例子是SSD全面替换硬盘,而在实际工作中内存、SSD、硬盘这几种物理存储介质一般都是混合应用的。这需要我们根据应用的实际需求,来选择使用不同的存 储介质。通过对需求的抽象,可以按照数据的特性和访问的特性来分析存储系统对于不同硬件的需求。对于数据,需要分析数据的规模、单条数据的大小以及数据是 否可变和变化的频率。对于访问模式,需要分析是随机查询、批量查询和顺序查询。另外一个考虑的因素是价格和功耗,SSD是SAS硬盘价格的2倍、SATA 硬盘价格的20倍,但功耗要小很多。未来的存储系统必然是内存、SSD和硬盘(特别是SATA)混用,这需要我们在架构层面上给予足够的支持。

 
 

邝宇恒:你的团队会对所有代码进行代码评审吗?具体如何实施?如何评价代码评审的作用?

侯震宇:我们是做代码评审的,但不会对所有代码做评审。代码是可以分级的,一方面从代码本身的重要性来分,另一方面从代码编写者的熟练度来分。代码 评审在我们内部叫Code Review,其有两个目的。第一也是最主要的目的是检查代码的质量,第二是学习一些优秀的代码,大家关心的可能是第一点。对 入职时间不长的新人,需要监控其代码质量,纠正其在编写代码中的不良习惯,并使他们逐步融入我们统一的编程风格中。对于这种情况,我们一般有安排专人 Review新人的代码。需要指出的是,不能指望Code Review发现所有代码层面的问题,它只能解决一些表面问题,而很难发现代码逻辑上的问题。 代码逻辑上的问题需要通过后期的测试来解决。这里说的表面问题主要指缺乏注释、大量使用全局变量以及明显的一些可能引发Bug的问题(如在不知道字符串长 度的情况下使用Copy等),这其中包括程序员编码的基本素质和编程风格两个因素。编码的素质可以通过训练和逐步积累提高,但编程风格不容易改变,只能进 行约束。

 

所以说Code Review只是发现问题的一种手段,但不是解决问题的方法。提高代码质量我觉得分为三个层次:第一,通过框架约束;第二,工具检查;第三,Code Review检查错误。我们逐个层面来看:

 

编程框架的约束。减少程序员代码中的Bug的最好方法,就是少写代码。我们会有专人编写适合绝大多数业务的编程框架,将我们的程序员从编写没有营 养、易出错的代码工作中解放出来。程序员只需要写一些配置或描述,就可以由框架生成可运行的代码框架。这既提高了程序员的工作效率,使程序员关注在业务逻 辑实现上,也由于框架的约束使程序形成了统一的风格和代码结构。同时由于是自动生成的框架代码,这部分经过严格的测试,可以确保是高质量的代码,大大降低 Bug数。

 

编程规范的工具检查。肉眼Review代码的效率是很低的。结合我们自己的编程规范编写的工具,可以像编译检查一样检查出大批不符合规范的代码缺 陷。这些缺陷如代码缺乏注释、参数未被使用、函数没有返回值等。代码检查工具执行后会形成报告,指出缺陷的位置和一定的统计信息,这对于程序员提高自己的 代码水平是很有帮助的。将工具检查结果与代码准入的流程相结合,可以大批过滤掉提交代码的低水平缺陷或Bug。

 

最后才是Code Review,再往后就到了测试阶段了。

 

总之,代码评审对于提高代码质量是很有帮助的,但只做代码评审是不够的或者说意义不大。如何最大限度地提高代码质量减少缺陷,是每个工程师和架构师都需要考虑的问题,涉及诸多方面,这都需要我们去关注。

架构师接龙:盛大许式伟VS. 金山张宴

主持人:冯大辉,现任丁香园 (http://www.dxy.cn)网站CTO。曾历任支付宝架构师、数据库团队负责人等职。

 

许式伟:作为系统架构师,您一般会从哪些方面来保证网站的高可用性(降低故障时间)?

 

张宴:很多因素都会导致网站发生故障,从而影响网站的高可用性,比如服务器硬件故障、软件系统故障、IDC机房故障、程序上线前测试未发现的Bug、遭受分布式攻击、突发访问人数剧增等。

一套良好的网站系统架构,应该尽可能地避免只有一台服务器、一个数据库、一套软件节点等单点故障的存在。单点故障一旦发生,将直接导致网站服务不可 用,恢复正常服务所需的时间也比较长,甚至还可能无法恢复。负载均衡集群、双节点热备、分布式处理等都可以用来解决单点故障,比如提供相同业务的Web服 务器、MySQL数据库从库,都可以构建负载均衡集群。一旦集群中的一台服务器、一个服务出现故障,自动实时摘除,对用户来说是不可感知的,不会影响到整 个网站的访问,可以为运维工程师留下足够的时间去排查和解决故障。

对于重要的MySQL数据库主库,我们习惯于从硬件层和软件层来实现热备,避免单点。越 是复杂的设备,发生故障的概率越大。在磁盘没有损坏的情况下,应用程序导致服务器宕机的概率,远高于简单的磁盘阵列宕机的概率。所以,从硬件层解决的话, 可以在两台服务器上安装相同的数据库版本、进行相同的配置,用SAS或SCSI线连接一台磁盘阵列,将数据库数据文件存放到盘阵上。正常情况下用服务器A 挂载盘阵分区,启动MySQL,绑定虚拟IP;如果服务器A宕机,则用服务器B挂载盘阵分区,启动MySQL,接管虚拟IP。从软件层解决的话,则可以借 助DRBD等软件做镜像。

IDC机房发生故障的概率较小,但如果发生的话,影响面也是最大的。如果所有服务器都托管在一个IDC机房,一旦该机房遭遇长时间流量攻击、断电、 断网、地方政策性封网等,通常只能联系IDC去处理,除此之外束手无策,解决时间也比较长。如果成本允许,将网站服务器分布在两个以上的IDC机房,当某 个IDC发生故障时,可以临时切换DNS域名解析来优先恢复服务。

虽然程序代码上线前,经过了测试人员的严格测试,但测试环境和生产环境毕竟有差异,所以一些会急剧影响性能、正常服务的Bug往往在程序上线之后, 才会被发现,这就要求我们在发现Bug后,能够迅速回滚到上一正常版本。我们在SVN的基础上,开发了Web代码发布系统,会将每个发布版本之间的文件变 更记录下来,一键实现程序代码在多台Web服务器上的发布和回滚。

遭遇DDOS分布式拒绝服务攻击,使用防火墙来对付半连接、假IP,还算比较容易。而那种专挑复杂动态应用程序URL进行的分布式CC攻击,来源为 真实IP、真实HTTP请求,具有模拟正规浏览器User-Agent、单个IP的每秒请求数不高、有成千上万个攻击源等特征,很难与正常访问区分开,比 较难对付。但是,正常通过浏览器访问一个URL,会加载该URL中引入的JavaScript脚本、CSS样式、图片等文件。遇到CC攻击,需要及时分析 日志,找出访问量异常上涨的URL,然后用事先写好的shell脚本找出哪些IP的请求只访问了该URL,而不加载该URL引入的文件,对这些IP进行自 动封锁。

系统架构设计时,需要事先考虑到高于目前访问量多少倍的突发访问。对于网游站点来说,访问量受广告集中时间段投放、线上活动的影响较大,带宽峰值时 间不固定,对于静态内容,可以使用商业CDN,按实际使用量计费。对于动态内容,如果遇到突发访问人数剧增,超过现有服务器处理能力,最简单的临时处理办 法就是增加服务器。上架新服务器需要时间,但是,同一个IDC机房内,可以借助其他业务的服务器,在不同端口开启一组新进程,加入到原有负载均衡池中。另 外,可以临时关闭一些Web中的次要功能,来减少服务器消耗。

 
 

许式伟:您在任务切分上,有什么经验分享?您通过哪些手段保证任务的独立性?

 

张宴:相信很多人都遇到过这种情况:在一个老项目上修改、增加一些新功能所花费的时间,不比重新来做一个包含所 有功能的新项目时间用得少。一个需要长期维护的项目,不可避免地会面临老员工的离职、新员工的接手,很多时候,项目代码的可维护性将决定一个项目的生存周 期。让一个新员工在规定开发时间的压力下,去面对一个文档不够详细、陌生的、功能复杂的庞大项目,短时间弄明白所有功能逻辑不是一件容易的事。所以,任务 需要切分,将一个大的任务切分成一个个小模块之后,各模块之间可以做到代码独立,互不影响,可维护性也大大增强。

关于任务切分,我以本人今年负责的两个重要项目架构设计为例来介绍一下。在第一个项目:金山游戏官网的《用户行为分析系统》中,由于数据挖掘计算需 要消耗较高的内存、CPU资源,一台服务器的处理能力不够,而商业的分布式数据仓库价格又太贵,所以,只有从程序应用中下手,进行任务切分。我们先按需要 挖掘的数据指标,将整个数据挖掘任务切分成多个数据挖掘插件,每个插件可以在不同的服务器上运行,多个插件可以同时在多台服务器上。多个数据挖掘插件之 间,如果用到相同的某项数据,那么,就将该项数据以冗余方式,复制几份提供给需要的插件,从而实现插件之间无交互、无关联,保证了超大数据量下插件的运算 速度。

在第二个项目:金山游戏新版运营管理系统中,则将整个任务切分成了PHP Web管理界面、PHP Web API功能接口、C/C++中间件引擎三部分。这是一种分层结构切分,最上层的“PHP Web管理界面”调用“PHP Web API功能接口”,“PHP Web API功能接口”调用运行在游戏服务器端的“C/C++中间件引擎”,“C/C++中间件引擎”与“游戏服务器端进程”通过TCP、UDP二进制协议、信 号、命令行等多种方式通信。四者之间相对独立,代码无关联,通过一层层API接口实现交互。“PHP Web管理界面”负责通用界面实现。“PHP Web API功能接口”内部,又按接入的游戏模块、子功能模块进行了更细的切分,各功能模块之间通过内部API交互。“C/C++中间件引擎”大而全,不处理具 体指令,但兼容TCP、UDP、HTTP、HTTPS/SSL、信号、命令行等大多数通信方式,负责和各种类型的游戏服务端交互。这是一套完全由API接 口驱动的系统架构,一款新游戏接入运营管理系统时,只需在“PHP Web API功能接口”中增加一个模块;一个游戏新管理功能的增加,只需要在“PHP Web API功能接口”中增加一个子模块。通过任务切分,将复杂功能简单化,也将原来接入一款新游戏所需要的几个月时间,缩短为1~2周。

 
 

许式伟:您通过哪些手段,来保障产品的质量?您倾向于多久更新一次您的网站?

 

张宴:Web产品质量主要体现在架构、功能、性能、安全、代码唯一性、兼容性等方面。

架构方面,我会先设计一套架构方案,然后让和项目相关的人员、专家组成员参与进来,一起探讨和论证架构的利弊,提出改进意见,保证架构的可行性。所有重要项目的技术方案需要经过专家组的评估。

功能、性能方面,则会由专门的测试人员进行功能测试、压力测试、安全扫描,测试环境分为线下测试环境、线上准测试环境。

在代码唯一性方面,我们开发了一个Web配置信息管理平台及相关PHP扩展,提供给系统工程师,用于配置信息的统一管理。在新项目中,PHP程序配 置文件中将不再出现MySQL、Memcached等各类IP和端口信息,统一用Web配置信息管理平台给出的变量代替。从“开发环境→线下测试环境→线 上测试环境→线上正式环境”,连接的数据库各不相同,导致PHP开发工程师经常搞混淆或忘了修改,通过Web配置信息管理平台,使得PHP代码中的配置文 件,在四个环境中无须作任何修改,保证了代码的一致性,降低了出错率,从而确保了产品质量。

在兼容性方面,我们从操作系统到PHP、MySQL版本,都保持开发环境、测试环境、线上环境的统一,所有的Web服务运行在CentOS Linux系统上。由于大多数PHP程序员习惯于在Windows上编写代码,而我们的程序中调用的一些接口、PHP扩展,只能在Linux下运行。为 此,我们开发了一个小工具,可以将多名程序员在各自本机Windows上搭建的nginx虚拟主机、编写的程序文件,映射到一台Linux服务器,用 Linux上的php-cgi执行Windows上的PHP代码。这样,PHP程序员修改完本机代码,保存一下,即可调试,多人之间互不影响。自己调试通 过后,可以在Windows直接点击鼠标右键,将修改的代码提交到SVN版本库。

Web 2.0时代,讲究网站更新的实时性,动态网站不用说,静态网站的内容发布也要保证实时。我们开发了一款名为Sersync的开源软件 (http://code.google.com/p/sersync/),使用Linux 2.6内核的inotify监控Linux文件系统事件,被监听目录下如果有文件发生修改,Sersync将通过内核自动捕获到事件,并将该文件利用 rsync同步到CDN源站服务器。Sersync仅仅同步发生增、删、改事件的单个文件或目录,不像rsync镜像同步那样需要比对双方服务器整个目录 下数千万的文件,并且支持多线程同步,因此效率非常高。金山游戏官网的CMS内容发布系统,无论网站编辑通过Web还是FTP上传图片、视频、附件,还是 系统工程师直接去CMS发布服务器上增加、修改、删除文件,干完这些事情后不用做任何处理,Sersync 会自动将发生增、删、改事件的文件同步到CDN源站服务器,并可以在文件同步完成后,自动调用CDN缓存刷新接口,主动刷新发生修改、删除的文件的访问 URL。

 
 

许式伟:您在面试时,通常关注应聘者的哪些方面?哪些问题经常会问呢?

 

张宴:第一,需要具备岗位要求的基础技能知识,这方面我不再详述。

第二,注重项目经验与积累,不看重学历与工作年限。做一个项目,犹如打一场战役,身经百战,积累下来的成功经验可以让工作更得心应手,失败经验可以避免走很多弯路。

第三,能够在1~2个以上技术领域精通。所谓术业有专攻,能够在某几项技术领域做到精通的人,相信对于新的技术领域或者从未有过相关经验的新项目,也能够轻松胜任,做到尽善尽美。

第四,关注应聘者的知识广度。如今的项目,已经告别个人英雄时代,讲究团队的协作。知识面越广,尽管在非专攻领域的深度可能不够,但是,知己知彼,可以站在一个更高的角度上看问题,这对于团队协作开发、项目融合的益处是显而易见的。

第五,具备良好的领悟能力、思考能力、设计能力、创新能力。基础技能知识不够可以学习,经验不足可以积累,技术不精通可以钻研,知识面不广可以开 拓,但要培养这四项能力,是一件非常困难的事。要打造一支优秀的团队,这四项能力不可缺少,它们的重要度甚至超过以上的四方面要求。

我不会经常去问固定的问题,但所问的问题,几乎都跟以上的这些方面相关。

 
 

许式伟:您曾尝试开放自己的程序代码吗?您对中国国内开源社区的现状有何看法?

 

张宴:是否开源自己的程序代码,跟所在公司或部门的性质有着密切的关系。如果是在研发驱动型企业或部门,程序代 码是公司生存的命脉,需要与竞争对手拼技术和保持技术领先的优势,因此,很难支持开源事业。反之,如果是在运营驱动型企业或部门,技术是用来提高运营质 量、运营水平的工具之一。将纯粹的技术代码或产品,从公司的业务产品中提取出来,进行开
源,可以按照开源产品的要求,提高公司内部技术产品的规范化、标准化,还可以引用更广大用户的使用、反馈和意见,解决未发现的潜在Bug,改进代码质量, 提升技术水平。对于提高运营质量、运营水平来说,益处多多。我也尝试开源自己的一些代码,例如简单消息队列服务 HTTPSQS(http://code.google.com/p/httpsqs/)、MySQL HTTP/REST客户端MySQL-UDF-HTTP(http://code.google.com/p/mysql-udf-http/),同时, 也鼓励团队成员尝试开源,例如刚才提到的自动同步软件Sersync。

国内的开源社区在不断壮大,很多知名互联网公司都开源了自己的一些产品,但大多数还只停留在开源产品的使用、技术交流、汉化层面,真正参与到开源产品编码中的人还是较少,很多开源产品最终还是由原作者或原公司团队维护。国内开源社区的道路仍然漫长。

跨域资源共享的10种方式

在客户端编程语言中,如javascript和ActionScript,同源策略是一个很重要的安全理念,它在保证数据的安全性方面有着重要的意义。同 源策略规定跨域之间的脚本是隔离的,一个域的脚本不能访问和操作另外一个域的绝大部分属性和方法。那么什么叫相同域,什么叫不同的域呢?

 
 

同源策略

在客户端编程语言中,如javascript和 ActionScript,同源策略是一个很重要的安全理念,它在保证数据的安全性方面有着重要的意义。同源策略规定跨域之间的脚本是隔离的,一个域的脚 本不能访问和操作另外一个域的绝大部分属性和方法。那么什么叫相同域,什么叫不同的域呢?当两个域具有相同的协议(如http), 相同的端口(如80),相同的host(如www.example.org),那么我们就可以认为它们是相同的域。比如 http://www.example.org/index.html和http://www.example.org/sub/index.html是 同域,而http://www.example.org, https://www.example.org, http://www.example.org:8080, http://sub.example.org中的任何两个都将构成跨域。同源策略还应该对一些特殊情况做处理,比如限制file协议下脚本的访问权限。 本地的html文件在浏览器中是通过file协议打开的,如果脚本能通过file协议访问到硬盘上其它任意文件,就会出现安全隐患,目前IE8还有这样的隐患。

受到同源策略的影响,跨域资源共享就会受到制约。但是随着人们的实践和浏览器的进步,目前在跨域请求的技巧上,有很多宝贵经验的沉淀和积累。这里我把跨域资源共享分成两种,一种是单向的数据请求,还有一种是双向的消息通信。接下来我将罗列出常见的一些跨域方式,以下跨域实例的源代码可以从这里获得

 
 

单向跨域

JSONP

JSONP (JSON with Padding)是一个简单高效的跨域方式,HTML中的script标签可以加载并执行其他域的JavaScript,于是我们可以通过script标 记来动态加载其他域的资源。例如我要从域A的页面pageA加载域B的数据,那么在域B的页面pageB中我以JavaScript的形式声明pageA 需要的数据,然后在pageA中用script标签把pageB加载进来,那么pageB中的脚本就会得以执行。JSONP在此基础上加入了回调函 数,pageB加载完之后会执行pageA中定义的函数,所需要的数据会以参数的形式传递给该函数。JSONP易于实现,但是也会存在一些安全隐患,如果 第三方的脚本随意地执行,那么它就可以篡改页面内容,截获敏感数据。但是在受信任的双方传递数据,JSONP是非常合适的选择。

 

flash URLLoader

flash有自己的一套安全策略,服务器可以通过crossdomain.xml文件来声明能被哪些域的SWF文件访问,SWF也可以通过API来确定自身能被哪些域的SWF加载。当跨域访问资源时,例如从域www.a.com请求域www.b.com上的数据,我们可以借助flash来 发送HTTP请求。首先,修改域www.b.com上的crossdomain.xml(一般存放在根目录,如果没有需要手动创建) ,把www.a.com加入到白名单。其次,通过Flash URLLoader发送HTTP请求,最后,通过Flash API把响应结果传递给JavaScript。Flash URLLoader是一种很普遍的跨域解决方案,不过需要支持iOS的话,这个方案就无能为力了。

 

Access Control

Access Control是比较超越的跨域方式,目前只在很少的浏览器中得以支持,这些浏览器可以发送一个跨域的HTTP请求(Firefox, Google Chrome等通过XMLHTTPRequest实现,IE8下通过XDomainRequest实现),请求的响应必须包含一个Access- Control-Allow-Origin的HTTP响应头,该响应头声明了请求域的可访问权限。例如www.a.com对www.b.com下的 asset.php发送了一个跨域的HTTP请求,那么asset.php必须加入如下的响应头:

window.name

window 对象的name属性是一个很特别的属性,当该window的location变化,然后重新加载,它的name属性可以依然保持不变。那么我们可以在页面 A中用iframe加载其他域的页面B,而页面B中用JavaScript把需要传递的数据赋值给window.name,iframe加载完成之后,页 面A修改iframe的地址,将其变成同域的一个地址,然后就可以读出window.name的值了。这个方式非常适合单向的数据请求,而且协议简单、安 全。不会像JSONP那样不做限制地执行外部脚本。

 

server proxy

在数据提供方没有提供对JSONP协议或者 window.name协议的支持,也没有对其它域开放访问权限时,我们可以通过server proxy的方式来抓取数据。例如当www.a.com域下的页面需要请求www.b.com下的资源文件asset.txt时,直接发送一个指向 www.b.com/asset.txt的Ajax请求肯定是会被浏览器阻止。这时,我们在www.a.com下配一个代理,然后把Ajax请求绑定到这个代理路径下,例如www.a.com/proxy/, 然后这个代理发送HTTP请求访问www.b.com下的asset.txt,跨域的HTTP请求是在服务器端进行的,客户端并没有产生跨域的Ajax请求。这个跨域方式不需要和目标资源签订协议,带有侵略性,另外需要注意的是实践中应该对这个代理实施一定程度的保护,比如限制他人使用或者使用频率。

 
 

双向跨域

document.domain

通 过修改document的domain属性,我们可以在域和子域或者不同的子域之间通信。同域策略认为域和子域隶属于不同的域,比如www.a.com和 sub.a.com是不同的域,这时,我们无法在www.a.com下的页面中调用sub.a.com中定义的JavaScript方法。但是当我们把它 们document的domain属性都修改为a.com,浏览器就会认为它们处于同一个域下,那么我们就可以互相调用对方的method来通信了。

 

FIM – Fragment Identitier Messaging

不 同的域之间,JavaScript只能做很有限的访问和操作,其实我们利用这些有限的访问权限就可以达到跨域通信的目的了。FIM (Fragment Identitier Messaging)就是在这个大前提下被发明的。父窗口可以对iframe进行URL读写,iframe也可以读写父窗口的URL,URL有一部分被称 为frag,就是#号及其后面的字符,它一般用于浏览器锚点定位,Server端并不关心这部分,应该说HTTP请求过程中不会携带frag,所以这部分 的修改不会产生HTTP请求,但是会产生浏览器历史记录。FIM的原理就是改变URL的frag部分来进行双向通信。每个window通过改变其他 window的location来发送消息,并通过监听自己的URL的变化来接收消息。这个方式的通信会造成一些不必要的浏览器历史记录,而且有些浏览器 不支持onhashchange事件,需要轮询来获知URL的改变,最后,URL在浏览器下有长度限制,这个制约了每次传送的数据量。

 

Flash LocalConnection

页 面上的双向通信也可以通过Flash来解决,Flash API中有LocalConnection这个类,该类允许两个SWF之间通过进程通信,这时SWF可以播放在独立的Flash Player或者AIR中,也可以嵌在HTML页面或者是PDF中。遵循这个通信原则,我们可以在不同域的HTML页面各自嵌套一个SWF来达到相互传递 数据的目的了。SWF通过LocalConnection交换数据是很快的,但是每次的数据量有40kb的大小限制。用这种方式来跨域通信过于复杂,而且 需要了2个SWF文件,实用性不强。

 

window.postMessage

window.postMessage是HTML5定义的一个很新的方法,这个方法可以很方便地跨window通信。由于它是一个很新的方法,所以在很旧和比较旧的浏览器中都无法使用。

 

Cross Frame

Cross Frame是FIM的一个变种,它借助了一个空白的iframe,不会产生多余的浏览器历史记录,也不需要轮询URL的改变,在可用性和性能上都做了很大 的改观。它的基本原理大致是这样的,假设在域www.a.com上有页面A.html和一个空白代理页面proxyA.html, 另一个域www.b.com上有个页面B.html和一个空白代理页面proxyB.html,A.html需要向B.html中发送消息时,页面会创建 一个隐藏的iframe, iframe的src指向proxyB.html并把message作为URL frag,由于B.html和proxyB.html是同域,所以在iframe加载完成之后,B.html可以获得iframe的URL,然后解析出 message,并移除该iframe。当B.html需要向A.html发送消息时,原理一样。Cross Frame是很好的双向通信方式,而且安全高效,但是它在Opera中无法使用,不过在Opera下面我们可以使用更简单的 window.postMessage来代替。

 
 

总结

跨域的方法很多,不同的应用场景我们都可以找到一个最合适的解决方 案。比如单向的数据请求,我们应该优先选择JSONP或者window.name,双向通信我们采取Cross Frame,在未与数据提供方没有达成通信协议的情况下我们也可以用server proxy的方式来抓取数据。

人人网使用的开源软件列表

MySQL
关系型数据库存储系统,我们的DBA团队很强大,每人管理上百台MySQL服务器,其他就不多说了,网上资料太多了

 

Tokyo Cabinet
一个key-value的存储引擎,日本人开发,国内很多公司也开始使用,我们内部很多地方也用它来代替MySQL来做存储,比如我们的搜索结果页的用户资料,就是用它来做一层MySQL外的冗余存储,目的是加快搜索结果页的显示。在key-value并需要持久存储的场景下,用它比MySQL更有效,Cabinet本身只是一个存储引擎,没有网络处理能力,你可以用它作为自己的某个系统的下层存储引擎,更好的是搭配Tokyo Tyrant使用。

 

Tokyo Tyrant
一个支持Memcached传输协议的网络接口,由Tokyo Cabinet的作者开发,目的是为Tokyo Cabinet提供网络接入能力,即Tokyo Tyrant处理网络连接,协议解析,然后调用Tokyo Cabinet的API来完成持久化存储。

 

ICE
一个跨语言的网络通讯框架,框架本身提供了强大的通讯能力,管理工具,负载均衡方案,其跨语言能力也是一个很大的亮点,基于这个框架之上,我们选用合适的 语言来提供合适的服务,比如我们使用C++来开发Cache服务,使用Java来开发一些逻辑服务。框架本身可以很重,也可以很轻,具体要看你怎么用。

 

Memcached
一个纯内存的key-value的cache系统,高效、稳定,使用广泛,如果你连它都没听说过就太out啦,memcached本身不具备分布式能力, 需要依靠Client来实现分布,这里强调一点的是,你应该选择一致性Hash来做key的分布。各种语言的client都有,我们使用 spymemcached作为java的Client,spymemcached是一个异步的NIO的memcached client,对网络IO的处理非常的精巧,也更加高效,同时因为提供异步操作方式,可以让你对Memcached的操作有更好的控制能 力,Memcached到1.4.0版本之后,开始支持binary protocol,spymemcached对其也支持的比较好,使用binary protocol可以提高对协议的解析效率和网络IO的读写效率。
上面说到我们使用ICE自己开发了Cache服务,为什么我们还要用Memcached呢?主要在对Cache的操作粒度不一样,Memcached对 Cache对象以binary byte作为一个整体来操作,需要频繁的序列化和反序列化,我们使用ICE提供的Cache服务,可以以Cache对象的一个或者多个字段来操作,比如一 个用户对象,我们可以只更新它的姓名,而Memcached

 

Nginx
高效、稳定的Web Server,我们利用其代理能力,做跨IDC的请求代理,同时也将其和我们的Resin(Java Web 容器)搭配,放在Resin的前面来解决Resin的对网络连接处理能力弱的问题,在一些小地方也用它来做7层的负载均衡

 

Resin
一个Java Web Server,比Tomcat更高效,是我们主要的Java Web容器

 

Squid
代理服务器,我们用他来做图片文件的反向代理缓存

 

LVS
能提供4层的负载均衡,高效、高可用,高并发。我们用他替代了很多硬件的负载均衡设备

 

Struts
Java web框架,不过这个已经是历史了,我们开发了一套自己的Web框架替代了它,未来我们也会把我们的内部的这套Web框架开源出来

 

Lucence
基于Java的搜索引擎框架,用它我们构建了一个搜索集群来提供搜人的服务

 

Netty
一个Java的网络框架,和apache的mina类似,但比mina更高效,我们用来做一些小的服务

 

Ganglia
一个监控系统,帮组我们了解我们每台Server的资源利用情况

 
 

还有些小东西就不列出来了,最后要说的一点就是,对这些开源软件或者系统,我们都非常的了解,或者说知根知底,从API到内部实现原理,甚至到一些源码的细节。