月度归档:2011 年四月

Flare-兼容Memcached协议的分布式(key/value store)键值存储系统[转]

http://nightsailer.com/2009/07/19/421.html

Flare, Green Lab开发的开源产品,底层使用TC, 完全兼容Memcached协议(ASCII,非binary)。主要有以下特性:

  • 支持Master/slave复制
  • 支持master 分区
  • 支持动态节点添加删除,可以failover
  • 持久存储

现在似乎大家都很关心好的key/value存储方案。作为传统数据库的补充。Memcached由于缺乏持久存储功能,因此无法作为一个可靠的 key/value方案。
我之前关注过基于Memcached派生的一些方案,包括
memcachedb – 新浪团队的,bdb+memcached协议
tokyo tyrant – TC+memcached网络接口
LightCloud 在Tokyo Tyrant上实现了多节点的分布式管理。

repcached - 在memcached源码基础上增加复制功能
redist - 除了string,还允许存储list、set等类型

除了上述软件,还有一些用Erlang,Java的方案,我并没有考虑。首先,我的使用场景还没有大到那个地步,我希望选择一个性价比更高的中低端 方案 ;-)

这其中,最关注的是TT(Toyko tyrant)。 但TT令我不太满意的是对于memcached的协议的兼容性并不够好,比如不能正确处理过期,也不能处理flag。导致客户端无法正常解压缩和 unserialize,虽然在client端都能处理,不过当时是打算作为一个session storage,无法自动过期就比较麻烦,解决方案是通过在TT端执行lua可以进行gc处理,总体感觉不够完满。
memcachedb 对于存储定长字段不错,但不固定长度记录的存储似乎不够好,也没有现行的例子。
repcached 仅仅是支持mm复制,但无法正面解决持久存储的问题。

redist 当初测试时缺乏我需要的api。不过目前已经有了PHP PECL版本的api。 redist的复制机制现在也有了很大的改进。redist的应用实例不多。但是,我认为它和mongoDb一样,值得持续关注。

flare 则是最后选择的。经过测试,虽然速度上没有其他那么快,但其良好的扩展能力让我非常满意。此外,对于memcached协议的兼容性也做的很好。
还有1个特性,flare的key可以超过256bytes,而value可以超过1mb。 传统memcached由于内存分配策略因此有上述限制。
flare的底层存储是可以扩展的,目前使用的是tc(tokyo cabinet)。
从这个结构上看,倒是一个tt的很好替代品。

flare的运行性能还是不错,目前在GREE中得到实际应用,摘自项目网站描述:

Flare is running at GREE (one of the major SNS services in Japan) w/ 6 masters and 6 slaves (over 2,000M keys), and 500-1,000 qps (load average is nearly 0.00…).

看起来很诱人。因为同样TT超过100M的key,性能会直线下降。plurk的lightclound通过多节点的负载均衡解决了这个问 题。(btw,plurk.com目前是被和谐中,要想取得lightclound源码还需要穿墙,唉)

以下是在我的osx上进行的安装测试。

1. 首先下载源码

http://labs.gree.jp/Top/OpenSource/Flare/Download-en.html

2. 使用port安装boost

$ port
install boost

3. 安装tc

http://tokyocabinet.sourceforge.net/

4. 编译flare
tar zxvf flare-1.0.8.tgz
./configure –with-boost=/opt/local –prefix=/opt/flare
make install

flare编译后只有2个文件
flarei,flared
分别是index server和node server.
很清爽啊。

5.运行
flare sources下有一个etc目录,中间分别有index server, node server的配置。
可以直接复制到/opt/flare/etc
然后使用
flared –daemonize -f
flarei –daemonize -f

就可以跑起来了。

6.概念
Flare有几个概念,需要理解
index server
这是索引服务器,用于控制node server的状态
注意,client并不直接和index server进行交互。
node server
这是实际存储节点. node有3种role:
master/slave/proxy
master是主节点,slave是分流节点,用于同步复制master
proxy则将client的请求转发到当前合适的节点(包括master/slave)。
有的人不太理解为什么要用proxy,是否多此一举,而实际测试表明,
通过proxy转发的请求的确要比直接connect到实际节点速度差很多。
这是因为,flare是一个集群,其中的node server是可以动态添加,删除的。
当某个node down后,index server会检测到,并标志其state为down。
此外,master 支持partition,因此通过proxy节点,client无需处理这些复杂问题。
根据作者的建议, proxy node应该和client本地运行,这样可以减少多余的tcp请求。

下面是我写的一个脚本,用于搭建一个典型的测试场景:
1个index server
2个master node,启用partition
1个slave,启用balance

由于flare把ip:port作为一个node,因此只需要1个ip,不同的port就可以快速实现测试需要的环境。

$./start_flare.sh
#启动index server,监听 127.0.0.1:12120
flarei –daemonize -f /opt/flare/etc/flarei.conf
#proxy
flared –daemonize –data-dir /opt/flare/var/data/d0 –index-server-name 127.0.0.1 –index-server-port 12120 –server-name 127.0.0.1 –server-port 12121
#master1 node
flared –daemonize –data-dir /opt/flare/var/data/d1 –index-server-name 127.0.0.1 –index-server-port 12120 –server-name 127.0.0.1 –server-port 12122
#slave node
#flared –daemonize –data-dir /opt/flare/var/data/d2 –index-server-name 127.0.0.1 –index-server-port 12120 –server-name 127.0.0.1 –server-port 12123
#master2
#flared –daemonize –data-dir /opt/flare/var/data/d3 –index-server-name 127.0.0.1 –index-server-port 12120 –server-name 127.0.0.1 –server-port 12124
echo “waiting dameon startup…”
sleep 3
echo “set nodes role….”

# 当某个node加入时,默认是proxy role,因此需要修改这些role
# 通过telnet到index server,可以执行这些命令,我们在脚本中可以使用
# nc来自动执行

# node role的命令格式:
# node role server port master|slave|proxy balance partiion

echo “node role 127.0.0.1 12122 master 1 0″|nc 127.0.0.1 12120
# 设置为slave, balance 为2,给于2倍read权重
echo “node role 127.0.0.1 12123 slave 2 0″|nc 127.0.0.1 12120
# 第2个master node,将partition设置为1,表明这是第2个partion,允许
#将部分数据从原来的master 同步过来
echo “node role 127.0.0.1 12124 master 1 1″|nc 127.0.0.1 12120
sleep 2
echo “stats nodes”|nc 127.0.0.1 12120

STAT 127.0.0.1:12121:role proxy
STAT 127.0.0.1:12121:state down
STAT 127.0.0.1:12121:partition -1
STAT 127.0.0.1:12121:balance 0
STAT 127.0.0.1:12121:thread_type 16
STAT 127.0.0.1:12122:role master
STAT 127.0.0.1:12122:state down
STAT 127.0.0.1:12122:partition 0
STAT 127.0.0.1:12122:balance 1
STAT 127.0.0.1:12122:thread_type 17
STAT 127.0.0.1:12123:role slave
STAT 127.0.0.1:12123:state prepare
STAT 127.0.0.1:12123:partition 0
STAT 127.0.0.1:12123:balance 0
STAT 127.0.0.1:12123:thread_type 18
STAT 127.0.0.1:12124:role master
STAT 127.0.0.1:12124:state prepare
STAT 127.0.0.1:12124:partition 1
STAT 127.0.0.1:12124:balance 1
STAT 127.0.0.1:12124:thread_type 19
END

stats nodes可以列出当前各个节点的状态信息
注意, 有些节点的state是prepare,表明正在进行同步复制。

我进行了一个简单的测试, 分别读写1M 记录,
测试代码


?php
$host = $argv[1];
$port = $argv[2];
set_time_limit(0);
echo "connect to $host $port \n";
$memcached = new Memcached();
$memcached->addServer($host,$port);

$loop = 1000000;
echo "start set tests...\n";
$start =microtime(true);
for ($i=0; $i < $loop; $i++) {
    $memcached->set(md5("k$i"),md5("k$i"));
}
$end = microtime(true);
echo "ok.\n";
$total1 = $end-$start;
echo "start get tests...\n";
$start =microtime(true);
for ($i=0; $i < $loop; $i++) {
    $memcached->get(md5("k$i"));
}
$end = microtime(true);
$total2 = $end-$start;
echo "ok.\n";
echo "set time:$total1 ",$loop/$total1,' rps',"\n";
echo "get time:$total2 ",$loop/$total2, ' rps',"\n";
?>

当单节点执行set/get操作时,速度和memcached
的ascii模式基本一样,rps只略低几百个。
但是使用proxy 节点后,只有原来的一半。

============
推荐的Flare的适用场景:
1. 最正统的就是key/value storage。我自己将flare作为doggy中dhash的后端实现。
2. Session Storage。 比如PHP,可以直接适用memcached的session_handler。由于是持久的,因此解决原来memcached的尴尬和困扰。
3. 其他的基于key/value的扩展方案

Flare可以直接替代Memcached么?
答案是否。Flare的优势和本质是分布式key/value的持久存储,而不是作为一个cache。作为一个caching方案,要比 memcached差很多。
尤其是启用了binary protocol后,memcached的优势很明显。

CentOS 5.4 安裝 boost 1.4.1 筆記[转]

/*編譯環境準備*/

安裝 ICU for Regex Unicode support

#yum install icu-3.6-5.11.4
#yum install libicu-devel-3.6-5.11.4
#yum install libicu-3.6-5.11.4

Export 環境變數

#export ICU_PATH=/usr
#export ICU_LINK=-L/usr/lib64
#export EXPAT_INCLUDE=/usr/include ;
#export EXPAT_LIBPATH=/usr/lib64 ;

安裝 MPI for Graph MPI support

#yum install openmpi-libs-1.3.2-2.el5
#yum install openmpi-devel-1.3.2-2.el5
#yum install openmpi-1.3.2-2.el5
#yum install mpi-selector-1.0.2-1.el5
#yum install openmpi-devel-1.3.2-2.el5

安裝 Expat for XML 需求

#yum install expat-devel-1.95.8-8.3.el5_4.2
#yum install expat-1.95.8-8.3.el5_4.2


/*開始編譯*/

解壓縮 boost,並切換至 boost 目錄。
執行指令:

#./bootstrap.sh --prefix=/usr

修改 project-config.jam:

using mpi ;

執行指令:

#./bjam install >build_log 2>&1

編譯輸出結果將會紀錄於 build_log,編譯期間可使用 tail -f build_log 觀察編譯狀態。

编译boost1.43.0

编译boost1.43.0 with icu 支持regex unicode编码
安装icu,即IBM的一个通用的转码库
wget http://downloads.sourceforge.net/project/icu/ICU4C/4.0/icu4c-4_0-src.tgz?use_mirror=cdnetworks-kr-2
tar zxvf icu4c-4_0-src.tgz
cd icu/source
./configure –prefix=/usr
make
make install
ldconfig
下载安装boost

wget http://sourceforge.net/projects/boost/files/boost/1.43.0/boost_1_43_0.tar.gz/download
tar zxvf boost_1_43_0.tar.gz
cd boost_1_43_0
rm -rf /usr/include/boost/
rm -rf /usr/lib/libboost*
./bootstrap.sh
./bjam -sHAVE_ICU=1
编译大概半小时,完成后:
cp ./stage/lib/* /usr/lib
cp ./boost /usr/include/
ldconfig
以前我使用bjam install –prefix=/usr但特别慢,有的时候lib下的东西copy不过去。现在我编译完直接cp过去,一点问题没有。

[技巧] CentOS 5.5一键安装Nginx+MySQL+PHP

#***************************************************************************************
#CentOS 5.5一键安装nginx+mysql+php
#系统为定制安装,只安装Editors组件,系统内核升级到2.6.35.7,有两个地方需要注意下:
#1、安装patch
#yum install -y patch
#2、设置环境变量
#sed -i “s#PATH=$PATH:$HOME/bin#PATH=$PATH:$HOME/bin:/sbin#” /root/.bash_profile
#***************************************************************************************

#!/bin/bash

echo “============================更新系统时间===========================================”
yum install -y ntp
ntpdate time.nist.gov
echo “00 01 * * * /usr/sbin/ntpdate time.nist.gov” >> /etc/crontab

echo “============================安装开源组件===========================================”
sudo -s
LANG=C
yum install -y gcc gcc-c++ autoconf libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel libxml2 libxml2-devel zlib zlib-devel glibc glibc-devel glib2 glib2-devel bzip2 bzip2-devel ncurses ncurses-devel curl curl-devel e2fsprogs e2fsprogs-devel krb5 krb5-devel libidn libidn-devel openssl openssl-devel openldap openldap-devel nss_ldap openldap-clients openldap-servers

echo “============================下载安装包=============================================”
cd /opt
wget http://sysoev.ru/nginx/nginx-0.8.46.tar.gz
wget http://www.php.net/get/php-5.2.14.tar.gz/from/this/mirror
wget http://php-fpm.org/downloads/php-5.2.14-fpm-0.5.14.diff.gz
wget http://dev.mysql.com/get/Downloads/MySQL-5.5/mysql-5.5.3-m3.tar.gz/from/http://mysql.he.net/
wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.13.1.tar.gz
wget “http://downloads.sourceforge.net/mcrypt/libmcrypt-2.5.8.tar.gz?modtime=1171868460&big_mirror=0″
wget “http://downloads.sourceforge.net/mcrypt/mcrypt-2.6.8.tar.gz?modtime=1194463373&big_mirror=0″
wget http://pecl.php.net/get/memcache-2.2.5.tgz
wget “http://downloads.sourceforge.net/mhash/mhash-0.9.9.9.tar.gz?modtime=1175740843&big_mirror=0″
wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.10.tar.gz
wget http://bart.eaccelerator.net/source/0.9.6.1/eaccelerator-0.9.6.1.tar.bz2
wget http://pecl.php.net/get/PDO_MYSQL-1.0.2.tgz
wget http://blog.s135.com/soft/linux/nginx_php/imagick/ImageMagick.tar.gz
wget http://pecl.php.net/get/imagick-2.3.0.tgz

echo “============================编译安装php所需的支持库=================================”
cd /opt
tar zxvf libiconv-1.13.1.tar.gz
cd libiconv-1.13.1/
./configure –prefix=/usr/local
make
make install
cd ../

tar zxvf libmcrypt-2.5.8.tar.gz
cd libmcrypt-2.5.8/
./configure
make
make install
/sbin/ldconfig
cd libltdl/
./configure –enable-ltdl-install
make
make install
cd ../../

tar zxvf mhash-0.9.9.9.tar.gz
cd mhash-0.9.9.9/
./configure
make
make install
cd ../

ln -s /usr/local/lib/libmcrypt.la /usr/lib/libmcrypt.la
ln -s /usr/local/lib/libmcrypt.so /usr/lib/libmcrypt.so
ln -s /usr/local/lib/libmcrypt.so.4 /usr/lib/libmcrypt.so.4
ln -s /usr/local/lib/libmcrypt.so.4.4.8 /usr/lib/libmcrypt.so.4.4.8
ln -s /usr/local/lib/libmhash.a /usr/lib/libmhash.a
ln -s /usr/local/lib/libmhash.la /usr/lib/libmhash.la
ln -s /usr/local/lib/libmhash.so /usr/lib/libmhash.so
ln -s /usr/local/lib/libmhash.so.2 /usr/lib/libmhash.so.2
ln -s /usr/local/lib/libmhash.so.2.0.1 /usr/lib/libmhash.so.2.0.1
ln -s /usr/local/bin/libmcrypt-config /usr/bin/libmcrypt-config

tar zxvf mcrypt-2.6.8.tar.gz
cd mcrypt-2.6.8/
/sbin/ldconfig
./configure
make
make install
cd ../

echo “=============================编译安装MySQL 5.5.3-m3=========================”

/usr/sbin/groupadd mysql
/usr/sbin/useradd -g mysql mysql -s /sbin/nologin
tar zxvf mysql-5.5.3-m3.tar.gz
cd mysql-5.5.3-m3/
./configure –prefix=/usr/local/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
make;make install
chmod +w /usr/local/mysql
chown -R mysql:mysql /usr/local/mysql
cd ../

mkdir -p /data/mysql/data
mkdir -p /data/mysql/binlog
mkdir -p /data/mysql/relaylog
mkdir -p /data/mysql/mysql
chown -R mysql:mysql /data/mysql
/usr/local/mysql/bin/mysql_install_db –basedir=/usr/local/mysql –datadir=/data/mysql/data –user=mysql

cp conf/my.cnf /data/mysql/my.cnf

#设置mysql启动文件
cp conf/mysqld /etc/rc.d/init.d/mysqld

#cp support-files/mysql.server /etc/rc.d/init.d/mysqld
#vi /etc/rc.d/init.d/mysqld
#basedir=
#basedir=/usr/local/mysql
#datadir=
#datadir=/data/mysql/data

chmod 700 /etc/rc.d/init.d/mysqld
/etc/rc.d/init.d/mysqld start
/sbin/chkconfig –add mysqld
/sbin/chkconfig –level 2345 mysqld on
ln -s /usr/local/mysql/bin/mysql /sbin/mysql
ln -s /usr/local/mysql/bin/mysqladmin /sbin/mysqladmin

#设置root密码(1q2w3e)
/sbin/mysqladmin -u root password 1q2w3e

#配置库文件搜索路径
echo “/usr/local/mysql/lib/mysql” >> /etc/ld.so.conf
/sbin/ldconfig

#添加/usr/local/mysql/bin到环境变量PATH中
export PATH=$PATH:/usr/local/mysql/bin

#添加mysql管理帐户
#mysql -h localhost -u root -p1q2w3e
#msqyl> use mysql;
#msqyl> grant all on *.* to ‘kerry’@’172.16.16.150′ identified by ‘kerry1q2w3e’;
#msqyl> flush privileges;
#msqyl> exit;

echo “==========================编译安装PHP(FastCGI模式)===============================”
#编译安装php-5.2.14
tar -zxvf php-5.2.14.tar.gz
gzip -cd php-5.2.14-fpm-0.5.14.diff.gz | patch -d php-5.2.14 -p1
cd php-5.2.14/
./configure –prefix=/usr/local/php –with-config-file-path=/usr/local/php/etc –with-mysql=/usr/local/mysql –with-mysqli=/usr/local/mysql/bin/mysql_config –with-iconv-dir=/usr/local –with-freetype-dir –with-jpeg-dir –with-png-dir –with-zlib –with-libxml-dir=/usr –enable-xml –disable-rpath –enable-discard-path –enable-safe-mode –enable-bcmath –enable-shmop –enable-sysvsem –enable-inline-optimization –with-curl –with-curlwrappers –enable-mbregex –enable-fastcgi –enable-fpm –enable-force-cgi-redirect –enable-mbstring –with-mcrypt –with-gd –enable-gd-native-ttf –with-openssl –with-mhash –enable-pcntl –enable-sockets –with-ldap –with-ldap-sasl –with-xmlrpc –enable-zip –enable-soap
make ZEND_EXTRA_LIBS=’-liconv’
make install
cp php.ini-dist /usr/local/php/etc/php.ini
cd ../

#编译安装PHP5扩展模块

tar zxvf memcache-2.2.5.tgz
cd memcache-2.2.5/
/usr/local/php/bin/phpize
./configure –with-php-config=/usr/local/php/bin/php-config
make
make install
cd ../

tar jxvf eaccelerator-0.9.6.1.tar.bz2
cd eaccelerator-0.9.6.1/
/usr/local/php/bin/phpize
./configure –enable-eaccelerator=shared –with-php-config=/usr/local/php/bin/php-config
make
make install
cd ../

tar zxvf PDO_MYSQL-1.0.2.tgz
cd PDO_MYSQL-1.0.2/
/usr/local/php/bin/phpize
./configure –with-php-config=/usr/local/php/bin/php-config –with-pdo-mysql=/usr/local/mysql
make
make install
cd ../

tar zxvf ImageMagick.tar.gz
cd ImageMagick-6.5.1-2/
./configure
make
make install
cd ../

tar zxvf imagick-2.3.0.tgz
cd imagick-2.3.0/
/usr/local/php/bin/phpize
./configure –with-php-config=/usr/local/php/bin/php-config
make
make install
cd ../

echo “===========================修改php.ini文件==============================”

sed -i ‘s#extension_dir = “./”#extension_dir = “/usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/”\nextension = “memcache.so”\nextension = “pdo_mysql.so”\nextension = “imagick.so”\n#’ /usr/local/php/etc/php.ini
sed -i ‘s#output_buffering = Off#output_buffering = On#’ /usr/local/php/etc/php.ini
sed -i “s#; always_populate_raw_post_data = On#always_populate_raw_post_data = On#g” /usr/local/php/etc/php.ini
sed -i “s#; cgi.fix_pathinfo=0#cgi.fix_pathinfo=0#g” /usr/local/php/etc/php.ini

#配置eAccelerator加速PHP
mkdir -p /usr/local/eaccelerator_cache
cat >>/usr/local/php/etc/php.ini<<EOF
[eaccelerator]
zend_extension=”/usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/eaccelerator.so”
eaccelerator.shm_size=”64″
eaccelerator.cache_dir=”/usr/local/eaccelerator_cache”
eaccelerator.enable=”1″
eaccelerator.optimizer=”1″
eaccelerator.check_mtime=”1″
eaccelerator.debug=”0″
eaccelerator.filter=”"
eaccelerator.shm_max=”0″
eaccelerator.shm_ttl=”3600″
eaccelerator.shm_prune_period=”3600″
eaccelerator.shm_only=”0″
eaccelerator.compress=”1″
eaccelerator.compress_level=”9″
EOF

/usr/sbin/groupadd www
/usr/sbin/useradd -g www www -s /sbin/nologin
mkdir -p /data/htdocs/blog
chmod +w /data/htdocs/blog
chown -R www:www /data/htdocs/blog
mkdir -p /data/htdocs/www
chmod +w /data/htdocs/www
chown -R www:www /data/htdocs/www

mv /usr/local/php/etc/php-fpm.conf /usr/local/php/etc/php-fpm.conf.bak
cp conf/php-fpm.conf /usr/local/php/etc/php-fpm.conf
ulimit -SHn 65535
/usr/local/php/sbin/php-fpm start

echo “================================ 安装Nginx 0.8.46 =============================”
tar zxvf pcre-8.10.tar.gz
cd pcre-8.10/
./configure
make;make install
cd ../

tar zxvf nginx-0.8.46.tar.gz
cd nginx-0.8.46/
./configure –user=www –group=www –prefix=/usr/local/nginx –with-http_stub_status_module –with-http_ssl_module
make;make install
cd ../

mkdir -p /data/logs
chmod +w /data/logs
chown -R www:www /data/logs

mv /usr/local/nginx/conf/nginx.conf /usr/local/nginx/conf/nginx.conf.bak
cp conf/nginx.conf /usr/local/nginx/conf/nginx.conf
cp conf/fcgi.conf /usr/local/nginx/conf/fcgi.conf

ulimit -SHn 65535
/usr/local/nginx/sbin/nginx

echo “=============================== 添加php测试页面 ===============================”
cat >/data/htdocs/www/phpinfo.php<<EOF
<?php
phpinfo();
$link=mysql_connect(‘localhost’,'root’,’1q2w3e’);
if(!$link) echo “失败!”;
else echo “成功!”;
mysql_close();
?>
EOF

echo “=============================== 设置启动项 =====================================”

echo “ulimit -SHn 65535″ >> /etc/rc.local
echo “/usr/local/php/sbin/php-fpm start” >> /etc/rc.local
echo “/usr/local/nginx/sbin/nginx” >> /etc/rc.local

cat >>/etc/sysctl.conf<<EOF
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
#net.ipv4.tcp_fin_timeout = 30
#net.ipv4.tcp_keepalive_time = 300
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_max_tw_buckets = 5000

net.ipv4.tcp_max_syn_backlog = 65536
net.core.netdev_max_backlog =  32768
net.core.somaxconn = 32768

net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216

net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2

net.ipv4.tcp_tw_recycle = 1
#net.ipv4.tcp_tw_len = 1
net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_mem = 94500000 915000000 927000000
net.ipv4.tcp_max_orphans = 3276800
EOF

/sbin/sysctl -p

#测试nginx配置
#/usr/local/nginx/sbin/nginx -t
#平滑重启
#/usr/local/nginx/sbin/nginx -s reload

echo “======================== LNMP安装完成 ===============================”
echo “The path of some dirs:”
echo “mysql dir:   /usr/local/mysql”
echo “php dir:     /usr/local/php”
echo “nginx dir:   /usr/local/nginx”
echo “web dir      /data/htdocs/www”
echo “======================================================================”

[Hyper-V] 如何在无线局域网中为 Hyper-V 虚拟机提供网络接入[转]

Windows Server 2008 with Hyper-V(以下简称:Hyper-V) 在推出后不少 ITPro 都对其展开了评测,相信不少朋友在自己的笔记本中安装测试时都遇到这样的难题,Hyper-V Beta 目前对无线网卡并不支持,所以当我们的笔记本只能通过无线网卡接入网络时, Hyper-V 下的虚拟机便无法正常接入网络,这为测试带来了诸多不便,其实我们可以通过另一种方式来实现,即添加微软的 Loopback 网卡,之后启用 ICS 或安装路由和远程访问服务启用 NAT 方式共享无线网络,使 Loopback 能够通过无线网卡接入网络,因为 Hyper-V 支持微软的 Loopback 网卡。

首先,请参考我之前的一篇Blog:如何在 Windows Server 2008 中启用无线局域网支持,网址是:http://goxia.maytide.net/read.php/37.htm,根据提示安装无线局域网服务,并正确配置无线网络,测试是否已经能够正常通讯。

之后,进入”Control Panel”,双击运行”Add Hardware”以”Install the hardware that I manually select from a list (Advanced)”方式手工安装硬件,选择添加”Network adapters”,查找并安装”Manufacturer”为”Microsoft”,”Network Adapter”为”Microsoft Loopback Adapter”的网卡驱动。完成后配置其网络属性。

如果你的无线网络非192.168.0.x/24,那么你可以将 Loopback 网卡的 IP 地址配置为 192.168.0.1/24,并且在无线网卡上的配置启用 ICS 服务。如果 192.168.0.x/24 被无线网络占用,那么只能通过”Server Manager”,进入”Roles”管理,单击”Add Roles”,添加”Network Policy and Access Services”角色中的”Routing and Remote Access Services”服务,并以NAT方式对无线网络进行共享。

如何让笔记本上运行的Hyper-V使用无线网络?

Hyper-V本身不支持使用电脑上的无线网卡(只支持有线网卡),这里你可以使用一个变通方法:

1. 创建一个新的虚拟网络(可以取一个容易识别的名字,比方To-Outside),类型选择Internal Only

2. 在开始运行里输入ncpa.cpl,回车打开网络连接。

3. 在网络连接里同时选择刚才创建的To-Outside和笔记本上的无线网卡,然后右键单击在他们当中任何一个上,选择桥接。

4. 把新建的虚拟机的网卡连接到To-Outside,这样它就能访问因特网了。

CentOS 5.5升级内核到2.6.35[转]

#!/bin/bash
# BY kerryhu
# QQ:263205768
# MAIL:king_819@163.com
# BLOG:http://kerry.blog.51cto.com

当前系统版本为CentOS 5.5,内核版本为2.6.18-194,现将内核升级到2.6.35.4

[root@vhost data]# wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.35.4.tar.bz2
[root@vhost data]# tar -jxvf linux-2.6.35.4.tar.bz2
[root@vhost data]# mv linux-2.6.35.4 /usr/src
[root@vhost data]# cd /usr/src/linux-2.6.35.4
#配置内核参数,选择自己所需的模块
[root@vhost linux-2.6.35.4]# make menuconfig
#编译安装内核
[root@vhost linux-2.6.35.4]# make
[root@vhost linux-2.6.35.4]# make modules
[root@vhost linux-2.6.35.4]# make modules_install
[root@vhost linux-2.6.35.4]# make install

注:如果老版本是2.4

  1. make menuconfig
  2. make dep
  3. make bzimage
  4. make modules
  5. make modules_install
  6. make install
如果是2.6
  1. make menuconfig
  2. make
  3. make modules_install
  4. make install

#修改默认以新的内核启动。
[root@vhost linux-2.6.35.4]# vi /boot/grub/grub.conf
default=0
#将新的内核配置文件复制到/boot目录。
[root@vhost linux-2.6.35.4]# cp /usr/src/linux-2.6.35.4/.config /boot/config-2.6.35.4
[root@vhost linux-2.6.35.4]# reboot

#重启后验证内核版本
[root@vhost /]# uname -r
2.6.35.4

#升级过程中遇到的问题
一、启动报错
mount: could not find filesystem ‘/dev/root’
setuproot: moving /dev failed: No such file or directory
setuproot: error mounting /proc: No such file or directory
setuproot: error mounting /sys: No such file or directory
switchroot: mount failed: No such file or directory
Kernel panic – not syncing: Attempted to kill init!

解决方法:
执行完make menuconfig后,修改/usr/src/linux-2.6.35.4/.config
将#CONFIG_SYSFS_DEPRECATED_V2 is not set
默认被注释掉的,将其改为y。即修改为
CONFIG_SYSFS_DEPRECATED_V2=y
再接着编译安装内核

二、启动报错
insmod: error inserting ‘/lib/dm-region-hash.ko’ : -1 File exists

解决方法:
1、解压initrd文件
[root@vhost ~]# cp /boot/initrd-2.6.35.4.img /tmp
[root@vhost ~]# cd /tmp/
[root@vhost tmp]# ls
initrd-2.6.35.4.img
[root@vhost tmp]# mkdir newinitrd
[root@vhost tmp]# cd newinitrd/
[root@vhost newinitrd]# zcat ../initrd-2.6.35.4.img |cpio -i
11282 blocks
释放之后看到如下内容
[root@vhost newinitrd]# ls
bin   dev   etc   init   lib   proc   sbin   sys   sysroot

2、下边就是编辑init,删掉其中重复的四行中的两行
echo “Loading dm-region-hash.ko module”
insmod /lib/dm-region-hash.ko
echo “Loading dm-region-hash.ko module”
insmod /lib/dm-region-hash.ko

3、重新打包initrd
[root@vhost newinitrd]# find .|cpio -c -o > ../initrd
11282 blocks
[root@vhost newinitrd]# cd ..
[root@vhost tmp]# gzip -9 < initrd > initrd.img
[root@vhost tmp]# ls
initrd-2.6.35.4.img    initrd    initrd.img          newinitrd

initrd.img就是重新打包的initrd了,然后把initrd.img拷贝到/boot
[root@vhost tmp]# mv /boot/initrd-2.6.35.4.img /boot/initrd-2.6.35.4.img.bak
[root@vhost tmp]# mv initrd.img /boot/initrd-2.6.35.4.img
[root@vhost tmp]# reboot
这样“insmod: error inserting ‘/lib/dm-region-hash.ko’ : -1 File exists” 就不会有了

C#: WebClient Usage[转]

Microsoft has provided a great utility since .NET 1.0 for doing quick I/O via websites.  The WebClient class provides basic functionality for downloading from and uploading to webservers.  the WebClient example on MSDN leaves a lot to be desired, especially for beginners.  I’d like to expand on that, as well as provide some example code.

C#: Using WebClient to fetch a page:

        // create a new instance of WebClient
        WebClient client = new WebClient();

        // set the user agent to IE6
        client.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705;)");
        try
        {
            // actually execute the GET request
            string ret = client.DownloadString("http://www.google.com/");

            // ret now contains the contents of the webpage
            Console.WriteLine("First 256 bytes of response: " + ret.Substring(0,265));
        }
        catch (WebException we)
        {
            // WebException.Status holds useful information
            Console.WriteLine(we.Message + "\n" + we.Status.ToString());
        }
        catch (NotSupportedException ne)
        {
            // other errors
            Console.WriteLine(ne.Message);
        }

(This code uses DownloadString, you can also use DownloadData for a more binary-friendly version)

This is great for fetching simple pages that have data encoded in the querystring, but there are some problems with the basic DownloadString method of WebClient.  It’s synchronous, so it will block until the operation completes.  So for slow connections, or large files, this would need to run in another thread.  There is a better way.  But first, here’s another example of another basic, but important, method,DownloadFile.

        // create a new instance of WebClient
        WebClient client = new WebClient();

        // set the user agent to IE6
        client.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705;)");
        try
        {
            // actually execute the GET request
            client.DownloadFile("http://www.google.com/","google_fetch.txt");

            // ret now contains the contents of the webpage
            Console.WriteLine("File Saved.");
        }
        catch (WebException we)
        {
            // WebException.Status holds useful information
            Console.WriteLine(we.Message + "\n" + we.Status.ToString());
        }
        catch (NotSupportedException ne)
        {
            // other errors
            Console.WriteLine(ne.Message);
        }

This example is almost identical to the above, aside from the client.DownloadFile method.  This will save the file to disk, instead of returning a string–often what you would end up doing with the string anyway.

But can I send POST data?

Yes!  Using WebClient.UploadString or WebClient.UploadData you can POST data to the server easily.  I’ll show an example using UploadData, since UploadString is used in the same manner as DownloadString.

            byte[] bret = client.UploadData("http://www.website.com/post.php", "POST",
                System.Text.Encoding.ASCII.GetBytes("field1=value1&amp;field2=value2") );

            string sret = System.Text.Encoding.ASCII.GetString(bret);

UploadData returns a byte array (byte[]) which contains the contents of the page.  This can easily be converted to a string by using the System.Text.Encoding.ASCII.GetString() method.  You can also use the other encoding types in System.Text.Encoding (such as UTF8) to do the same.

Also note the use of GetBytes(), the UploadData method will only take a byte array as a buffer for the upload.  This works well if you are uploading a binary file.

What about the asynchronous methods of WebClient?

WebClient provides asynchronous methods for fetching webpages as well, they are named similarly to the synchronous methods, DownloadFileAsync, DownloadDataAsync, DownloadStringAsync, UploadFileAsync, UploadDataAsync, UploadStringAsync, and UploadValuesAsync.

In order to execute an Async request, you will need to attach event handlers before the method is executed.  Without these event handlers you will not have any sense of when the operation finishes, or what stage it is at.

C# WebClient Asynchronous call example:

void do_upload() {
   WebClient client = new WebClient();
   // add event handlers for completed and progress changed
   client.UploadProgressChanged += new UploadProgressChangedEventHandler(client_UploadProgressChanged);

   client.UploadFileCompleted += new UploadFileCompletedEventHandler(client_UploadFileCompleted);
  // carry out the operation as normal
   client.UploadFileAsync("http://www.daveamenta.com/up.php", @"c:\somefile.bin");
}

void client_UploadProgressChanged(object sender, UploadProgressChangedEventArgs e)
{
   Console.WriteLine(e.ProgressPercentage);
}

void client_UploadFileCompleted(object sender, UploadFileCompletedEventArgs e)
{
   if(e.Result != null) {
      Console.WriteLine(System.Text.Encoding.ASCII.GetString(e.Result));
   }
}

The call to client.DownloadFileAsync will no longer block the thread, and will execute in the background, periodically calling the event handlers to display progress.  The other methods can be used in this same way.

在C#中使用SerialPort类实现串口通信[转]

在.NET Framework 2.0中提供了SerialPort类,该类主要实现串口数据通信等。本文章将本人在学习过程中从网络上搜集到的相关信息写出来供大家参考。

下面主要介绍该类的主要属性(表1)和方法(表.2)。

如果需要了解更多的信息请登录http://msdn.microsoft.com/zh-cn/library/system.io.ports.serialport(VS.80).aspx查看。

相关文章

《使用System.IO.Ports读取COM口数据》

http://www.devasp.net/net/articles/display/727.html

表1                                                      SerialPort类的常用属性

名  称 说  明
BaseStream 获取 SerialPort 对象的基础 Stream 对象
BaudRate 获取或设置串行波特率
BreakState 获取或设置中断信号状态
BytesToRead 获取接收缓冲区中数据的字节数
BytesToWrite 获取发送缓冲区中数据的字节数
CDHolding 获取端口的载波检测行的状态
CtsHolding 获取“可以发送”行的状态
DataBits 获取或设置每个字节的标准数据位长度
DiscardNull 获取或设置一个值,该值指示 Null 字节在端口和接收缓冲区之间传输时是否被忽略
DsrHolding 获取数据设置就绪 (DSR) 信号的状态
DtrEnable 获取或设置一个值,该值在串行通信过程中启用数据终端就绪 (DTR) 信号
Encoding 获取或设置传输前后文本转换的字节编码
Handshake 获取或设置串行端口数据传输的握手协议
IsOpen 获取一个值,该值指示 SerialPort 对象的打开或关闭状态
NewLine 获取或设置用于解释 ReadLine( )和WriteLine( )方法调用结束的值
Parity 获取或设置奇偶校验检查协议

续表

名  称 说  明
ParityReplace 获取或设置一个字节,该字节在发生奇偶校验错误时替换数据流中的无效字节
PortName 获取或设置通信端口,包括但不限于所有可用的 COM 端口
ReadBufferSize 获取或设置 SerialPort 输入缓冲区的大小
ReadTimeout 获取或设置读取操作未完成时发生超时之前的毫秒数
ReceivedBytesThreshold 获取或设置 DataReceived 事件发生前内部输入缓冲区中的字节数
RtsEnable 获取或设置一个值,该值指示在串行通信中是否启用请求发送 (RTS) 信号
StopBits 获取或设置每个字节的标准停止位数
WriteBufferSize 获取或设置串行端口输出缓冲区的大小
WriteTimeout 获取或设置写入操作未完成时发生超时之前的毫秒数

表2                                                     SerialPort类的常用方法

方 法 名 称 说  明
Close 关闭端口连接,将 IsOpen 属性设置为False,并释放内部 Stream 对象
Open 打开一个新的串行端口连接
Read 从 SerialPort 输入缓冲区中读取
ReadByte 从 SerialPort 输入缓冲区中同步读取一个字节
ReadChar 从 SerialPort 输入缓冲区中同步读取一个字符
ReadLine 一直读取到输入缓冲区中的 NewLine 值
ReadTo 一直读取到输入缓冲区中指定 value 的字符串
Write 已重载。将数据写入串行端口输出缓冲区
WriteLine 将指定的字符串和 NewLine 值写入输出缓冲区

使用SerialPort类的方法:

方法一:

首先要添加

using System.IO;
using System.IO.Ports;

1…在类的内部定义SerialPort com;

2…打开串口

com = new SerialPort();
com.BaudRate = 115200;
com.PortName = “COM1″;
com.DataBits = 8;
com.Open();//打开串口

3…发送数据

Byte[] TxData ={1,2,3,4,5,6,7,8 };
com.Write(TxData, 0, 8);

4…接收数据

4.1使用事件接收

this.com.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.OnDataReceived);

private void OnDataReceived(object sender, SerialDataReceivedEventArgs e)

4.2使用线程接收

接收数据启动一个线程,使其接收。

在类的内部定义

Thread _readThread;
bool _keepReading;

打开串口后启动线程

_keepReading = true;
_readThread = new Thread(ReadPort);
_readThread.Start();

线程函数

  1. private void ReadPort()
  2. {
  3. while (_keepReading)
  4. {
  5. if (com.IsOpen)
  6. {
  7. byte[] readBuffer = new byte[com.ReadBufferSize + 1];
  8. try
  9. {
  10. // If there are bytes available on the serial port,
  11. // Read returns up to ”count” bytes, but will not block (wait)
  12. // for the remaining bytes. If there are no bytes available
  13. // on the serial port, Read will block until at least one byte
  14. // is available on the port, up until the ReadTimeout milliseconds
  15. // have elapsed, at which time a TimeoutException will be thrown.
  16. int count = com.Read(readBuffer, 0, com.ReadBufferSize);
  17. String SerialIn = System.Text.Encoding.ASCII.GetString(readBuffer, 0, count);
  18. if (count != 0)
  19. //byteToHexStr(readBuffer);
  20. ThreadFunction(byteToHexStr(readBuffer,count));
  21. }
  22. catch (TimeoutException) { }
  23. }
  24. else
  25. {
  26. TimeSpan waitTime = new TimeSpan(0, 0, 0, 0, 50);
  27. Thread.Sleep(waitTime);
  28. }
  29. }
  30. }

方法二:使用C#自带的SerialPor控件。

1…在“工具箱”的“组件”中选择SerialPor控件添加。

2…设置串口并打开

serialPort1.PortName = “COM1″;

serialPort1.BaudRate = 9600;

serialPort1.Open();

3…写入数据可以使用Write或者下面的函数

serialPort1.WriteLine(str);

4…添加数据接收的事件

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)

使用中的一些常见问题

C#中SerialPort类中DataReceived事件GUI实时处理方法(来自wanglei_wan@yahoo.com.cn 的看法)
MSDN:从 SerialPort 对象接收数据时,将在辅助线程上引发 DataReceived 事件。由于此事件在辅助线程而非主线程上引发,因此尝试修改主线程中的一些元素(如 UI 元素)时会引发线程异常。如果有必要修改主 Form 或 Control 中的元素,必须使用 Invoke 回发更改请求,这将在正确的线程上执行.进而要想将辅助线程中所读到的数据显示到主线程的Form控件上时,只有通过Invoke方法来实现
下面是代码实例:

  1. private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
  2. {
  3. int SDateTemp = this.serialPort1.ReadByte();
  4. //读取串口中一个字节的数据
  5. this.tB_ReceiveDate.Invoke(
  6. //在拥有此控件的基础窗口句柄的线程上执行委托Invoke(Delegate)
  7. //即在textBox_ReceiveDate控件的父窗口form中执行委托.
  8. new MethodInvoker(
  9. /*表示一个委托,该委托可执行托管代码中声明为 void 且不接受任何参数的任何方法。 在对控件的 Invoke    方法进行调用时或需要一个简单委托又不想自己定义时可以使用该委托。*/
  10. delegate{
  11. /*匿名方法,C#2.0的新功能,这是一种允许程序员将一段完整代码区块当成参数传递的程序代码编写技术,通过此种方法可  以直接使用委托来设计事件响应程序以下就是你要在主线程上实现的功能但是有一点要注意,这里不适宜处理过多的方法,因为C#消息机制是消息流水线响应机制,如果这里在主线程上处理语句的时间过长会导致主UI线程阻塞,停止响应或响应不顺畅,这时你的主form界面会延迟或卡死      */
  12. this.tB_ReceiveDate.AppendText(SDateTemp.ToString());//输出到主窗口文本控件
  13. this.tB_ReceiveDate.Text += “ ”;}
  14. )
  15. );
  16. }

如何知道当前电脑有哪个串口

在窗体上添加一个comboBox控件。

然后使用comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());  或者

string[] portList = System.IO.Ports.SerialPort.GetPortNames();
for (int i = 0; i < portList.Length; ++i)
{
string name = portList[i];
comboBox1.Items.Add(name);
}

具体请参考http://msdn.microsoft.com/zh-tw/library/system.io.ports.serialport.getportnames.aspx