存档

‘$Programming’ 分类的存档

DBCP连接池(一):原理与基本配置

2010年1月29日 Killman 没有评论

大约在半年前,曾经帮同事解决过一个Commons-dbcp连接池的问题。当时遇到的问题比较诡异,但是其实并不是什么特别复杂的问题,了解DBCP的原理,大部分问题就迎刃而解了。本文主要对连接池的基本原理以及dbcp的实现方式做一个分析,对dbcp的配置参数结合原理做一个简单解释。

连接池扼要

JDBC是一套通用的Java语言与多种数据库(文件)通讯的标准API。大部分针对数据库服务器(例如Oracle, MySQL等等)的JDBC实现都是基于TCP/IP连接的客户端-服务器端通讯方式。

当我们需要执行一个数据库操作时,有下面三步:

  1. 客户端与服务器之间建立一个数据库连接
  2. 执行某种数据库操作
  3. 断开连接

如果每次处理都要走上面的三步,则应用程序与数据库服务器都要将大量的时间和资源消耗在数据连接的断开与建立上。对于并发较大的系统,建立一次连接然后缓存起来连续使用,直到程序结束等情况下再释放连接,就能够将系统资源集中在对数据库操作的处理上,从而大大提高性能。通常情况下将数据连接的建立和断开委托给一种能够数据库连接池的组件或服务进行管理。而DBCP, C3p0, Proxool等都是常用的开源的连接池组件。

就好像A公司在郊外,他们公司附近没有出租车。如果A公司有人要出去办事,他必须打电话给出租公司订车,用完车后他还要付账报销。 这样每个人出去一趟都必须订车、退车和报销。员工的很多时间白白花费在这上面了。于是A公司跟出租车公司定了一个合同,出租车公司给了他们一个车队。要用车随时去楼下找车队就可以了,用完了也不必结帐,A公司统一跟出租车公司订车和结帐。这个车队就好比连接池,由公司(应用程序)来统一向出租车公司(数据库服务器)订车(建立连接)和退车(关闭连接)。

DBCP的配置参数以及背后的原理

Commons-dbcp连接池的配置参数比较多,也比较复杂,主要分为

  • Jdbc连接参数(username, password, url, driverClassName, connectionProperties )
  • 事务处理参数 (defaultAutoCommit, defaultReadOnly, defaultTransactionIsolation, defaultCatalog)
  • 连接池参数(详见下文)
  • 连接池中链接存活性测试参数(详见下文)
  • 预处理查询池化参数(poolPreparedStatements, maxOpenPreparedStatements)
  • 丢弃失效链接相关参数(详见下文)以及一个控制是否可以正常情况下处于访问连接池包装下的底层JDBC链接参数(accessToUnderlyingConnectionAllowed)

其中Jdbc链接参数、事务处理都跟连接池关系不大,另预处理查询池化参数本文不详细叙述。有关commons-dbcp的详细参数配置信息请参考官方文档

连接池的配置

再用车队来比喻,出租车公司每提供一辆车给A公司,A公司肯定要付出一定费用。这时候维持车队的大小就很重要了,在项目少用车少的时候,车队肯定要减少,不然很多空闲车辆也要付出成本;在项目多用车多的时候,肯定要扩大车队,不然车不够用,车队忙不过来。A公司可以简单地设地两个阀值来动态调节车队中空闲的车辆数目以满足动态需求,一个是最小空闲车辆数(最小空空闲连接数(minIdle),当剩余的空车数目小于该数目时,A公司就向出租车公司请求加入新车。 一个是最大空闲车辆数(maxIdle),当剩余的车大于该数目时,就将刚刚用用完的车还给出租车公司从而减少车队数量。

另外,这家出租车公司可能要为多个客户服务,要考虑能够提供给A公司的最大的车数量,不能超过某个数量(maxActive)。所以A公司想出租车申请新车时首先要看下当前正在用的车辆数目是否超过了这个最大数目,如果没有超过那就直接申请新车,否则可以让申请者(应用程序中执行请求的线程)等待 (maxWait<=0, 无限等待; maxWait>0 当等待时间超过 maxWait时,失败)。

在连接池中,这几个参数是十分重要的,官方的说明如下,是我们调节系统性能时需要认真考虑的值。


Parameter Default Description
initialSize 0 The initial number of connections that are created when the pool is started.

Since: 1.2
线程池启动时初始化的连接数
maxActive 8 The maximum number of active connections that can be allocated from this pool at the same time, or non-positive for no limit.
最大活动连接数,如果非正整数,则不做限制。
maxIdle 8 The maximum number of connections that can remain idle in the pool, without extra ones being released, or negative for no limit.
最大空闲连接数。
minIdle 0 The minimum number of connections that can remain idle in the pool, without extra ones being created, or zero to create none.
最小空闲连接数。
maxWait indefinitely The maximum number of milliseconds that the pool will wait (when there are no available connections) for a connection to be returned before throwing an exception, or -1 to wait indefinitely.
(在没有连接可用时)连接池等待一个数据连接可用时的以毫秒计的最大等待时间,超时以后抛出异常, -1 则将无限等待

实际上,Dbcp 依赖于 commons-pool 来存储连接对象。 BasicDataSource默认使用GenericObjectPool来管理连接对象。除了请求的线程会在请求和返回连接过程中影响池中连接实例外,另有一个跑着GenericObjectPool.Evictor类型 (implements Runnable) 的实例的线程,也会影响池中的数据库连接。

请继续阅读下一篇:《DBCP连接池(二):Commons-pool的设计》

My Vimrc File

2009年12月24日 Killman 没有评论

Apply the recommend vimrc file:

cp /usr/share/vim/vimcurrent/vimrc_example.vim  /usr/share/vim/vimrc

~/.vimrc: Keep it simple!

" 设置文件编码检测类型及支持格式
 set fencs=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936
 
 "显示行号
 set nu!
 
 " 中文帮助
 if version > 603
 set helplang=cn
 endi
 
 " 设置代码自动缩进
 :set cindent
 
 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 " cscope setting (from http://easwy.com/blog/archives/advanced-vim-skills-cscope/)
 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 if has("cscope")
   set csprg=/usr/bin/cscope
   set csto=1
   set cst
   set nocsverb
   " add any database in current directory
   if filereadable("cscope.out")
       cs add cscope.out
   endif
   set csverb
 endif
 
 nmap <C-@>s :cs find s <C-R>=expand("<cword>")<CR><CR>
 nmap <C-@>g :cs find g <C-R>=expand("<cword>")<CR><CR>
 nmap <C-@>c :cs find c <C-R>=expand("<cword>")<CR><CR>
 nmap <C-@>t :cs find t <C-R>=expand("<cword>")<CR><CR>
 nmap <C-@>e :cs find e <C-R>=expand("<cword>")<CR><CR>
 nmap <C-@>f :cs find f <C-R>=expand("<cfile>")<CR><CR>
 nmap <C-@>i :cs find i ^<C-R>=expand("<cfile>")<CR>$<CR>
 nmap <C-@>d :cs find d <C-R>=expand("<cword>")<CR><CR>
分类: Tools & Tips 标签:

Arguments on Java & C++

2009年12月23日 Killman 没有评论

The Hypertable Team claimed they choose C++ to be Hypertable implement language for performance issues. They gave two points about that, Hypertable is memory (malloc) intensive and and CPU intensive. They also say:

(Hadoop)There are some places where Java is sub-optimal. In particular, at scale, there will be considerable memory pressure in the Namenode of the DFS. Java is a poor choice for this type of memory hungry application. Another place where the use of Java is sub-optimal is the post-map sorting in preparation for the reduce phase. This is CPU-intensive and involves the type of CPU work that Java is not good at.

There are a bunch comments on the Wiki Page. Someone gave another views. A guy gave two links to support Java is not so bad.

Some interesting comparative articles.

http://www.ddj.com/cpp/184401976?pgno=1

http://www.idiom.com/~zilla/Computer/javaCbenchmark.html

分类: c/c++, java 标签:

My Ubuntu Installation log

2009年12月18日 Killman 没有评论

业余使用Ubuntu好些年了,装了删删了装的,为了以后方便,把这次的新版本的安装配置过程都记录下来。

第一步,从官方下载 Ubuntu-desktop。

第二步,在VMWare上安装,并安装VMWare-tools。 在ubuntu-desktop-9.10上,不像以前需要手工安装一些包,安装linux头文件,这次一路回车就搞定了。

到这里系统就算安装完毕,发现已经用去了8G硬盘的 37%。

(update 2009-12-28): 事后发现根本没有装好,再次尝试安装,基本上各个模块编译时都会出现error日志,并报告模块没有成功编译。而原来在 ubuntu 8.10下是工作正常的。 为什么升级到 ubuntu 9.10就出错了呢?一开始在网络上搜索,看过 VMware workstation fails after 9.0.4 upgrade to 9.10, 根据该帖建议去打补丁, 但是都没有解决。

后来,去Vmware官方找了下是否有更新,结果发现 VMware Workstationfor Windows 出了新的6.5.3版本, 在 Release Notes 中发现 Ubuntu 9.04 is fully supported. 猜测也许是需要新版本。 尝试下载新版本安装后,重新安装和配置 vmware-tools, 一切顺利!

第三步,安装我需要的各种软件。

0. 设置source.list,我使用 mirrors.163.com.
设置网卡:

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
address 192.168.1.126
netmask 255.255.255.0
gateway 192.168.1.1

#auto eth0
#iface eth0 inet dhcp

1. 安装 vim/ctags/cscope, 设置颜色,缩进等。 The details are noted at Here.

  • install: sudo apt-get install vim
  • Install Chinese vim help: download from http://vimcdoc.sourceforge.net/, tar and enter the directory, execute
  • sudo ./vimcdoc.sh -i
  • sudo apt-get install exuberant-ctags cscope

2. 安装 JDK/C++工具:

sudo apt-get install sun-java6-jdk sun-java6-source
sudo apt-get install build-essential

3. 安装manuals:

开发用的手册页:

sudo apt-get install manpages-dev

安装 Posix 相关的手册页。pthread 库相关的手册页就在这里面,而不在 Dev manual pages 中。

sudo apt-get install manpages-posix manpages-posix-dev

4. 安装版本工具 Subversion 和 Git:

sudo apt-get install subversion subversion-tools git-doc git-core

5. Configure SSH server:

sudo apt-get install openssh-server

.
6. Install LAMP server by tasksel, and configure;
7. 中文支持。我安装系统时用的是英文,因此 LANG=’en_US.UTF-8′。中文输入遵循下面三步骤即可:

  1. Install Simple Chinese Language support.
  2. install: sudo apt-get install scim scim-pinyin
  3. System->Administration->Language Support->Input Method, select scim.
    1. Reboot system, 此时就可以使用智能拼音了。

Resource: SCIM Setup, SCIM Usage

中文问题的解决没有这么简单,还存在下面的问题:

  • gedit不能打开中文文件: 这个文件主要是gedit猜测编码的机制造成的,略加修改就可以。具体参考这里
  • vim不能打开中文文件:Here
  • pdf不能阅读某些中文文件: 问题的症状是能够阅读某些中文pdf,但是还有一些pdf则表现为乱码。问题的原因不太清楚,但是Google后安装了一个新包 poppler-data,就解决了。(sudo apt-get install poppler-data)

8. 安装 CHM 格式文档查看工具 kchmviewer.

sudo apt-get install kchmviewer

但是 kchmviewer 在查看 boost中文文档页时出现了编码错误。当然这不一定就是kchmviewer有问题,也可能是boost中文文档本身的兼容性等。于是另外安装了chmsee, chmsee的另外一个优点就是安装时体积很小,下载过程中才下了几百K。当然也可能是因为我提前把其他需要的库都已经装上了…
9. ruby gems:

sudo apt-get install rubygems1.9.1

10. 声音问题的解决:这里

分类: Tools & Tips 标签:

Cygwin下使用公钥登录SSH

2009年12月2日 Killman 没有评论

为了直接使用公钥登录SSH,而不使用密码登录Cygwin,费了老大劲,很长时间以来一直没有成功。此前,一直是按照网络上流传的方法,主要是生成key,然后设置到 authorized_keys中。遵照官方的命令,修改sshd_config, ssh_config, 但是一直没有奏效(不过遵照这些方法,在Ubuntu等系统上配置成功)。

昨天偶然在这个页面上看到 ssh-user-config 命令,试了试,就成功了!各位设置不成功的同学,考虑使用下这个命令,然后一路回车确认即可。

另一篇重要的参考文章:这里

顺便记录下在探索 SSH使用公钥登录过程中学到的几个sshd相关的命令:

# debug more information 
ssh  -vvv  localhost
 
#start services
net start sshd
#or
cygrunsrv  --start  sshd
 
#login command for user name that has space
ssh  Mickey\  mouse@127.0.0.1
 
#copy publickey to remote host
king@king:~$ cat .ssh/id_dsa.pub | ssh master "cat - >> ~/.ssh/authorized_keys"
#copy publickey from remote host
king@king:~$  ssh master "cat .ssh/id_dsa.pub" | cat - >> ~/.ssh/authorized_keys"

在某些情况下,必须使用代理登录SSH服务器。connect.c is the simple relaying command to make network connection via SOCKS and https proxy. It is mainly intended to be used as proxy command of OpenSSH. You can make SSH session beyond the firewall with this command.

在Windows下,只需要下载connect.exe到c:/windows,然后在 ~/.ssh/config中添加如下配置:

ProxyCommand connect -S x.x.x.x:x %h %p

connect.c 还支持 https 代理,真不赖。

分类: server & system 标签:

细节背后:为什么线程协作之前必须先获得锁?

2009年10月3日 Killman 没有评论

为什么Object.wait()/notify()/notifyAll() 之前必须获得锁? 这是JLS的规定。Wait-notify机制是围绕监控器锁进行的,获得锁是很自然的前提,自身没有拿到锁之前,怎么能够尝试去操作靠锁来调控的线程呢?不过今天偶尔有时间,就看下Sun Hotspot是怎么实现这一机制的。

当我们执行下面的代码时,线程会抛出异常java.lang.IllegalMonitorStateException: current thread not owner。

public class WaitNotifyCompilerCode {
	private String aString = "Hello World!";
 
	public static void main(String[] args) {
		System.out.println("Execute start ....");
		final WaitNotifyCompilerCode w = new WaitNotifyCompilerCode();
		w.wait1SecAndPrintString();
		System.out.println("Execute end ....");
	}
 
	public void wait1SecAndPrintString() {
		try {
			this.wait(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(aString);
	}
 
}

异常栈的信息如下:

Exception in thread "main" java.lang.IllegalMonitorStateException: current thread not owner
	at java.lang.Object.wait(Native Method)
	at com.feihoo.test.waitnotify.WaitNotifyCompilerCode.wait1SecAndPrintString(WaitNotifyCompilerCode.java:35)
	at com.feihoo.test.waitnotify.WaitNotifyCompilerCode.main(WaitNotifyCompilerCode.java:27)

深入查看 OpenJDK的源码,找到 Object.wait() 函数本地代码:

JVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms))
  JVMWrapper("JVM_MonitorWait");
  Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
  assert(obj->is_instance() || obj->is_array(), "JVM_MonitorWait must apply to an object");
  JavaThreadInObjectWaitState jtiows(thread, ms != 0);
  if (JvmtiExport::should_post_monitor_wait()) {
    JvmtiExport::post_monitor_wait((JavaThread *)THREAD, (oop)obj(), ms);
  }
  ObjectSynchronizer::wait(obj, ms, CHECK);
JVM_END

重点看倒数第二行,调用的函数如下面的代码:

// NOTE: must use heavy weight monitor to handle wait()
void ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
  if (UseBiasedLocking) {
    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
  }
  if (millis < 0) {
    TEVENT (wait - throw IAX) ;
    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
  }
  ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj());
  DTRACE_MONITOR_WAIT_PROBE(monitor, obj(), THREAD, millis);
  monitor->wait(millis, true, THREAD);

而上面的代码中最后一行的函数里,在做实际操作之前调用了下面的宏:

// A macro is used below because there may already be a pending
// exception which should not abort the execution of the routines
// which use this (which is why we don't put this into check_slow and
// call it with a CHECK argument).
 
#define CHECK_OWNER()                                                             \
  do {                                                                            \
    if (THREAD != _owner) {                                                       \
      if (THREAD->is_lock_owned((address) _owner)) {                              \
        _owner = THREAD ;  /* Convert from basiclock addr to Thread addr */       \
        _recursions = 0;                                                          \
        OwnerIsThread = 1 ;                                                       \
      } else {                                                                    \
        TEVENT (Throw IMSX) ;                                                     \
        THROW(vmSymbols::java_lang_IllegalMonitorStateException());               \
      }                                                                           \
    }                                                                             \
  } while (false)
分类: $Performance, java 标签: , ,

Weblogic 81Sp3

2009年5月14日 Killman 没有评论

Weblogic 81Sp3 发布时遇到如下错误:

&lt;2009-5-14 下午05时2920秒 CST&gt; &lt;Warning&gt; &lt;Deployer&gt; &lt;BEA-149004&gt; &lt;Failures were detected while initiating Deploy task for application receive.&gt;
&lt;2009-5-14 下午05时2920秒 CST&gt; &lt;Error&gt; &lt;Deployer&gt; &lt;BEA-149201&gt; &lt;Failed to complete the deployment task with ID 0 for the application receive.
weblogic.management.ApplicationException:
Exception:weblogic.management.ApplicationException: prepare failed for receive
Module: receive Error: Could not load receive: java.lang.StringIndexOutOfBoundsException: String index out of range: -1
 
at weblogic.management.deploy.slave.SlaveDeployer$ActivateTask.createContainer(SlaveDeployer.java:2398)
at weblogic.management.deploy.slave.SlaveDeployer$ActivateTask.prepare(SlaveDeployer.java:2310)
at weblogic.management.deploy.slave.SlaveDeployer.processPrepareTask(SlaveDeployer.java:866)
at weblogic.management.deploy.slave.SlaveDeployer.prepareDelta(SlaveDeployer.java:594)
at weblogic.management.deploy.slave.SlaveDeployer.prepareUpdate(SlaveDeployer.java:508)
at weblogic.drs.internal.SlaveCallbackHandler$1.execute(SlaveCallbackHandler.java:25)
at weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:219)
at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:178)
--------------- nested within: ------------------
weblogic.management.ManagementException:  - with nested exception:
[weblogic.management.ApplicationException:
Exception:weblogic.management.ApplicationException: prepare failed for receive
Module: receive Error: Could not load receive: java.lang.StringIndexOutOfBoundsException: String index out of range: -1
]
at weblogic.management.deploy.slave.SlaveDeployer$ActivateTask.prepare(SlaveDeployer.java:2327)
at weblogic.management.deploy.slave.SlaveDeployer.processPrepareTask(SlaveDeployer.java:866)
at weblogic.management.deploy.slave.SlaveDeployer.prepareDelta(SlaveDeployer.java:594)
at weblogic.management.deploy.slave.SlaveDeployer.prepareUpdate(SlaveDeployer.java:508)
at weblogic.drs.internal.SlaveCallbackHandler$1.execute(SlaveCallbackHandler.java:25)
at weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:219)
at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:178)

错误原因是Spring 2.5.5 与Weblogic 81之间不兼容造成的。
详细看这里

Doc: Deployment error on Weblogic 8.1 SP1/SP2 due to manifest issues – upgrade to SP6 required

分类: server & system 标签:

Vim 快捷键

2009年5月10日 Killman 没有评论

查找

这里有篇介绍文章:VIM下,在文件及目录中查找字符串的方法 。例如: vimgrep /登录/g **/*.html

查找的结果会显示在 QuickList 列表中。对于Quicklist 的操纵,参考下面的文章 打造自己的VIM: QuickFix 編譯視窗 。 这篇文章还介绍了打造快捷键,因为我的Vim使用的版本比较多,而且直接切换到Qucik List然后使用行移动也很方便的,所以就不配置这些快捷键。 更详细的参考见官方手册 Quickfix 或者 :help quickfix

替换 

可以在 vim 中查看帮助 :help argdo

示例:

:args **/*.htm

:argdo %s/旧/新/ge  |  update

翻页

整页翻页 ctrl-f ctrl-b
f就是forword b就是backward

翻半页
ctrl-d ctlr-u
d=down u=up

滚一行
ctrl-e ctrl-y

zz 让光标所杂的行居屏幕中央
zt 让光标所杂的行居屏幕最上一行 t=top
zb 让光标所杂的行居屏幕最下一行 b=bottom

分类: Tools & Tips 标签:

Google搜索使用快捷键

2009年5月9日 Killman 没有评论

Google 搜索支持快捷键,对于只用键盘的人们是十分重要的。

Navigate search results quickly and easily, minimizing use of your mouse. Current keyboard shortcuts include:

Key Action
J Selects the next result.
K Selects the previous result.
O Opens the selected result.
<Enter> Opens the selected result.
/ Puts the cursor in the search box.
<Esc> Removes the cursor from the search box.

默认情况下,谷歌中国的搜索是支持快捷键的,但是 Google.com 不支持。要打开对快捷键的支持,你需要去下面的页面去激活快捷键功能。http://www.google.com/experimental/index.html

参考:

http://www.showsing.net/logs/google-search-of-shortcuts.html

分类: Tools & Tips 标签:

安装Sybase SQL Anywhere 7.02后Path路径丢失

2009年4月30日 Killman 没有评论

今天下午,安装完成Sybase SQL Anywhere 7.02后,按照提示重新启动。重新启动以后,发现很多程序启动不了。一查环境变量,Path变量竟然变成了

D:\software\sybaseASA7\SQLAnywhere7\win32;D:\software\sybaseASA7\Shared\win32;D:\software\sybaseASA7\Shared\Sybase Central 4.0\java

后悔莫及。于是从网上找找有没有备份的工具,没有找到,倒是找到一个环境变量编辑器:Windows Environment Variables Manager 。 这个东西的好处就是编辑变量更加方便些,尤其是像Path那样的路径。详细可以参考它主页上的图片。这个软件可以将环境变量保存到某个文件中。 如果能够做成TaskSchedule,在以后都定时自动备份到某个位置,就再也不用担心环境变量丢失的问题了。

我还发现了个不错的功能,就是如果发现指定的环境变量路径不存在时,会标红表示。

capture.JPG

分类: database 标签: