Leveldb是一个google实现的非常高效的kv数据库,目前的版本1.2能够支持billion级别的数据量了。 在这个数量级别下还有着非常高的性能,主要归功于它的良好的设计。特别是LSM算法。

    那么数据库最怕的的随机IO他是如何解决的呢?

    先说随机写,它的写都是先记录到日志文件去的,在日志文件满之前只是简单的更新memtable,那么就把随机写转化成了顺序写。在日志满了后,把日志里面的数据排序写成sst表同时和之前的sst进行合并,这个动作也是顺序读和写。大家都知道传统磁盘raid的顺序读写吞吐量是很大的,100M左右是没有问题。在写日志文件的时候,用到是buffer IO,也就是说如果操作系统有足够的内存,这个读写全部由操作系统缓冲,效果非常好。即使是sync写模式,也是以数据累计到4K为一个单位写的,所以效率高。

    那么随机读呢?这个它解决不了。但是ssd盘最擅长随机读了。这个硬件很自然的解决了这个问题。

    所以leveldb的绝配是ssd盘的raid.

    leveldb标准版本编译见这里,由于标准版本用到了c++ 0x的特性,在RHEL平台下没得到支持,所以为了移植性, basho见这里为它做了标准c++版本的port, 见目录c_src/leveldb.

    我们的测试采用的就是这个版本, 我们分别测试了1000万, 1亿,10亿数据量下的leveldb表现,发现随着数据集的变化性能变化不大。

     由于leveldb默认的sst文件是2M, 在数据集达到100G的时候要占用几万个文件,我修改了:

version_set.cc:23 static const int kTargetFileSize = 32 * 1048576; 

    让默认的文件变成32M,减少目录的压力。

    我的测试环境是:

$uname -r 2.6.18-164.el5 #RHEL 5U4 # 10* SAS 300G raid卡,fusionIO 320G, Flashcache,内存96G,  24 * Intel(R) Xeon(R) CPU 

    top说:

21782 root      18   0 1273m 1.1g 2012 R 85.3  1.2   1152:34 db_bench 

    iostat说:

$iostat -dx 5 ... sdb1              0.40     0.00  3.40  0.00    30.40     0.00     8.94     0.02    4.65   4.65   1.58 fioa              0.00     0.00 2074.80  3.80 16598.40    30.40     8.00     0.00    0.13   0.00   0.00 dm-0              0.00     0.00 1600.00  0.00 16630.40     0.00    10.39     0.25    0.15   0.15  24.76 ... 

    该测试中请注意snappy压缩没有打开,如果有压缩性能还会高很多,因为IO少了一半。

     write_buffer_size=$((256*1024*1024)),log大小设成256M,这样减少切换日志的开销和减少数据合并的频率。

    同时应该注意到db_bench是单线程程序,还有一个compact线程,所以最多的时候这个程序只能跑到200%的cpu, IO util也不是很高. 换句话说如果是多线程程序的话性能还要N倍的提高。

    我们来看下实际的性能数字:

#1千万条记录 $sudo ./db_bench --num=10000000 --write_buffer_size=$((256*1024*1024)) LevelDB:    version 1.2 Date:       Fri May 27 17:14:33 2011 CPU:        24 * Intel(R) Xeon(R) CPU           X5670  @ 2.93GHz CPUCache:   12288 KB Keys:       16 bytes each Values:     100 bytes each (50 bytes after compression) Entries:    10000000 RawSize:    1106.3 MB (estimated) FileSize:   629.4 MB (estimated) write_buffer_size=268435456 WARNING: Snappy compression is not enabled ------------------------------------------------ fillseq      :       2.134 micros/op;   51.8 MB/s fillsync     :      70.722 micros/op;    1.6 MB/s (100000 ops) fillrandom   :       5.229 micros/op;   21.2 MB/s overwrite    :       5.396 micros/op;   20.5 MB/s readrandom   :      65.729 micros/op; readrandom   :      43.086 micros/op; readseq      :       0.882 micros/op;  125.4 MB/s readreverse  :       1.200 micros/op;   92.2 MB/s compact      : 24599514.008 micros/op; readrandom   :      12.663 micros/op; readseq      :       0.372 micros/op;  297.4 MB/s readreverse  :       0.559 micros/op;  198.0 MB/s fill100K     :     349.894 micros/op;  272.6 MB/s (10000 ops) crc32c       :       4.759 micros/op;  820.8 MB/s (4K per op) snappycomp   :       3.099 micros/op; (snappy failure) snappyuncomp :       2.146 micros/op; (snappy failure)  #1亿条记录 $sudo ./db_bench --num=100000000 --write_buffer_size=$((256*1024*1024)) LevelDB:    version 1.2 Date:       Fri May 27 17:39:19 2011 CPU:        24 * Intel(R) Xeon(R) CPU           X5670  @ 2.93GHz CPUCache:   12288 KB Keys:       16 bytes each Values:     100 bytes each (50 bytes after compression) Entries:    100000000 RawSize:    11062.6 MB (estimated) FileSize:   6294.3 MB (estimated) write_buffer_size=268435456 WARNING: Snappy compression is not enabled ------------------------------------------------ fillseq      :       2.140 micros/op;   51.7 MB/s fillsync     :      70.592 micros/op;    1.6 MB/s (1000000 ops) fillrandom   :       6.033 micros/op;   18.3 MB/s overwrite    :       7.653 micros/op;   14.5 MB/s readrandom   :      44.833 micros/op; readrandom   :      43.963 micros/op; readseq      :       0.561 micros/op;  197.1 MB/s readreverse  :       0.809 micros/op;  136.8 MB/s compact      : 123458261.013 micros/op; readrandom   :      14.079 micros/op; readseq      :       0.378 micros/op;  292.5 MB/s readreverse  :       0.567 micros/op;  195.2 MB/s fill100K     :    1516.707 micros/op;   62.9 MB/s (100000 ops) crc32c       :       4.726 micros/op;  826.6 MB/s (4K per op) snappycomp   :       1.907 micros/op; (snappy failure) snappyuncomp :       0.954 micros/op; (snappy failure)  #10亿条记录 $sudo ./db_bench --num=1000000000 --write_buffer_size=$((256*1024*1024)) Password: LevelDB:    version 1.2 Date:       Sun May 29 17:04:14 2011 CPU:        24 * Intel(R) Xeon(R) CPU           X5670  @ 2.93GHz CPUCache:   12288 KB Keys:       16 bytes each Values:     100 bytes each (50 bytes after compression) Entries:    1000000000 RawSize:    110626.2 MB (estimated) FileSize:   62942.5 MB (estimated) write_buffer_size=268435456 WARNING: Snappy compression is not enabled ------------------------------------------------ fillseq      :       2.126 micros/op;   52.0 MB/s fillsync     :      63.644 micros/op;    1.7 MB/s (10000000 ops) fillrandom   :      10.267 micros/op;   10.8 MB/s overwrite    :      14.339 micros/op;    7.7 MB/s ...比较慢待补充 

    总结: Leveldb是个很好的kv库,重点解决了随机IO性能不好的问题,多线程更新的性能非常好.

您可能还对下面的文章感兴趣:

posted @ 2011-06-01 22:18 小马歌 阅读(575) | 评论 (0)编辑 收藏
 

今天在51js论坛中看到一个网友发布了一个javasctipt实现的快速排序的算法,前些日子工作中也涉及到javasctipt中数据排序的应用,当时为了提高排序速度,使用的也是快速排序的算法。
但是让我感到意外的是,下面有个网友回复说,javascript中的Array本身的sort方法才是最快的,比快速排序算法都快,当时看到了很是郁闷,因为当时花了好长时间在排序算法上,居然忘记了Array本身的sort方法
不过javascript中内置的sort方法真的比快速排序算法还快吗?
哈哈,测试一下不就知道了
先说一下我测试的环境
1,我的测试环境是IE6.0和firefox2.0
2,每种算法有很多种不同的实现方法,下面测试中我选择上面网友实现的快速排序算法,只是把内嵌函数搬到了外面
3,算法执行的速度与数据的类型、大小、数据量的多少都有关系,我这里只比较 小于 999999 的整数的排序,数据量分别定为500、2000、30000

关于sort方法:sort方法是Array的一个内置的方法:javascript权威指南 中是这样定义的:

The sort( ) method sorts the elements of array in place: no copy of the array is made. If sort( ) is called with no arguments, the elements of the array are arranged in alphabetical order (more precisely, the order determined by the character encoding). To do this, elements are first converted to strings, if necessary, so that they can be compared.
If you want to sort the array elements in some other order, you must supply a comparison function that compares two values and returns a number indicating their relative order. The comparison function should take two arguments, a and b, and should return one of the following:

sort方法可以接受一个function类型的参数来自定义自己的排序逻辑,当没有提供参数的时候,默认按照字符顺序排序,所以对整数排序需要提供一个function类型的参数,本测试的调用方式如下:

array.sort(function(a,b){return a-b})

当然如果要排序的整数位数相同,不提供参数返回的结果也是一样的,测试一下就知道:


复制代码 代码如下:
<script>
alert( [3,4,5,11,1].sort())
alert([3,4,5,11,1].sort(function(a,b){return a-b}))
</script>
提示:可以先修改了再运行
得到的结果是 [1, 11, 3, 4, 5],显然不是我们要的结果
生成需要排序的数组,为了得到公正的结果我先随机生成用于排序的数组,每次比较中两种方法使用的数组都具有相同的元素,下面是生成随机数组的代码
复制代码 代码如下:
function random(m,n){
//生成一个m、n之间的整数
var i=Math.random();
return Math.round((n-m)*i+m);
}

function getRandomArr(m,n,l){
//m:生成随即整数的最小值,n:生成随即整数的最大值,l:生成的数组的长度
var resultArr=[];
for(var i=0;i<l;i++){
resultArr.push(random(m,n))
}
return resultArr;
}

快速排序算法的实现,这个算法取自我看到的51js论坛上这个网友的实现,代码如下:
复制代码 代码如下:
function doSort(a,s,e)
{
if(s<e)
{
var pos=partition(a,s,e);
doSort(a,s,pos-1);
doSort(a,pos+1,e);
}
}
function partition(a,st,en)
{
var s=st;
var e=en+1;
var temp=a[s];
while(1)
{
while(a[++s]<temp);
while(a[--e]>temp);
if(s>e)break;
var tem=a[s];
a[s]=a[e];
a[e]=tem;
}
a[st]=a[e];
a[e]=temp;
return e;
}

Array.prototype.quickSort=function(){
doSort(this,0,this.length-1);
}

检查结果是否正确使用array.join()来判断, 性能测试代码如下:
复制代码 代码如下:
function sortIntF(a,b){return a-b}
function pk(num){
//num: 用于排序的数组的元素个数
//生成用于排序的数组
var arr=getRandomArr(1,999999,num);
//当元素个数小于10000时,执行n次取平均值
var n=Math.ceil(10000/num);
//生成多个用于排序的数组的拷贝
var quickSortArrs=[];
var sortArrs=[];
for(var i=0;i<n;i++){
quickSortArrs.push(arr.slice(0));
sortArrs.push(arr.slice(0));
}
var t1=new Date();
for(var i=0;i<n;i++){
quickSortArrs[i].quickSort();
}
var t2=new Date();
for(var i=0;i<n;i++){
sortArrs[i].sort(sortIntF);
}
var t3=new Date();
alert("性能比较,对于"+num+"个元素的数组,平均每次排序花费时间如下:\n"
+"Array.prototype.sort:"+((t3-t2)/n)+"ms\n"
+"quickSort:"+((t2-t1)/n)+"ms\n"
);
alert("排序结果是否正确:"+(sortArrs[0].join()==quickSortArrs[0].join()));
}

直接调用pk函数就可以了,例如你要对300个元素的数组进行排序性能比较,调用pk(300) 就可以了

完整的测试代码如下:
 
<script>
function rand(m,n){
//生成一个m、n之间的整数
var i=Math.random();
return Math.round((n-m)*i+m);
}

function getRandomArr(m,n,l){
//m:生成随即整数的最小值,n:生成随即整数的最大值,l:生成的数组的长度
var resultArr=[];
for(var i=0;i<l;i++){
resultArr.push(rand(m,n))
}
return resultArr;
}
function partition(a,st,en)
{
var s=st;
var e=en+1;
var temp=a[s];
while(1)
{
while(a[++s]<=temp);
while(a[--e]>temp);
if(s>e)break;
var tem=a[s];
a[s]=a[e];
a[e]=tem;
}
a[st]=a[e];
a[e]=temp;
return e;
}
function doSort(a,s,e)
{
if(s<e)
{
var pos=partition(a,s,e);
doSort(a,s,pos-1);
doSort(a,pos+1,e);
}
}
Array.prototype.quickSort = function()
{
doSort(this,0,this.length-1);
}

function sortIntF(a,b){return a-b}
function pk(num){
//num: 用于排序的数组的元素个数
//生成用于排序的数组
var arr=getRandomArr(1,999999,num);
//当元素个数小于10000时,执行n次取平均值
var n=Math.ceil(10000/num);
//生成多个用于排序的数组的拷贝
var quickSortArrs=[];
var sortArrs=[];
for(var i=0;i<n;i++){
quickSortArrs.push(arr.slice(0));
sortArrs.push(arr.slice(0));
}
var t1=new Date();
for(var i=0;i<n;i++){
quickSortArrs[i].quickSort();
}
var t2=new Date();
for(var i=0;i<n;i++){
sortArrs[i].sort(sortIntF);
}
var t3=new Date();
alert("性能比较,对于"+num+"个元素的数组,平均每次排序花费时间如下:\n"
+"Array.prototype.sort:"+((t3-t2)/n)+"ms\n"
+"quickSort:"+((t2-t1)/n)+"ms\n"
);
alert("排序结果是否正确:"+(sortArrs[0].join()==quickSortArrs[0].join()));
}
pk(500);
pk(2000);
pk(30000);
</script>

  [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]
测试结果
第一次 第一次 第一次(ms)
500个元素: ie6.0: sort: 38.3 39.05 39.05
quickSort: 8.6 8.6 9.4
ff2.0: sort: 3.1 3.15 3.9
quickSort: 4.7 4.7 3.15

2000个元素: ie6.0: sort: 200 203.2 203
quickSort: 40.6 43.6 43.8
ff2.0: sort: 18.8 18.6 18.8
quickSort: 18.6 15.6 15.6

30000个元素: ie6.0: sort: 10360 9765 9203
quickSort: 843 813 891
ff2.0: sort: 422 422 406
quickSort: 328 297 407
从结果中可以看到,
在ie6.0中快速排序算法比Array对象的sort方法快多了,对于元素比较少的,快速排序的速度基本上是sort方法的5倍左右,对于30000个元素快速排序是sort方法速度的十几倍
在ff2.0中两种排序算法速度基本上差不多,快速排序算法稍微快一点,这也说明ff2.0中Array对象的sort还是比较高效的,说不定就是用的快速排序,因为它跟快速排序算法的数据很接近
说明:上面的测试只代表我本机上的测试结果,也许在你机器上结果会有很大的区别,希望大家也帮忙测试一下
详细出处参考:http://www.jb51.net/article/6136.htm

posted @ 2011-05-31 11:27 小马歌 阅读(262) | 评论 (0)编辑 收藏
 
     摘要: 作者: 杨廷勇(scyzxp at toping.net)来自: LinuxSir.Org版权:杨廷勇 Copyright © 2004、2005、2006摘要: 本文介绍使用 Linux + Postfix + Cyrus-sasl + Courier-imap + Tmail3.0 + spamassassin + Clamav + mailscanne...  阅读全文
posted @ 2011-05-27 11:51 小马歌 阅读(617) | 评论 (0)编辑 收藏
 
在我们日常运维工作中,经常会碰到负载均衡器后端应用代码更新、临时剔除后端服务器、排查一主机应用故障等,往往我们会选择比较粗鲁的做法,直接停止或重启应用服务,让负载均衡器探测服务不可用将其剔除。这样带来的坏处是用户与服务器已经建立的连接会被中止,开发人员无法对已经停止服务的主机进行调试。现介绍一种较为温柔的做法,即通过禁用/启用成员的方式来达到目的。本文针对目前最为流行的负载均衡器逐一进行介绍。包括LVS、Haproxy、F5在命令行模式下的实现(方便与其它管理平台对接,实现自动化维护)。当然,Haproxy与F5都提供了人性化管理界面,不过只依赖手工来进行操作。

一、LVS负载均衡器
原理
使用LVS自带的管理工具来实现。

环境说明
Disable VIP:192.168.100.11:80
Disable REAL SERVER:192.168.100.78

实施步骤
1、初始状态
[devuser@lvsserver ~]# ipvsadm -Ln

IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.100.11:80 rr persistent 60
  -> 192.168.100.74:80            Route   3      462        464        
  -> 192.168.100.75:80            Route   3      420        440       
  -> 192.168.100.76:80            Route   3      431        400
  -> 192.168.100.77:80            Route   3      430        432
  -> 192.168.100.78:80            Route   3      435        438

2、禁用成员
[devuser@lvsserver ~]# ipvsadm -d -t 192.168.100.11:80 -r 192.168.100.78

3、当前状态
[devuser@lvsserver ~]# ipvsadm -Ln

IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.100.11:80 rr persistent 60
  -> 192.168.100.74:80            Route   3      462        464        
  -> 192.168.100.75:80            Route   3      420        440       
  -> 192.168.100.76:80            Route   3      431        400
  -> 192.168.100.77:80            Route   3      430        432

4、启用成员
[devuser@lvsserver ~]#ipvsadm -a -t 192.168.100.11:80 -r 192.168.100.78

5、当前状态
[devuser@lvsserver ~]# ipvsadm -Ln

IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.100.11:80 rr persistent 60
  -> 192.168.100.74:80            Route   3      462        464        
  -> 192.168.100.75:80            Route   3      420        440       
  -> 192.168.100.76:80            Route   3      431        400
  -> 192.168.100.77:80            Route   3      430        432
  -> 192.168.100.78:80            Route   3      435        438


二、Haproxy负载均衡器
原理
使用Haproxy的socket admin通道来实现。

环境说明
Disable backend:test.tianya.cn
Disable REAL SERVER:192.168.100.78

实施步骤
1、修改haproxy.cfg配置
#vi /usr/local/haproxy/etc/haproxy.cfg
在global域添加socket admin支持并重启Haproxy服务

global
... ...
   stats socket /usr/local/haproxy/HaproxySocket level admin
... ...
#service haproxy restart

2、安装socat(在任意的两个socket管道之间建立一个通道,在该通道中交换两端的数据。)

wget http://www.dest-unreach.org/socat/download/socat-2.0.0-b3.tar.gz
./configure --disable-fips
make;make install

注:disable OpenSSL FIPS support  "--disable-fips",在没有安装fips包的情况下make时会提示:

FIPSLD_CC=gcc fipsld -O -D_GNU_SOURCE  -Wall -Wno-parentheses -DHAVE_CONFIG_H -I.  -I.   -c -o socat.o socat.c
/bin/sh: fipsld: command not found
make: *** [socat.o] Error 127


3、禁用成员
#echo "disable server test.tianya.cn/192.168.100.78" | socat stdio /usr/local/haproxy/HaproxySocket
点击在新窗口中浏览此图片

4、启用成员
#echo "enable server test.tianya.cn/192.168.100.78" | socat stdio /usr/local/haproxy/HaproxySocket


三、F5-LTM负载均衡器
原理
使用F5-iControl开发包Pycontrol对F5设备进行管理。

环境说明
Disable POOL:test.tianya.cn
Disable SERVER:192.168.100.42:80 192.168.100.43:80 192.168.100.44:80

实施步骤
1、部署运行环境
#mkdir -p /home/install;cd /home/install
安装python环境(略),要求py2.5或以上。
1.1、安装SUDS模块

#wget https://fedorahosted.org/releases/s/u/suds/python-suds-0.3.8.tar.gz
#tar xvfz python-suds-0.3.8.tar.gz
#cd python-suds-0.3.8
#python setup.py install

1.2、安装PYCONTROL模块

#wget http://trungale.net/pycontrol.tar.gz
#tar xvfz pycontrol.tar.gz
#cd trunk
#python setup.py install

1.3、校验安装结果
#python
>>> import suds >>> import pycontrol.pycontrol as pc >>> suds.__version__ '0.4' >>> suds.__build__ 'GA R699-20100913' >>> pc.__version__ '2.0.1' >>> pc.__build__ 'r83' >>> 
2、编写LB_member.py代码
# -*- coding: utf-8 -*- """ ---------------------------------------------------------------------------- Disable/Enable F5-LTM POOL member Name:        LB_member.py Author:      Liu tian si Email:       liutiansi@gamil.com Created:     2011/05/08 Version:     1.0 Blog:        http://blog.liuts.com Copyright:   (c) 2011 ---------------------------------------------------------------------------- """ import sys import time import string import pycontrol.pycontrol as pc """ ---------------------------------------------------------------------------- F5-LTM Disable/Enable Pool member Class ---------------------------------------------------------------------------- __init__() -Initialization F5-BIG object set_pool_member() -Initialization pool and member object member_factory() -Create a pool member object (Common.IPPortDefinition) session_state_factory() -Create a session state object (LocalLB.PoolMember.MemberSessionState) disable_member() -Disable menber methods enable_member() -Enable menber methods ---------------------------------------------------------------------------- """ class F5_LB_menber():     def __init__(self,_hostname,_username,_password):         self.b = pc.BIGIP(         hostname = _hostname,         username = _username,         password = _password,         fromurl = True,         wsdls = ['LocalLB.PoolMember'])         self.sstate_seq = self.b.LocalLB.PoolMember.typefactory.create('LocalLB.PoolMember.MemberSessionStateSequence')              def set_pool_member(self,pool,members):         self.POOL=pool         self.members=members         self.sstate_seq.item = self.session_state_factory()     def member_factory(self, member):         ip,port = member.split(':')         pmem = self.b.LocalLB.PoolMember.typefactory.create('Common.IPPortDefinition')         pmem.address = ip         pmem.port = int(port)         return pmem     def session_state_factory(self):         session_states = []         for x in self.members:             sstate = self.b.LocalLB.PoolMember.typefactory.create('LocalLB.PoolMember.MemberSessionState')             sstate.member = self.member_factory(x)             session_states.append(sstate)         return session_states     def disable_member(self):         for x in self.sstate_seq.item:             x.session_state = 'STATE_DISABLED'         try:             self.b.LocalLB.PoolMember.set_session_enabled_state(pool_names =                 [self.POOL], session_states = [self.sstate_seq])              except Exception, e:             print e     def enable_member(self):         for x in self.sstate_seq.item:             x.session_state = 'STATE_ENABLED'         try:             self.b.LocalLB.PoolMember.set_session_enabled_state(pool_names = [self.POOL],                 session_states = [self.sstate_seq])         except Exception, e:             print e if __name__ == "__main__":     if len(sys.argv) < 4:         print "Usage %s POOL MEMBER:port[,member1:80,member2:80,member3:80] enable|disable" % sys.argv[0]         print "Examples: python LB_member.py app.domain.com 192.168.0.10:80,192.168.0.11:80,192.168.0.12:80 disable"         sys.exit()     #F5 administrator info     hostname="192.168.100.2"     username="adminuser"     password="adminpass"     App=F5_LB_menber(hostname,username,password)          #init F5 pool and member     CommandParameters = sys.argv[1:]     pool=CommandParameters[0]     members=string.split(CommandParameters[1],',')          App.set_pool_member(pool,members)     if CommandParameters[2]=="enable":         App.enable_member()     elif CommandParameters[2]=="disable":         App.disable_member()     else:         print "opt parameters error!"         sys.exit() 

3、源码分析:
3.1、创建一个池成员对象,将用户传入的成员列表转成规范的pool成员,见member_factory()方法;
3.2、创建一个会话状态对象,追加成员对象到会话状态当中,见session_state_factory()方法;
3.3、创建一个队列,将会话状态对象添加到队列子项中,同时修改所处状态,见__init__()、set_pool_member()、disable_member()/enable_member()方法。

4、禁用成员
#python LB_member.py test.tianya.cn 192.168.100.42:80,192.168.100.43:80,192.168.100.44:80 disable


5、启用成员
#python LB_member.py test.tianya.cn 192.168.100.42:80,192.168.100.43:80,192.168.100.44:80 enable


参考文章
http://devcentral.f5.com/wiki/default.aspx/iControl.CodeShare
posted @ 2011-05-26 22:15 小马歌 阅读(464) | 评论 (0)编辑 收藏
 

Selenium RC

Selenium RC是一款测试工具,允许你为web应用编写自动化的用户接口测试,支持任何程序设计语言、任何HTTP站点以及任何主流浏览器。它使用Selenium Core,这是个利用JavaScript执行自动浏览器任务的库。Selenium测试直接运行于浏览器中,就像真实做的那样。这些测试既可用于验收测试(通过在集成系统上执行更高级的测试而不是只独立地测试系统的各个单元),又可用于浏览器兼容性测试(通过测试不同操作系统和浏览器上的web应用)。

我看看下Selenium RC是如何安装的:

  1. 下载一个Selenium RC分发包存档。
  2. 分发包存档并拷贝server/selenium-server.jar/usr/local/bin(例如)。
  3. 通过运行java -jar /usr/local/bin/selenium-server.jar启动Selenium RC服务器。

现在我们可以利用它的客户/服务器协议向Selenium RC服务器发送命令了。

PHPUnit_Extensions_SeleniumTestCase

PHPUnit_Extensions_SeleniumTestCase测试用例扩展将同Selenium RC通话的客户/服务器协议实现为专门用于web测试的断言方法。

范例 19.1显示如何测试http://www.example.com/站点的<title>元素的内容。

范例 19.1: PHPUnit_Extensions_SeleniumTestCase使用举例

<?php
require_once 'PHPUnit/Extensions/SeleniumTestCase.php';
 
class WebTest extends PHPUnit_Extensions_SeleniumTestCase
{
    protected function setUp()
    {
        $this->setBrowser('*firefox /usr/lib/firefox/firefox-bin');
        $this->setBrowserUrl('http://www.example.com/');
    }
 
    public function testTitle()
    {
        $this->open('http://www.example.com/');
        $this->assertTitleEquals('Example Web Page');
    }
}
?>

不同于PHPUnit_Framework_TestCase类,扩展了PHPUnit_Extensions_SeleniumTestCase的测试用例类必须提供setUp()方法。该方法用于配置Selenium RC会话。可用于此的方法列表见表 19.1

表 19.1. Selenium RC API:装配

方法含义
void setBrowser(string $browser)Selenium RC服务器使用的浏览器。
void setBrowserUrl(string $browserUrl)设置用于测试的基址URL。
void setHost(string $host)设置连接到Selenium RC服务器的主机名。
void setPort(int $port)设置连接到Selenium RC服务器的端口号。
void setTimeout(int $timeout)设置连接到Selenium RC服务器的超时时间。
void setSleep(int $seconds)设置Selenium RC客户端向Selenium RC服务器发送动作指令之间睡眠的秒数。

你也可以使用一组浏览器运行每一个测试:在你的测试用例类中声明一个名为$browserspublic static数组代替使用setBrowser()设置一个浏览器。该数组中的每一项都描述一个浏览器配置。这些浏览器中的每一个都能被不同的Selenium RC服务器接待:

范例 19.2: 设置多浏览器配置

<?php
require_once 'PHPUnit/Extensions/SeleniumTestCase.php';
 
class WebTest extends PHPUnit_Extensions_SeleniumTestCase
{
    public static $browsers = array(
      array(
        'name'    => 'Firefox on Linux',
        'browser' => '*firefox /usr/lib/firefox/firefox-bin',
        'host'    => 'my.linux.box',
        'port'    => 4444,
        'timeout' => 30000,
      ),
      array(
        'name'    => 'Safari on MacOS X',
        'browser' => '*safari',
        'host'    => 'my.macosx.box',
        'port'    => 4444,
        'timeout' => 30000,
      ),
      array(
        'name'    => 'Safari on Windows XP',
        'browser' => '*custom C:\Program Files\Safari\Safari.exe -url',
        'host'    => 'my.windowsxp.box',
        'port'    => 4444,
        'timeout' => 30000,
      ),
      array(
        'name'    => 'Internet Explorer on Windows XP',
        'browser' => '*iexplore',
        'host'    => 'my.windowsxp.box',
        'port'    => 4444,
        'timeout' => 30000,
      )
    );
 
    protected function setUp()
    {
        $this->setBrowserUrl('http://www.example.com/');
    }
 
    public function testTitle()
    {
        $this->open('http://www.example.com/');
        $this->assertTitleEquals('Example Web Page');
    }
}
?>

PHPUnit_Extensions_SeleniumTestCase能够收集测试经由Selenium运行时的代码覆盖率信息:

  1. 拷贝PHPUnit/Extensions/SeleniumTestCase/phpunit_coverage.php到你的web服务器的文件根目录中。
  2. 在你的web服务器的php.ini配置文件中,配置PHPUnit/Extensions/SeleniumTestCase/prepend.phpPHPUnit/Extensions/SeleniumTestCase/append.php分别作为auto_prepend_fileauto_append_file
  3. 在你的扩展了PHPUnit_Extensions_SeleniumTestCase的测试用例类中,使用
    protected $coverageScriptUrl = 'http://host/phpunit_coverage.php';
    配置用于phpunit_coverage.php脚本的URL。

表 19.2列出PHPUnit_Extensions_SeleniumTestCase提供的各种断言方法。

表 19.2. 断言

断言含义
void assertAlertPresent()如果不存在警告(对话框)则报错。
void assertNoAlertPresent()如果存在警告(对话框)则报错。
void assertChecked(string $locator)如果$locator标识的元素未选中则报错。
void assertNotChecked(string $locator)如果$locator标识的元素被选中则报错。
void assertConfirmationPresent()如果不存在确认(对话框)则报错。
void assertNoConfirmationPresent()如果存在确认(对话框)则报错。
void assertEditable(string $locator)如果$locator标识的元素不可编辑则报错。
void assertNotEditable(string $locator)如果$locator标识的元素可编辑则报错。
void assertElementValueEquals(string $locator, string $text)如果$locator标识的元素的值不等于给定的$text则报错。
void assertElementValueNotEquals(string $locator, string $text)如果$locator标识的元素的值等于给定的$text则报错。
void assertElementContainsText(string $locator, string $text)如果$locator标识的元素不含给定的$text则报错。
void assertElementNotContainsText(string $locator, string $text)如果$locator标识的元素包含给定的$text则报错。
void assertElementPresent(string $locator)如果$locator标识的元素不存在则报错。
void assertElementNotPresent(string $locator)如果$locator标识的元素存在则报错。
void assertLocationEquals(string $location)如果当前位置(location)不等于给定的$location则报错。
void assertLocationNotEquals(string $location)如果当前位置(location)等于给定的$location则报错。
void assertPromptPresent()如果不存在提示(对话框)则报错。
void assertNoPromptPresent()如果存在提示(对话框)则报错。
void assertSelectHasOption(string $selectLocator, string $option)如果给定的选项不可用则报错。
void assertSelectNotHasOption(string $selectLocator, string $option)如果给定的选项可用则报错。
void assertSelected($selectLocator, $option)如果给定的标签未选中则报错。
void assertNotSelected($selectLocator, $option)如果给定的标签被选中则报错。
void assertIsSelected(string $selectLocator, string $value)如果给定的值未选中则报错。
void assertIsNotSelected(string $selectLocator, string $value)如果给定的值被选中则报错。
void assertSomethingSelected(string $selectLocator)如果$selectLocator标识的选项未选中则报错。
void assertNothingSelected(string $selectLocator)如果$selectLocator标识的选项被选中则报错。
void assertTextPresent(string $pattern)如果给定的$pattern不存在则报错。
void assertTextNotPresent(string $pattern)如果给定的$pattern存在则报错。
void assertTitleEquals(string $title)如果当前标题不等于给定的$title则报错。
void assertTitleNotEquals(string $title)如果当前标题等于给定的$title则报错。
void assertVisible(string $locator)如果$locator标识的元素不可见则报错。
void assertNotVisible(string $locator)如果$locator标识的元素可见则报错。

表 19.3显示PHPUnit_Extensions_SeleniumTestCase的两个模板方法:

表 19.3. 模板方法

方法含义
void defaultAssertions()重写以执行一个测试用例中的所有测试共享的断言。该方法在发送给Selenium RC服务器的每个命令之后被调用。
void sharedAssertions()重写以执行一个测试用例中的所有测试共享的断言。该方法在一个测试执行结束之前被调用。

请查阅Selenium Core的文档获得关于可用的命令以及如何使用的参考。

利用runSelenese($filename)方法,你也能从它的Selenese/HTML规范运行一个Selenium测试。此外,利用静态属性$seleneseDirectory,你能从一个包含Selenese/HTML文件的目录自动地创建测试对象。指定的目录被递归地搜索预期包含Selenese/HTML的.htm文件。 范例 19.3显示一个例子。

范例 19.3: 使用Selenese/HTML文件的目录作为测试

<?php
require_once 'PHPUnit/Extensions/SeleniumTestCase.php';
 
class SeleneseTests extends PHPUnit_Extensions_SeleniumTestCase
{
    public static $seleneseDirectory = '/path/to/files';
}
?>
posted @ 2011-05-25 12:14 小马歌 阅读(1486) | 评论 (0)编辑 收藏
 
这个问题一般是出现在Internetr Explorer 7.0上面,这个是IE7阅览器提示,IE7浏览器是伴随着Vista操作系统而诞生的,不过微软也发布了针对XP系统的IE7浏览器版本。不过不管是Vista系统还是XP系统下的IE7,由于它的安全防范意识有很大提高,对于非法站点和安全加密站点的过滤都比较苛刻,所以在IE7下访问https这种通过SSL协议加密的网站都会出现故障。尤其为人熟知的在打开淘宝支付宝网页的时候经常会出现,Https密码页面也会有这个提示。

       最容易被一些人搞错地方,就是时间设置问题,所以碰到这种情况,请首先检查你的电脑时间设置是否正确,如果不正确将导致助理从你的电脑上取到的时候,已经不在服务器发送给助理的有效时间范围内,请你核对你的时间设置是否正确。将“自动与internet时间服务器同步”取消后问题消失。如果还是不行,请看下面。

========================================================================

 

一、XP系统下IE7.0 访问https站点故障排除:

         默认情况,XP系统下通过XP版本的IE 7 浏览器,访问https加密的站点都会出现这个提示,这个是IE7阅览器的提示,必须再次点“继续浏览此网站(不推荐)”才能查看页面信息。每次访问Https站点都需要重复点击,在操作上带来很大的麻烦。下面我们就通过安装证书步骤来解决此问题。

        第一步:当我们用IE7浏览Https站点后会在地址栏右边出现一个红色的“证书错误”的提示,我们点该红色按钮,然后选择“查看证书”。

第二步:在打开的“查看证书”窗口中的“常规”标签中点右下角的“安装证书”按钮。

第三步:出现“证书导入向导”后点“下一步”按钮继续。

第四步:选择证书存储的系统区域,通过“浏览”按钮设置将证书保存为“受信任的根证书颁发机构”。

第五步:之后在安全警告窗口中选择“”按钮来安装该证书。

第六步:设置完毕后我们再次访问该https站点就不会出现任何问题,也不会再出现这个错误提示了。

========================================================================

 

 

  二、Vista系统下IE7.0 访问https站点故障排除:

  在Vista系统下使用IE7浏览器访问https站点也会出现这个错误提示,但是他的解决步骤却和XP下IE7有很大区别。这是因为在Vista系统中IE7访问https证书查看里没有安装的提示,错误信息提示“由于CA根证书不在受信任的根证书颁发机构存储区中,所以他不受信任。

  那么该如何解决呢?我是至今还没有发现可以通过调整IE7浏览器的设置来解决此问题,不过可以通过证书导入来解决。

  第一步:首先打开IE7浏览器,然后通过“工具->internet选项”打开属性设置窗口,并选择“内容”标签,直接点“证书”标签。

  第二步:选择要安装的证书类型时点“受信任的根证书颁发机构”,接下来点左下角的“导入”按钮。

  第三步:这时就需要我们在“要导入的文件”设置窗口中找到该网站的证书文件。至于这个证书文件如何获得,笔者的方法是通过在别的浏览器(例如IE 6或XP系统IE 7)中将该网站对应的证书以文件的形式导出即可,接下来回到Vista系统中导入此文件即可。

  第四步:在证书存储设置处和上面介绍的方法一样,选择将所有的证书放入下列存储——受信任的根证书颁发机构。

  第五步:在安装该证书的窗口中点“”按钮即可。

  第六步:所有工作完成后会出现导入成功的提示,以后我们再访问https加密的站点就不会出现上面的错误提示了。

posted @ 2011-05-24 17:04 小马歌 阅读(3087) | 评论 (0)编辑 收藏
 

主要讲述在windows下apache配置SSL以实现http转换为https

SSL: SSl是为Http传输提供安全的协议,通过证书认证来确保客户端和网站服务器之间的数据是安全。也就是说在SSL下http传输是安全的,我们成为https.

过程:

步骤一:安装apache,使其支持SSL,并安装php
  
    1.安装配有SSL模块的apache,apache_2.2.8-win32-x86-openssl-0.9.8g
    2.配置apache以支持SSL:打开apache的配置文件conf/httpd.conf
        1)LoadModule ssl_module modules/mod_ssl.so
          Include conf/extra/httpd-ssl.conf
          去掉两行前面的#
        2)注意修改httpd-ssl.conf 文件里的两个字段:
           SSLCertificateFile "C:/Apache2.2/conf/server.crt"
           SSLCertificateKeyFile "C:/Apache2.2/conf/server.key"
    3.安装php,整合apache和Php(略)  //此步可以省略,如果你不需要PHP的话。
           为下面你所生成的证书和密钥地址。

步骤二:为网站服务器生成证书及私钥文件
       
      1. 生成服务器的私钥
         进入命令行:
         D:\local\apache2\bin\openssl genrsa -out server.key 1024
         在当前目录下生成了一个server.key生成签署申请
      2. 生成签署申请
         D:\local\apache2\bin>openssl req -new –out server.csr -key server.key -config ..\conf\openssl.cnf
         此时生成签署文件server.csr.

步骤三:通过CA为网站服务器签署证书
      
       1.生成CA私钥
         D:\local\apache2\bin\openssl genrsa  -out ca.key 1024
         多出ca.key文件
       2.利用CA的私钥产生CA的自签署证书
         D:\local\apache2\bin\openssl req  -new -x509 -days 365 -key ca.key -out ca.crt  -config ..\conf\openssl.cnf
         此时需要输入一些信息,注意Common Name为服务器域名,如果在本机,为本机IP。
       3.CA为网站服务器签署证书
         D:\local\apache2\bin\openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key -config ..\conf\openssl.cnf
但,此时会报错:
         于是在在当前目录创建demoCA,里面创建以下文件,index.txt,serial内容为01,其他为空,以及文件夹newcert.再执行一遍,即可生成server.crt文件

步骤四:然后将  server.crt,server.key复制到apache的conf文件夹下,重启apache

步骤五:访问http://localhost即支持https
不过由于,我们的CA不是由第三方机构颁发的,而是我们自己颁发的,所以,IE访问的时候,会显示,这个证书不是由Trused CA Authenticator颁发,告诉我们可能有安全隐患

posted @ 2011-05-20 10:08 小马歌 阅读(348) | 评论 (0)编辑 收藏
 

背景:HipHop是Facebook在今年早些时候放出的一个php开源项目,主要的特征就是把php翻译成了c++执行,HipHop所带来的性能提升用Facebook官方博客上项目负责人赵海平的话说:

With HipHop we’ve reduced the CPU usage on our Web servers on average by about fifty percent, depending on the page. Less CPU means fewer servers, which means less overhead. This project has had a tremendous impact on Facebook.

HipHop的官网是http://github.com/facebook/hiphop-php,上面有说明了HipHop的安装步骤,但是我个人感觉那还是不够详细具体的,实际的安装过程中会碰到了不少问题。

在此我详细罗列出安装步骤和分享出解决所碰到问题的过程和方法,以便能帮助到那些喜爱php技术,想要了解HipHop的人,能对HipHop有更深层次的认识。

我的环境准备: Centos 5.5 64bit,Corei7 860,4G内存(注意:内存不能太小,HipHop在make时候和运行时候是很耗内存的;操作系统最好为64位)

开始安装:

1.切换到root账号并建立/root/bulid目录

[user@localhost ~]$ su -
[root@localhost ~]# mkdir build
[root@localhost ~]# cd build

2.安装rpmforge

[root@localhost build]# yum install yum-priorities
[root@localhost build]# wget http://apt.sw.be/redhat/el5/en/i386/RPMS.dag/rpmforge-release-0.3.6-1.el5.rf.i386.rpm
[root@localhost build]# rpm -import http://apt.sw.be/RPM-GPG-KEY.dag.txt
[root@localhost build]# rpm -K rpmforge-release-0.3.6-1.el5.rf.*.rpm
[root@localhost build]# rpm -i rpmforge-release-0.3.6-1.el5.rf.*.rpm
[root@localhost build]# yum check-update
[root@localhost build]# vim /etc/yum.repos.d/rpmforge.repo  修改enabled = 0

3.直接先用yum安装一些HipHop需要的基础包

[root@localhost build]# yum install \
binutils \
binutils-devel \
bison \
cmake \
curl-devel \
distcc \
expat \
gcc  \
gcc-c++ \
gd  \
gd-devel \
git \
libcap-devel \
libevent-devel \
libmcrypt-devel \
libssh2 \
libxml2-devel \
openssl-devel \
pcre-devel \
re2c \
flex \
zlib \
--enablerepo=rpmforge

4.安装perl git

[root@localhost build]# wget http://www.kernel.org/pub/software/scm/git/RPMS/x86_64/perl-Git-1.5.6.1-1.x86_64.rpm
[root@localhost build]# rpm -U perl-Git-1.5.6.1-1.x86_64.rpm

5.安装tbb

[root@localhost build]# wget http://www.threadingbuildingblocks.org/uploads/77/151/3.0/tbb30_20100406oss_lin.tgz
[root@localhost build]# tar xvzf tbb30_20100406oss_lin.tgz
[root@localhost build]# export TBB_INSTALL_DIR="/root/build/tbb30_20100406oss"
[root@localhost build]# export TBB_ARCH_PLATFORM="intel64/cc4.1.0_libc2.4_kernel2.6.16.21"

注意:我一开始cmake的时候,总会报Could NOT find TBB library的错误,分析了hiphop-php/CMake/FindTBB.cmake源码后,发现167行为:

set (TBB_LIBRARY_DIR "${_TBB_INSTALL_DIR}/$ENV{TBB_ARCH_PLATFORM}/lib")

改为

set (TBB_LIBRARY_DIR "${_TBB_INSTALL_DIR}/lib/$ENV{TBB_ARCH_PLATFORM}")

后即可。

因此我得出一个结论,当你配置好了环境变量而cmake的时候又提示你找不到这个lib的时候,本身的cmake文件和你下载下来的的lib不匹配就可能导致此问题,解决的办法即是直接修改cmake文件,满足符合你的需要。

当然还会有其他可能导致类似的问题,我接下去会说。

6.通过rpm包安装boost和icu库

[root@localhost build]# wget http://sourceforge.net/projects/hphp/files/CentOS%205%2064bit/RPM/boost-1.37.0-1.x86_64.rpm/download
[root@localhost build]# wget http://sourceforge.net/projects/hphp/files/CentOS%205%2064bit/RPM/boost-devel-1.37.0-1.x86_64.rpm/download
[root@localhost build]# wget http://sourceforge.net/projects/hphp/files/CentOS%205%2064bit/RPM/icu-4.2.1-6.x86_64.rpm/download
[root@localhost build]# wget http://sourceforge.net/projects/hphp/files/CentOS%205%2064bit/RPM/libicu-4.2.1-6.x86_64.rpm/download
[root@localhost build]# wget http://sourceforge.net/projects/hphp/files/CentOS%205%2064bit/RPM/libicu-devel-4.2.1-6.x86_64.rpm/download
[root@localhost build]# rpm -ivh \
icu-4.2.1-6.x86_64.rpm \
libicu-4.2.1-6.x86_64.rpmm \
libicu-devel-4.2.1-6.x86_64.rpm \
boost-1.37.0-1.x86_64.rpm \
boost-devel-1.37.0-1.x86_64.rpm

7.安装Oniguruma

[root@localhost build]# wget http://www.geocities.jp/kosako3/oniguruma/archive/onig-5.9.2.tar.gz
[root@localhost build]# tar xvfz onig-5.9.2.tar.gz
[root@localhost build]# cd onig-5.9.2
[root@localhost onig-5.9.2]# ./configure && make && sudo make install
[root@localhost onig-5.9.2]# cd ..

8.下载HipHop

[root@localhost build]# git clone git://github.com/facebook/hiphop-php.git

9.安装libevent

[root@localhost build]# wget http://www.monkey.org/~provos/libevent-1.4.13-stable.tar.gz
[root@localhost build]# tar xvzf libevent-1.4.13-stable.tar.gz
[root@localhost build]# cd libevent-1.4.13-stable
[root@localhost libevent-1.4.13-stable]# cp ../hiphop-php/src/third_party/libevent-1.4.13.fb-changes.diff .
[root@localhost libevent-1.4.13-stable]# patch -p1 < libevent-1.4.13.fb-changes.diff
[root@localhost libevent-1.4.13-stable]# ./configure && make && make install
[root@localhost libevent-1.4.13-stable]# cp .libs/libevent.so /usr/lib64/libevent.so
[root@localhost libevent-1.4.13-stable]# cd ..

10.安装curl

[root@localhost build]# wget http://curl.haxx.se/download/curl-7.20.0.tar.gz
[root@localhost build]# tar xvzf curl-7.20.0.tar.gz
[root@localhost build]# cd curl-7.20.0
[root@localhost curl-7.20.0]# cp ../hiphop-php/src/third_party/libcurl.fb-changes.diff .
[root@localhost curl-7.20.0]# patch -p1 < libcurl.fb-changes.diff
[root@localhost curl-7.20.0]# ./configure && make && make install
[root@localhost curl-7.20.0]# cp .libs/libcurl.so /usr/lib64/libcurl.so
[root@localhost curl-7.20.0]# cd ..

11.安装MySQL

[root@localhost build]# wget http://dev.mysql.com/get/Downloads/MySQL-5.5/mysql-5.5.3-m3.tar.gz/from/http://mysql.he.net/
[root@localhost build]# tar zxvf mysql-5.5.3-m3.tar.gz
[root@localhost build]# cd mysql-5.5.3-m3/
[root@localhost mysql-5.5.3-m3]# ./configure --prefix=/root/bulid/mysql/ --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-big-tables --with-readline --with-ssl --with-embedded-server --enable-local-infile --with-plugins=partition,innobase,myisammrg
[root@localhost mysql-5.5.3-m3]# make && make install
[root@localhost mysql-5.5.3-m3]# cd ..
[root@localhost build]# export MYSQL_DIR="/root/bulid/mysql"
[root@localhost build]# vi hiphop-php/CMake/FindMySQL.cmake
删除33行$ENV{MYSQL_INCLUDE_DIR}
删除70行$ENV{MYSQL_DIR}/libmysql_r/.libs
删除71行$ENV{MYSQL_DIR}/lib

12.安装libmemcached,要先装memcached

[root@localhost build]# wget http://memcached.googlecode.com/files/memcached-1.4.5.tar.gz
[root@localhost build]# wget http://launchpad.net/libmemcached/1.0/0.42/+download/libmemcached-0.42.tar.gz
[root@localhost build]# tar zxvf memcached-1.4.5.tar.gz
[root@localhost build]# cd memcached-1.4.5
[root@localhost memcached-1.4.5]# ./configure --with-libevent=/root/build/libevent-1.4.1/
[root@localhost memcached-1.4.5]# make && make install
[root@localhost memcached-1.4.5]# cd ../libmemcached-0.42
[root@localhost libmemcached-0.42]# ./configure --with-memcached-dir=/root/build/memcached-1.4.5
[root@localhost libmemcached-0.42]# make && make install
[root@localhost libmemcached-0.42]# cd ..

13.cmake HipHop

[root@localhost build]# export CMAKE_PREFIX_PATH=/root/build
[root@localhost build]# cd hiphop-php/
[root@localhost hiphop-php]# git submodule init
[root@localhost hiphop-php]# git submodule update
[root@localhost hiphop-php]# export HPHP_HOME=`pwd`
[root@localhost hiphop-php]# export HPHP_LIB=`pwd`/bin
[root@localhost hiphop-php]# cmake .

cmake列表

-- MySQL Include dir: /root/bulid/mysql/include  library dir: /root/bulid/mysql/lib/mysql
-- MySQL client libraries: mysqlclient_r
-- Found libevent: /usr/lib64/libevent.so
-- Found GD: /usr/lib64/libgd.so
-- Found ICU header files in /usr/include
-- Found ICU libraries: /usr/lib64/libicuuc.so
-- Skipping TCmalloc
-- Found Intel TBB
-- Found mcrypt: /usr/lib/libmcrypt.so
-- Looking for arpa/inet.h
-- Looking for arpa/inet.h - found
-- Looking for netinet/in.h
-- Looking for netinet/in.h - found
-- Looking for stddef.h
-- Looking for stddef.h - found
-- Looking for stdint.h
-- Looking for stdint.h - found
-- Looking for string.h
-- Looking for string.h - found
-- Looking for sys/socket.h
-- Looking for sys/socket.h - found
-- Looking for sys/time.h
-- Looking for sys/time.h - found
-- Looking for unistd.h
-- Looking for unistd.h - found
-- Looking for sys/types.h
-- Looking for sys/types.h - found
-- Looking for stdint.h
-- Looking for stdint.h - found
-- Looking for stddef.h
-- Looking for stddef.h - found
-- Check size of size_t
-- Check size of size_t - done
-- Check size of ssize_t
-- Check size of ssize_t - done
-- Check size of uint32_t
-- Check size of uint32_t - done
-- Check size of uint8_t
-- Check size of uint8_t - done
-- Looking for AF_LOCAL
-- Looking for AF_LOCAL - found
-- Looking for PF_LOCAL
-- Looking for PF_LOCAL - found
-- Looking for memset
-- Looking for memset - found
-- Looking for socket
-- Looking for socket - found
-- Looking for strerror
-- Looking for strerror - found
-- Found libevent: /usr/lib64/libevent.so
-- Looking for event_get_version_number
-- Looking for event_get_version_number - found.
-- Performing Test HAVE_LIBEVENT_145
-- Performing Test HAVE_LIBEVENT_145 - Success
-- Found libevent 1.4.5+
-- Looking for include files INCLUDE_CHECK_stdlib.h
-- Looking for include files INCLUDE_CHECK_stdlib.h - found
-- Looking for include files INCLUDE_CHECK_assert.h
-- Looking for include files INCLUDE_CHECK_assert.h - found
-- Looking for strcasecmp
-- Looking for strcasecmp - found
-- Looking for strchr
-- Looking for strchr - found
-- Downloading 8859-1.TXT
-- Downloading 8859-2.TXT
-- Downloading 8859-3.TXT
-- Downloading 8859-4.TXT
-- Downloading 8859-5.TXT
-- Downloading 8859-6.TXT
-- Downloading 8859-7.TXT
-- Downloading 8859-8.TXT
-- Downloading 8859-9.TXT
-- Downloading 8859-10.TXT
-- Downloading 8859-11.TXT
-- Downloading 8859-13.TXT
-- Downloading 8859-14.TXT
-- Downloading 8859-15.TXT
-- Downloading 8859-16.TXT
-- Downloading EastAsianWidth.txt
-- Looking for include files HAVE_SYS_STAT_H
-- Looking for include files HAVE_SYS_STAT_H - found
-- Looking for include files HAVE_STDLIB_H
-- Looking for include files HAVE_STDLIB_H - found
-- Looking for include files HAVE_STRING_H
-- Looking for include files HAVE_STRING_H - found
-- Looking for include files HAVE_MEMORY_H
-- Looking for include files HAVE_MEMORY_H - found
-- Looking for include files HAVE_STRINGS_H
-- Looking for include files HAVE_STRINGS_H - found
-- Looking for include files HAVE_INTTYPES_H
-- Looking for include files HAVE_INTTYPES_H - found
-- Looking for include files HAVE_UNISTD_H
-- Looking for include files HAVE_UNISTD_H - found
-- Looking for include files HAVE_DLFCN_H
-- Looking for include files HAVE_DLFCN_H - found
-- Looking for fdatasync
-- Looking for fdatasync - found
-- Looking for usleep
-- Looking for usleep - found
-- Looking for fullfsync
-- Looking for fullfsync - found
-- Looking for localtime_r
-- Looking for localtime_r - found
-- Looking for gmtime_r
-- Looking for gmtime_r - found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Check if the system is big endian
-- Searching 16 bit integer
-- Check size of unsigned short
-- Check size of unsigned short - done
-- Using unsigned short
-- Check if the system is big endian - little endian
-- Looking for include files HAVE_LOCALE_H
-- Looking for include files HAVE_LOCALE_H - found
-- Looking for include files HAVE_LIMITS_H
-- Looking for include files HAVE_LIMITS_H - found
-- Check size of int32_t
-- Check size of int32_t - done
-- Looking for strtoll
-- Looking for strtoll - found
-- Looking for atoll
-- Looking for atoll - found
-- Looking for strftime
-- Looking for strftime - found
-- Looking for setlocale
-- Looking for setlocale - found
-- Configuring done
-- Generating done
-- Build files have been written to: /root/build/hiphop-php

cmake一般出错就是提示库找不到,原因出了之前说的那种外还有可能是程序找的/usr/lib/libxxx.so,而这个lib本身叫/usr/lib/libxxx.so.1,因此你需要cp一份或是ln,让程序能找得到。

14.make HipHop,离胜利仅仅一步之遥了!

[root@localhost hiphop-php]# make

make的时候很耗cpu和内存的,因此想在vps上玩HipHop的同学要注意了,有可能程序会卡死。

我在make的过程中碰到如下的错误:

追到ext_mysql.cpp的722行后看到有如下语句:

721 static Variant php_mysql_localize_result(MYSQL *mysql) {
722 mysql = mysql->last_used_con;
723 if (!mysql->fields) return true;
724 if (mysql->status != MYSQL_STATUS_GET_RESULT) {
725    // consistent with php_mysql_do_query_general
726    return true;
727 }

我查询了mysql-5.5.3的源码后,发现MYSQL的定义并没有last_used_con,结构如下:

typedef struct st_mysql
{
NET           net;                    /* Communication parameters */
unsigned char *connector_fd;          /* ConnectorFd for SSL */
char          *host,*user,*passwd,*unix_socket,*server_version,*host_info;
char          *info, *db;
struct charset_info_st *charset;
MYSQL_FIELD   *fields;
MEM_ROOT      field_alloc;
my_ulonglong affected_rows;
my_ulonglong insert_id;               /* id if insert on table with NEXTNR */
my_ulonglong extra_info;              /* Not used */
unsigned long thread_id;              /* Id for connection in server */
unsigned long packet_length;
unsigned int  port;
unsigned long client_flag,server_capabilities;
unsigned int  protocol_version;
unsigned int  field_count;
unsigned int  server_status;
unsigned int  server_language;
unsigned int  warning_count;
struct st_mysql_options options;
enum mysql_status status;
my_bool       free_me;                /* If free in mysql_close */
my_bool       reconnect;              /* set to 1 if automatic reconnect */

/* session-wide random string */
char          scramble[SCRAMBLE_LENGTH+1];
my_bool unused1;
void *unused2, *unused3, *unused4, *unused5;

LIST  *stmts;                     /* list of all statements */
const struct st_mysql_methods *methods;
void *thd;
/*
Points to boolean flag in MYSQL_RES  or MYSQL_STMT. We set this flag
from mysql_stmt_close if close had to cancel result set of this object.
*/

my_bool *unbuffered_fetch_owner;
/* needed for embedded server - no net buffer to store the 'info' */
char *info_buffer;
void *extension;
} MYSQL;

然后我google追了下mysql之前的源码,是有过存在last_used_con的时期,但是后来已经被mysql的开发人员废弃了,因此我 怀疑这个有可能是HipHop在开发的时候MYSQL的结构里还有last_used_con,但是我下载的mysql库已经没有,所以导致此问题。

我把722的mysql = mysql->last_used_con;删除后重新make就没有问题了。

还有一点需要注意的是:如果是你在cmake阶段出现的问题,但是在make阶段暴露了,你需要重新cmake的时候你需要移除hiphop-php/CMakeCache.txt文件。

到此,HipHop的安装就算告一段落,还是比较繁琐的,希望以后facebook能简化这个过程。

未来的文章里我会对HipHop的应用有持续的说明,比如它如何编译smarty,以及各种环境性能的测试比较,尽请期待!

本站文章皆为原创,如需转载,请注明出处:http://blog.liubijian.com/hiphop-php-install.html和本站声明,谢谢!

Posted in HipHop, PHP by lbj at 七月 26th, 2010.
Tags: ,
posted @ 2011-05-19 10:29 小马歌 阅读(1244) | 评论 (0)编辑 收藏
 
常用到的是“一个网卡绑定多个IP”

一个网卡绑定多个IP

linux的网络设备配置文件存放在/etc/sysconfig/network-scripts里面,

对于以太网的第一个网络设备,配置文件名一般为ifcfg-eth0。

如果需要为第一个网络设备多绑定一个IP地址,只需要在

/etc/sysconfig/network-scripts目录里面创建一个名为ifcfg-eth0:0的文件,

内容样例为:

DEVICE="eth0:0"

IPADDR="211.100.10.119"

NETMASK="255.255.255.0"

ONBOOT="yes"

其中的DEVICE为设备的名称,

IPADDR为此设备的IP地址,

NETMASK为子网掩码

ONBOOT表示在系统启动时自动启动。

如果需要再绑定多一个IP地址,

只需要把文件名和文件内的DEVICE中的eth0:x加一即可。

LINUX最多可以支持255个IP别名

 

 

多个网卡绑定一个IP

使用多块网卡虚拟成为一块网卡,具有相同的IP地址。

这项技术其实在sun和cisco中已经存在,分别称为Trunking和etherchannel技术,

在linux中,这种技术称为bonding。

因为bonding在内核2.4.x中已经包含了,

只需要在编译的时候把网络设备选项中的Bondingdriversupport选中就可以了。

然后,重新编译核心,重新起动计算机,执行如下命令:

ismodbonding

ifconfigeth0down

ifconfigeth1down

ifconfigbond0ipaddress

ifenslavebond0eth0

ifenslavebond0eth1

现在两块网卡已经象一块一样工作了,这样可以提高集群节点间的数据传输。

你最好把这几句写成一个脚本,再由/etc/rc.d/rc.local调用,

以便一开机就生效。

bonding对于服务器来是个比较好的选择,在没有千兆网卡时,

用两三块100兆网卡作bonding,可大大提高服务器到交换机之间的带宽。

但是需要在交换机上设置连接bonding网卡的两个口子映射为同一个虚拟接口。

posted @ 2011-05-18 12:01 小马歌 阅读(421) | 评论 (0)编辑 收藏
 
[HKEY_CLASSES_ROOT\Http\shell\open\command]
@="\"D:\\Program Files\\GreenBrowser\\GreenBrowser.exe\" \"%1\""
posted @ 2011-05-14 22:01 小马歌 阅读(411) | 评论 (0)编辑 收藏
仅列出标题
共95页: First 上一页 52 53 54 55 56 57 58 59 60 下一页 Last