2008年9月25日星期四

escape analysis 和 lock elision

Escape analysis 是检查所有引用的作用域, 如果一个引用只是在一个本地作用域内,没有escape到更大的作用域, JIT编译成本地代码的时候会进行实时优化。
比如最重要的一个就是锁擦除 lock elision.
如果escape analysis发觉这个引用只在一个本地作用域(局部变量),这表示只有在当前作用域的线程才有可能访问这个锁,在这种情况下永远不可能有别的线程进入这个作用域和当前线程竞争,所以这种情况下这个锁可以被消除,这就是lock elision.

比如这段代码:
public String concatBuffer(String s1, String s2) {
StringBuffer sb = new StringBuffer();
sb.append(s1);
sb.append(s2);
return sb.toString();
}

这种情况下StringBuffer对象的作用域就这这个方法内,所以StringBuffer完全没有必要线程安全加锁(当然更好的做法是用StringBuilder,不要依赖于聪明但是有时候行为不可预料的编译器和JIT/JRE.), 所以escape analysis结果表示可以优化,lock elision这种情况下就可以发生。

以下是测试程序
package test.thread;

public class LockElisionTest {

public static void main(String[] args) {
long t1 = System.currentTimeMillis();
LockElisionTest obj = new LockElisionTest();
for (int i = 0; i < 10000000; i++) {
obj.concatBuffer("1", "2");
}
long t2 = System.currentTimeMillis();
System.out.println(t2 - t1);
}

public String concatBuffer(String s1, String s2) {
StringBuffer sb = new StringBuffer();
sb.append(s1);
sb.append(s2);
return sb.toString();
}
}


注意的是是-XX:+DoEscapeAnalysis默认没有打开,而且你需要用-server模式

结果JRE5没有打开escape analysis是3500毫秒
JRE6打开是2100毫秒,关闭2200毫秒左右(估计因为还有别的优化)

Java Biased Lock 实验

今天神舟七号升天,不知道是不是去成都的飞机都受影响,19:50的飞机改到23:20,在机场无聊,写篇博客吧

什么是biased lock?
Biased Locking is a class of optimizations that improves uncontended synchronization performance by eliminating atomic operations associated with the Java language’s synchronization primitives.

有些时候一个线程多次获得对象锁的操作中,理论上这些操作可以合并在一起,而减少lock/unlock的时间。不过这样会导致对其他线程的不公平,所以叫biased lock.通常是对第一个获得锁的线程偏心。

禁止:-XX:-UseBiasedLocking
使用:JRE6默认使用,或者显式使用-XX:+UseBiasedLocking
以下是我的测试程序,在JRE6上使用biased lock只需要500毫秒左右,而使用JRE5则需要5500毫秒左右,快10倍以上。
奇怪的是JRE6上禁止biased lock之后貌似性能没有什么变化,如果你打印一些调试信息(关闭注释System.out.println("T" + id + " holds lock")那行)你会发现仍然是biased lock,知道一个线程结束才释放锁。

package test.thread;

import java.util.concurrent.CountDownLatch;

public class BiasedLockTest {

public static volatile Long t1 = System.nanoTime();
static {
System.out.println(t1);
}
public static volatile Long t2;

public static void main(String[] args) throws InterruptedException {

Object lock = new Object();

TestThread[] threads = new TestThread[100];
CountDownLatch latch = new CountDownLatch(threads.length);

for (int i = 0; i < 100; i++) {
threads[i] = new TestThread(i, lock, latch);
}
for (int i = 0; i < 100; i++) {
threads[i].start();
}

for (int i = 0; i < 100; i++) {
threads[i].join();
}
System.out.println(t2);
System.out.println( (t2 - t1) / 10e5);
}
}


class TestThread extends Thread {
final private int id;
final private Object lock;
final private CountDownLatch latch;

public TestThread(int id, Object lock, CountDownLatch latch) {
this.id = id;
this.lock = lock;
this.latch = latch;
}
public void run() {
for(int i = 0; i < 10000; i++) {
synchronized (lock) {
int k = 0;
k=k+1;//dummy calculation
}
// System.out.println("T" + id + " holds lock");
}
BiasedLockTest.t2 = System.nanoTime();
latch.countDown();
// System.out.println("T" + id + " dies");
}
}

2008年9月23日星期二

把金山词霸添加到google bar按钮查询

安装了google金山词霸合作版之后,今天查了几个词都没有查到,觉得很差劲。我甚至尝试性搜索了一个最简单的gonna都查不到,一气之下反安装了。突然想起iciba.com还是不错的,我又用google bar,能不能做一个按钮呢?
首先随便添加任何一个google button,然后选项里点edit, advanced editor, 把内容换成这个
<custombuttons xmlns="http://toolbar.google.com/custombuttons/">
<button>
<title>iciba</title>
<description>www.iciba.com/</description>
<icon mode="base64" type="image/x-icon">
iVBORw0KGgoAAAANSUhEUgAAABEAAAAQCAMAAADH72RtAAAAAXNSR0IArs4c6QAAAARnQU1BAACx
jwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAwBQTFRF
AAAAgAAAAIAAgIAAAACAgACAAICAgICAwMDA/wAAAP8A//8AAAD//wD/AP//////AAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAzAABmAACZAADMAAD/ADMAADMzADNmADOZADPMADP/AGYAAGYzAGZmAGaZAGbM
AGb/AJkAAJkzAJlmAJmZAJnMAJn/AMwAAMwzAMxmAMyZAMzMAMz/AP8AAP8zAP9mAP+ZAP/MAP//
MwAAMwAzMwBmMwCZMwDMMwD/MzMAMzMzMzNmMzOZMzPMMzP/M2YAM2YzM2ZmM2aZM2bMM2b/M5kA
M5kzM5lmM5mZM5nMM5n/M8wAM8wzM8xmM8yZM8zMM8z/M/8AM/8zM/9mM/+ZM//MM///ZgAAZgAz
ZgBmZgCZZgDMZgD/ZjMAZjMzZjNmZjOZZjPMZjP/ZmYAZmYzZmZmZmaZZmbMZmb/ZpkAZpkzZplm
ZpmZZpnMZpn/ZswAZswzZsxmZsyZZszMZsz/Zv8AZv8zZv9mZv+ZZv/MZv//mQAAmQAzmQBmmQCZ
mQDMmQD/mTMAmTMzmTNmmTOZmTPMmTP/mWYAmWYzmWZmmWaZmWbMmWb/mZkAmZkzmZlmmZmZmZnM
mZn/mcwAmcwzmcxmmcyZmczMmcz/mf8Amf8zmf9mmf+Zmf/Mmf//zAAAzAAzzABmzACZzADMzAD/
zDMAzDMzzDNmzDOZzDPMzDP/zGYAzGYzzGZmzGaZzGbMzGb/zJkAzJkzzJlmzJmZzJnMzJn/zMwA
zMwzzMxmzMyZzMzMzMz/zP8AzP8zzP9mzP+ZzP/MzP///wAA/wAz/wBm/wCZ/wDM/wD//zMA/zMz
/zNm/zOZ/zPM/zP//2YA/2Yz/2Zm/2aZ/2bM/2b//5kA/5kz/5lm/5mZ/5nM/5n//8wA/8wz/8xm
/8yZ/8zM/8z///8A//8z//9m//+Z///M////RGKwUAAAAKpJREFUKFNNzrEKAjEMBuCKBSlXzLsJ
t/VRQo9b9B18g3Pr1Ew39RG6dXRXHG4Sirmz1f6hFD6SEBFjxPL44wiGDDmsWmWDpRHsIONtGE6/
Htw/8OwdXGydwq7TKTmA8VD2sBgA71IrEiB5Z5oe5KY0jtN/KqCUUoNWnDkK3hPwStSbxDTnTZ6k
uHpz1DN8JdDrzlkJqMi6QaneWLIs7yXsqBYfLibbhg/4ACM/k1kU4ql2AAAAAElFTkSuQmCC
</icon>
<search>http://www.iciba.com/{query}</search>
</button>
</custombuttons>

就行了,如果要换图标去这里生成base64
http://www.motobit.com/util/base64-decoder-encoder.asp

替换<icon>就可以了

现在你在google bar搜索框写进去一个单词,比如gonna然后点击词霸的图标看看结果如何?

2008年9月21日星期日

CentOS 安装 Subversion

1. 下载collabnet subversion server rpm包
2. 安装rpm包rpm -iv client then server
3. 创建启动脚本 as /etc/init.d/svnserve

#!/bin/bash
#
# /etc/rc.d/init.d/svnserve
#
# Starts the Subversion Daemon
#
# chkconfig: 345 90 10
# description: Subversion Daemon

# processname: svnserve

source /etc/rc.d/init.d/functions

[ -x /usr/bin/svnserve ] || exit 1

# To pass additional options (for instace, -r root of directory to server) to
# the svnserve binary at startup, set OPTIONS here.
#
OPTIONS="-r /svn"
RETVAL=0
prog="svnserve"
desc="Subversion Daemon"

start() {
echo -n $"Starting $desc ($prog): "
daemon $prog -d $OPTIONS
RETVAL=$?
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
echo
}

stop() {
echo -n $"Shutting down $desc ($prog): "
killproc $prog
RETVAL=$?
[ $RETVAL -eq 0 ] && success || failure
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
return $RETVAL
}

case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
RETVAL=$?
;;
condrestart)
[ -e /var/lock/subsys/$prog ] && restart
RETVAL=$?
;;
*)
echo $"Usage: $0 {start|stop|restart|condrestart}"
RETVAL=1
esac

exit $RETVAL

添加启动脚本到run level 3 和 5
[root@alpha init.d]# chkconfig --add svnserve
[root@alpha init.d]# chkconfig --level 35 svnserve on


现在启动客户端比如svn tortoise,browse repository就可以了

CentOS 安装 apache http server 2.2

1. download apache httpd source
2. unzip it to /opt/httpd/httpd-2.2.9
3. cd /opt/httpd-2.2.9, 执行 "./configure --prefix="/opt/httpd-2.2.9"
4. make
5. make install
6. bin/apachectl start,然后打开首页 http://192.168.0.100/, it should show "it works"
7. bin/apachectl stop

你也可以编译安装到其他路径,但是你不可以移动已经编译好的apache httpd

ref:
http://httpd.apache.org/docs/2.0/install.html#configure


8. 作为服务安装在runlevel 3

cd /etc/init.d
vi appachehttpd, 加入以下内容
#!/bin/bash
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
#
http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
# Startup script for the Apache Web Server
#
# chkconfig: - 85 15
# description: Apache is a World Wide Web server. It is used to serve \
# HTML files and CGI.
# processname: httpd
# pidfile: /var/run/httpd.pid
# config: /etc/httpd/conf/httpd.conf
# Source function library.
. /etc/rc.d/init.d/functions
if [ -f /etc/sysconfig/httpd ]; then
. /etc/sysconfig/httpd
fi
# This will prevent initlog from swallowing up a pass-phrase prompt if
# mod_ssl needs a pass-phrase from the user.
INITLOG_ARGS=""
# Set HTTPD=/usr/sbin/httpd.worker in /etc/sysconfig/httpd to use a server
# with the thread-based "worker" MPM; BE WARNED that some modules may not
# work correctly with a thread-based MPM; notably PHP will refuse to start.
# Path to the apachectl script, server binary, and short-form for messages.
apachectl=/usr/local/apache/bin/apachectl
httpd=${HTTPD-/usr/local/apache/bin/httpd}
prog=httpd
RETVAL=0
# check for 1.3 configuration
check13 () {
CONFFILE=/usr/local/apache/conf/httpd.conf
GONE="(ServerType|BindAddress|Port|AddModule|ClearModuleList|"
GONE="${GONE}AgentLog|RefererLog|RefererIgnore|FancyIndexing|"
GONE="${GONE}AccessConfig|ResourceConfig)"
if grep -Eiq "^[[:space:]]*($GONE)" $CONFFILE; then
echo
echo 1>&2 " Apache 1.3 configuration directives found"
echo 1>&2 " please read @docdir@/migration.html"
failure "Apache 1.3 config directives test"
echo
exit 1
fi
}
# The semantics of these two functions differ from the way apachectl does
# things -- attempting to start while running is a failure, and shutdown
# when not running is also a failure. So we just do it the way init scripts
# are expected to behave here.
start() {
echo -n $"Starting $prog: "
check13 || exit 1
daemon $httpd $OPTIONS
RETVAL=$?
echo
[ $RETVAL = 0 ] && touch /var/lock/subsys/httpd
return $RETVAL
}
stop() {
echo -n $"Stopping $prog: "
killproc $httpd
RETVAL=$?
echo
[ $RETVAL = 0 ] && rm -f /var/lock/subsys/httpd /var/run/httpd.pid
}
reload() {
echo -n $"Reloading $prog: "
check13 || exit 1
killproc $httpd -HUP
RETVAL=$?
echo
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status $httpd
RETVAL=$?
;;
restart)
stop
start
;;
condrestart)
if [ -f /var/run/httpd.pid ] ; then
stop
start
fi
;;
reload)
reload
;;
graceful|help|configtest|fullstatus)
$apachectl $@
RETVAL=$?
;;
*)
echo $"Usage: $prog {start|stop|restart|condrestart|reload|status|fullstatus|graceful|help|configtest}"
exit 1
esac
exit $RETVAL

注意文件中有三处主要的地方需要修改下的:
apachectl=/usr/local/apache/bin/apachectl
httpd=${HTTPD-/usr/local/apache/bin/httpd}
CONFFILE=/usr/local/apache/conf/httpd.conf

然后
chkconfig --add apachehttpd
如果你要运行在多个runlevel,比如3和5
chkconfig --level 35 apachehttpd on

附各个run level:

* rc0.d - System Halted
* rc1.d - Single User Mode
* rc2.d - Single User Mode with Networking
* rc3.d - Multi-User Mode - boot up in text mode
* rc4.d - Not yet Defined
* rc5.d - Multi-User Mode - boot up in X Windows
* rc6.d - Shutdown & Reboot


确认安装:
cd /etc/rc.d/rc3.d
you should see S85apachehttpd
cat S85apachehttpd
should show you the script

reboot and you should see the web page

2008年9月19日星期五

资源管理器里添加DOS和Cygwin Bash命令行到右键上下文菜单


1. 添加DOS命令行到右键点击目录的上下文菜单
添加注册表
[HKEY_CLASSES_ROOT\Directory\shell\cmd]
默认值:Open Command Line
[HKEY_CLASSES_ROOT\Directory\shell\cmd\command]
默认值:cmd.exe /k "cd %L"

2. 添加Cygwin Bash命令行到右键点击目录的上下文菜单
add c:\Tools\cygwin\bin to %PATH%
然后 添加注册表
[HKEY_CLASSES_ROOT\Directory\shell\cygwin]
默认值:Open Cygwin Bash
[HKEY_CLASSES_ROOT\Directory\shell\cygwin\command]
默认值:c:\Tools\cygwin\bin\bash.exe --login -c "cd '%1' ; exec /bin/bash -rcfile ~/.bashrc"

对于配置cygwin bash上下文菜单更多内容请看http://www.mindview.net/Etc/Cygwin/BashHere

有了cygwin的一个主要好处是可以把windows dos 命令行和unix style的命令结合一起用,比如:
$ netstat -nao | grep 139
TCP 16.158.65.15:139 0.0.0.0:0 LISTENING 4
TCP 192.168.116.1:139 0.0.0.0:0 LISTENING 4
TCP 192.168.199.1:139 0.0.0.0:0 LISTENING 4

如果只用dos会很麻烦的事情,所以我现在在windows下也是用cgywin

2008年9月18日星期四

这个缺乏诚信的年代,还是不喝牛奶为妙

完了,我喝了不知道多少光明的牛奶的,估计在我国也没有办法索赔了
以后怎么办呢?还是不喝牛奶算了。不知道以后还能不能吃米饭,白菜?

液态奶检出三聚氰胺的批次表
公司 序号 生产企业 产品名称 规格型号 商标 生产日期/批次 三聚氰胺(mg/kg)
蒙牛 1 蒙牛(武汉)友芝友乳业有限公司 核桃牛奶 200ml/袋 友芝友 20080910 0.765
2 内蒙古蒙牛乳业(集团)股份有限公司 蒙牛高钙低脂牛奶 250ml/盒 蒙牛 2008.08.07 0.8
3 内蒙古蒙牛乳业(集团)股份有限公司 全脂灭菌纯牛乳 250ml/盒 蒙牛 2008.09.01 1.0
4 内蒙古蒙牛乳业(集团)股份有限公司 高钙低脂牛奶 250ml/盒 蒙牛 2008.08.01 1.5
5 内蒙古蒙牛乳业(集团)股份有限公司 早餐奶(麦香味) 250ml/包 蒙牛 20080814 1.9
6 内蒙古蒙牛乳业(集团)股份有限公司 蒙牛早餐奶 250ml/盒 蒙牛 2008.07.26/x 2.57
7 内蒙古蒙牛乳业(集团)股份有限公司 妙点 250ml/盒 蒙牛 20080728/W206 3.17
8 蒙牛乳业(北京)有限责任公司 木糖醇酸牛奶 2kg/瓶 蒙牛 20080806 3.52
9 内蒙古蒙牛乳业(集团)股份有限公司 高钙低脂牛奶 243ml(250g)/袋 蒙牛 20080908/C206/GAfb 4.2
10 蒙牛乳业(马鞍山)有限公司 蒙牛大粒果实酸牛奶 160克/盒 蒙牛 M20080903 6.8(A样)
11 蒙牛乳业(马鞍山)有限公司 蒙牛大粒果实酸牛奶 160克/盒 蒙牛 M20080903 7(B样)
伊利 1 济南伊利乳业有限责任公司 伊利芒果+黄桃酸牛奶 125g/盒 伊利 2008.09.07 0.69
2 内蒙古伊利实业集团股份有限公司 酸牛奶(木瓜+甜橙) 125g/瓶 伊利 20080903 1.02
3 内蒙古伊利实业集团股份有限公司 纯牛奶 220ml/袋 伊利 2008.09.13 2.2
4 内蒙古伊利实业集团股份有限公司 脱脂奶 250ml/盒 伊利 20080820 2.9
5 内蒙古伊利实业集团股份有限公司 纯牛奶 220ml/袋 伊利 20080905MIAC6 5.5
6 内蒙古伊利实业集团股份有限公司 纯牛奶 242ml/袋 伊利 20080906/LIA09 8
7 内蒙古伊利实业集团股份有限公司 高钙低脂奶 250ml/盒 伊利 20080819 8.4
光明 1 北京光明健能乳业有限公司 光明酸牛奶(原味) 180g/袋 光明 2008.09.12 0.6
2 武汉光明乳品有限公司 原味酸牛奶 180g/盒 光明 2008-09-13 3.41
3 北京光明健能乳业有限公司 原味酸牛奶 100克/杯 光明 20080910A 3.5
4 北京光明健能乳业有限公司 大颗果粒草莓酸奶 450克/盒 光明 20080902BC 4.8
5 光明乳业有限责任公司 益生菌·优乳酪(原味) 190g/罐 光明 B20080908C 5.65
6 北京光明健能乳业有限公司 优酪乳·酸牛奶(原味) 580克/瓶 光明 B20080909A 8.6

2008年9月17日星期三

SSL 单向双向认证配置实例 - HP OpenView Service Manager和Tomcat

0. 如果没有openssl预装,那么你需要自己下载并编译,如果java -version是gnu的,那么要下载并安装Sun的JRE,最好是JDK
1. 下载源代码http://www.openssl.org/source/
2. 我使用CentOS5.2其他Linux/unix操作系统应该类似,以root身份登录
3. 把source解压缩到安装路径,比如/opt/openssl
4. 进入目录编译
./config --prefix=/opt/openssl
5. 安装
make test
make install

配置openssl.cnf
找到openssl.cnf
[root@arsenal14 /]# find / -name openssl.cnf
/etc/pki/tls/openssl.cnf
然后加入你自己的country state等等:

生成自签名的CA根证书
首先生成CA的private key:
[root@arsenal14 tmp]# openssl genrsa -des3 -out ca.pem 2048
Generating RSA private key, 2048 bit long modulus
...............................................................................................................................+++
......................+++
e is 65537 (0x10001)
Enter pass phrase for ca.pem:
Verifying - Enter pass phrase for ca.pem:

然后用这个private key生成CA根证书
[root@arsenal14 tmp]# openssl req -new -key ca.pem -x509 -days 1095 -out ca.cer
Enter pass phrase for ca.pem:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [CN]:
State or Province Name (full name) [Shanghai]:
Locality Name (eg, city) [Shanghai]:
Organization Name (eg, company) [Hewlett Packard]:
Organizational Unit Name (eg, section) []:GDCC-SMCi
Common Name (eg, your name or your server's hostname) []:arsenal14.asiapacific.hpqcorp.net
Email Address []:daniel.woo@hp.com
注意机器名一定要是这台机器的FDQN

到此为止,我们看看当前目录都有了哪些东西:
[root@arsenal14 tmp]# ls
ca.cer CA根证书
ca.pem CA private key (重要!保密!)

下面是一个真是用例,比如我们要把一台tomcat和一台HP OpenView ServiceManager(下文简称SM)建立mutal authentication.
我们需要
1. 建立一个CA
2. 分别创建tomcat和SM的private/public key pair
3. CA签发tomcat和SM的证书
4. 导入CA证书到tomcat和SM的信任keystore


现在为了做mutual authentication我们还需要对SM和tomcat分别生成private key和证书,然后把证书通过CA签发。

生成SM的private/public key pair[root@arsenal14 tmp]# keytool -genkey -alias smserver -keystore sm.jks
Enter keystore password:
Re-enter new password:
What is your first and last name?
[Unknown]: tsmcivm8
What is the name of your organizational unit?
[Unknown]:
What is the name of your organization?
[Unknown]:
What is the name of your City or Locality?
[Unknown]:
What is the name of your State or Province?
[Unknown]:
What is the two-letter country code for this unit?
[Unknown]: CN
Is CN=tsmcivm8, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=CN correct?
[no]: y

Enter key password for
(RETURN if same as keystore password):



生成tomcat的private/public key pair

[root@arsenal14 tmp]# keytool -genkey -alias tomcat -keystore tomcat.jks
Enter keystore password:
Re-enter new password:
What is your first and last name?
[Unknown]: danielnc6400.asiapacific.hpqcorp.net
What is the name of your organizational unit?
[Unknown]:
What is the name of your organization?
[Unknown]:
What is the name of your City or Locality?
[Unknown]:
What is the name of your State or Province?
[Unknown]:
What is the two-letter country code for this unit?
[Unknown]: CN
Is CN=danielnc6400.asiapacific.hpqcorp.net, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=CN correct?
[no]: y

Enter key password for
(RETURN if same as keystore password):
Re-enter new password:


现在多了两个包含private/public key的keystore:
sm.jks 和 tomcat.jks

我们从中导出两个待签发的证书(只包含public key)
sm_req.crs 和 tomcat_req.crs

[root@arsenal14 tmp]# keytool -certreq -alias smserver -keystore sm.jks -file sm_req.crs
Enter key store password: password

[root@arsenal14 tmp]# keytool -certreq -alias tomcat -keystore tomcat.jks -file tomcat_req.crs
Enter key store password: password


然后我们要用CA根证书签发出一个SM的证书,发布给其他系统
[root@arsenal14 tmp]# openssl x509 -req -days 365 -in sm_req.crs -CA ca.cer -CAkey ca.pem -CAcreateserial -out sm.cer
Signature ok
subject=/CN=tsmcivm8/O=HP/OU=GDCC-SMCi/L=Shanghai/ST=Shanghai/C=CN
Getting CA Private Key
Enter pass phrase for ca.pem:

然后我们要用CA根证书签发出一个tomcat的证书,发布给其他系统
[root@arsenal14 tmp]# openssl x509 -req -days 365 -in tomcat_req.crs -CA ca.cer -CAkey ca.pem -CAcreateserial -out tomcat.cer
Signature ok
subject=/CN=danielnc6400.asiapacific.hpqcorp.net/O=HP/OU=GDCC-SMCi/L=Shanghai/ST=Shanghai/C=CN
Getting CA Private Key
Enter pass phrase for ca.pem:


现在又多了两个文件,两个sign好的证书sm.cer 和 tomcat.cer

我们有了这些文件:
ca.cer 根证书
ca.pem 根证书private key
ca.srl
sm.cer 已经签名的sm证书
sm.jks sm server keystore
sm.pem sm private key
sm_req.crs 没用了
tomcat.cer 已经签名的tomcat证书
tomcat.jks tomcat server keystore
tomcat.pem tomcat private key
tomcat_req.crs 没用了

现在把signed好的证书导回keystore
但是之前你必须把CA的根证书导入
[root@arsenal14 tmp]# keytool -cacert -file ca.cer -keystore sm.jks
[root@arsenal14 tmp]# keytool -cacert -file ca.cer -keystore tomcat.jks


然后才能导入CA签发好的证书
keytool -import -file sm.cer -keystore sm.jks -alias smserver
keytool -import -file tocmat.cer -keystore tomcat.jks -alias tomcat

先测试tomcat的单向服务器认证
把tomcat.jks复制到tomcat/conf下
打开tomcat/conf/server.xml,更改https的connector配置
先测试单向tomcat服务器端验证(不要求客户上传验证客户端证书)
minSpareThreads="2" maxSpareThreads="15"
enableLookups="true" disableUploadTimeout="true"
acceptCount="100" maxThreads="100"
scheme="https" secure="true" SSLEnabled="true"
keystoreFile="C:/Projects/Tomcat6SM/conf/tomcat.jks" keyAlias="tomcat" keystorePass="password"
clientAuth="false" sslProtocol="TLS"/>

启动tomcat, log应该有
2008-9-18 23:24:38 org.apache.coyote.http11.Http11Protocol start
信息: Starting Coyote HTTP/1.1 on http-443

从FireFox3这个时候访问https://danielnc6400.asiapacific.hpqcorp.net你应该看到这个内容



这是因为你不信任这个证书,下一步我们需要把根证书导入FireFox的trust keystore
Tools->Option->Advanced->Encryption->View Certificates->authorities->Import



导入之后你可以查看所有已经导入的证书



IE直接访问会弹出对话框问你是否信任
IE证书导入更简单,直接double click ca.cer安装根证书
然后再次打开这个URL你会发现IE不在有任何提示,因为IE信任这个根证,所以也信任根证书签发的tomcat的证书。

接下来配置SM的单向server认证
复制sm.jks 到SM安装路径的RUN/security目录下
修改sm.ini如下(sm -helpssl可以显示所有参数的意义)
# SSL configuration
ssl:0
ssl_reqClientAuth:0
sslConnector:1
httpsPort:13443

#
# Certificates
truststoreFile:security/sm.jks
truststorePass:password
keystoreFile:security/sm.jks
keystorePass:password

重新启动服务

然后到客户端打开Windows->Preferences->HP Service Manager->Security
把包含CA根证书的那个keystore全路径写在CA Certificate file里.这里是为了能让客户端验证服务器上的证书是否有效。不过奇怪的是这里没有输入访问keystore的密码的地方,eclipse client怎么打开keystore还是个迷。:-)

然后新建一个链接,hostname一定要填写域名,第二页要勾上Use SSL Encryption,现在你就可以连接上SM了

这个单向配置都没有问题了,我们来尝试把SM和tomcat做mutual authentication
由于双方trust keystore里面都信任ca.cer所以理论上讲现在是自动支持的。

打开SM做个实验,打开Script Library
创建个JS脚本
var url = "https://danielnc6400.asiapacific.hpqcorp.net/index.html";
var headers = new Array();
//headers.push("Authorization: Basic " + base64Encode("administrator:admblabla"));
var resp = doHTTPRequest( "GET", url, headers, null, 10, 10, 10 );
print(resp);

执行脚本输出是:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<body>
This is a test
</body>
</html>

结束

MySQL Master-Slave Replication

MySQL Master-Slave Replication

Offical reference
http://dev.mysql.com/doc/refman/5.0/en/replication.html

简化步骤:
1. download
mySQL for centOS5 (RHEL5)建议intel cc编译的这个版本,建议下载5.1版本,6.0的falcon性能并不比innoDB好
Linux (non RPM, Intel C/C++ compiled, glibc-2.3) downloads
配置默认网关:/etc/sysconfig/network
配置dhcp或者静态IP在/etc/network-scripts/ifcfg-eth0, 1, 2...
配置dns hostname在/etc/resolv.conf

2. 如果已经有了mysql那么先 rpm -ev mysql
然后关闭iptables防火墙

[root@arsenal14 mysqlM]# chkconfig --list iptables
iptables 0:off 1:off 2:on 3:on 4:on 5:on 6:off
[root@arsenal14 mysqlM]# service iptables save
Saving firewall rules to /etc/sysconfig/iptables: [ OK ]
[root@arsenal14 mysqlM]# service iptables stop
Flushing firewall rules: [ OK ]
Setting chains to policy ACCEPT: filter [ OK ]
Unloading iptables modules: [ OK ]
[root@arsenal14 mysqlM]# chkconfig iptables off
[root@arsenal14 mysqlM]# chkconfig --list iptables
iptables 0:off 1:off 2:off 3:off 4:off 5:off 6:off


3. 创建用户
groupadd mysql
useradd -g mysql mysql
passwd mysql

4. 解开压缩包然后复制到三份,master-slave-slave
cp -r mysql* /opt/mysqlM
cp -r mysql* /opt/mysqlS0
cp -r mysql* /opt/mysqlS1
到/opt下执行
chown -R mysql *
chgrp -R mysql *
到mysqlM,和另外两个数据库下执行
scripts/mysql_install_db --user=mysql
chown -R mysql data
chgrp -R mysql data

5. 启动主数据库
./bin/mysqld_safe --user=mysql &
然后测试数据库状态:
[root@arsenal14 mysqlM]# bin/mysqladmin version
bin/mysqladmin Ver 8.42 Distrib 5.1.26-rc, for redhat-linux-gnu on i686
Copyright (C) 2000-2006 MySQL AB
This software comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to modify and redistribute it under the GPL license

Server version 5.1.26-rc
Protocol version 10
Connection Localhost via UNIX socket
UNIX socket /tmp/mysql.sock
Uptime: 1 min 13 sec

Threads: 1 Questions: 1 Slow queries: 0 Opens: 15 Flush tables: 1 Open tables: 8 Queries per second avg: 0.13
关闭数据库 ./mysqladmin shutdown
创建配置文件,把support-files里的my-medium.conf复制到mysqlM/my.cnf
更改一些参数,比如
port=4306
socket=/tmp/mysqlM.sock
collation_server=utf8_unicode_ci
character_set_server=utf8
打开innoDB的配置等

然后用这个命令行启动mysql:
mysqld_safe --defaults-file=/opt/mysqlM/my.cnf --user=mysql

用ping看看数据库状态
[root@arsenal14 mysqlM]# bin/mysqladmin --defaults-file=/opt/mysqlM/my.cnf ping
mysqld is alive

如果你需要用root通过远程客户端登录,你需要enable mysql 的root remote login
[root@arsenal14 mysqlM]# bin/mysql --defaults-file=/opt/mysqlM/my.cnf
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 5.1.26-rc-log MySQL Community Server (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION;
Query OK, 0 rows affected (0.00 sec)

mysql> exit
Bye
然后你就可以用toad for mysql了

6. 配置两个slave数据库
[root@arsenal14 mysqlM]# cp my.cnf ../mysqlS0
[root@arsenal14 mysqlM]# cp my.cnf ../mysqlS1
然后只要改端口和sock文件不要重复,innoDB数据文件路径不重复,pid file 不重复就可以了
建议改成
port=5306
socket = /tmp/mysqlS.sock
innodb_data_home_dir = /opt/mysqlS0/data/
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = /opt/mysqlS0/data/
pid-file=/opt/mysqlS0/pid


port = 6306
socket = /tmp/mysqlS1.sock
innodb_data_home_dir = /opt/mysqlS1/data/
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = /opt/mysqlS1/data/
pid-file=/opt/mysqlS1/pid


检查是否可以启动,查看err日志
[root@arsenal14 mysqlS0]# bin/mysqld_safe --defaults-file=/opt/mysqlS0/my.cnf --user=mysql &

[root@arsenal14 mysqlS1]# bin/mysqld_safe --defaults-file=/opt/mysqlS1/my.cnf --user=mysql &


7. 准备知识
现在才开始真正配置master-slave,有些基础知识要知道
1. master-slave之间使用master的数据库日志来让slave知道master发生了什么
2. 除了master-slave模式,mySQL现在cluster也是免费的了
3. mySQL proxy 是一个代理组件,上面可以运行mysql load balancer
4. mysql load balancer的好处:
4.1 自动排除掉同步失败或者落后的slave
4.2 修复后同步正常的slave可以自动加入
4.3 把读取分布转发到集群内任何一台服务器
4.4 写不可以分发
4.5 保持各个数据库链接数平均

8. 配置主数据库
先关闭数据库 ./mysqladmin shutdown
在master上创建同步用的用户,我用了root偷懒

接下来要master打开日志,并标识一个ID
[mysqld]
log-bin=mysql-bin
server-id=1
innodb_flush_log_at_trx_commit=1
sync_binlog=1
binlog-do-db=test

9. 配置一个slave数据库

指定一个id
[mysqld]
server-id=2
master-host =arsenal14.asiapacific.hpqcorp.net
master-user =mysqlrep
master-password =password
master-port =4036
replicate-do-db=test

10.配置master-slave
如果master已经有了数据,那么你要停止master的数据操作,先dump到slave保持一致才能开始replication

mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000010 | 106 | | |
+------------------+----------+--------------+------------------+
1 row in set (0.01 sec)


这里bin 日志是000006,偏移量是106,记下来这个数据

在命令行下导出master的数据
./bin/mysqldump --defaults-file=/opt/mysqlM/my.cnf --all-databases --lock-all-tables >dbdump.db
然后倒入到slave中。
./bin/mysql -h master <>最后在slave配置目标master
这里应该是
mysql> STOP SLAVE;
Query OK, 0 rows affected (0.01 sec)
mysql> change master to master_host='arsenal14.asiapacific.hpqcorp.net', master_port=4306, master_user='mysql', master_password='password', master_log_file='mysql-bin.000010', master_log_pos=106;
Query OK, 0 rows affected (0.02 sec)

好了,重新启动slave,然后对master新建一个表看看,不行的话要改配置需要先删除data/maseter.info,然后再执行上面的sql
然后你可以看到第三条数据是自动复制过来的,貌似create table没有正常复制过来,自己创建了table之后数据就复制过来了,钱两行因为没有表所以丢失了
mysql复制有两种,statement和record的,DDL比如创建表同步这个问题需要看一下
我又重新做了测试,这次DDL也可以同步了,数据也是正确的。刚才的问题一直没有再次重现,比较奇怪。