浪漫煙花之博客

Microsft Server 的一些有用的資料連結

Server管理 — 作者 yangbright @ 15:24

活动目录之用户配置文件: http://searchwin2000.techtarget.com.cn/tips/373/2173373.shtml

重新认识NTFS文件系统的妙处: http://searchwin2000.techtarget.com.cn/tips/465/2360965.shtml

提升Windows系统运行速度的八大绝招: http://searchwin2000.techtarget.com.cn/tips/397/2359397.shtml



NVL, NVL2 or COALESCE?(貼在這邊。供自己參考)

Oracle Database — 作者 yangbright @ 15:02

跟别的RDBMS系统一样,Oracle中的空值(nulls)也应该被特殊对待。在Oracle中,有3个(也许更多?)函数可以用来处理空值,NVL, NVL2 和 COALESCE。我想要问你们一个问题,但是首先我自己得先温习一下。

NVL ( expr1 , expr2 )
如果expr1是空,那么NVL返回expr2。如果expr1不是空,那么NVL返回expr1。

NVL2 ( expr1 , expr2 , expr3 )
如果expr1是空,那么NVL2返回expr3。如果expr1不是空,那么NVL返回expr2。

COALESCE(expr[,expr]…)
返回参数列表中的第一个非空值。

当然我也可以使用CASE或者DECODE函数来处理空值。

下面左右的查询都返回相同的结果:

使用NVL:

  1. HR@XE> select nvl(commission_pct,0)
  2. 2 from employees
  3. 3 where commission_pct is null
  4. 4 and rownum = 1;
  5. NVL(COMMISSION_PCT,0)
  6. ---------------------
  7. 0

使用NVL2:

  1. HR@XE> select nvl2(commission_pct,commission_pct,0)
  2. 2 from employees
  3. 3 where commission_pct is null
  4. 4 and rownum = 1;
  5. NVL2(COMMISSION_PCT,COMMISSION_PCT,0)
  6. -------------------------------------
  7. 0

使用COALESCE:

  1. HR@XE> select COALESCE(commission_pct,0)
  2. 2 from employees
  3. 3 where commission_pct is null
  4. 4 and rownum = 1;
  5. COALESCE(COMMISSION_PCT,0)
  6. --------------------------
  7. 0

使用CASE:

  1. HR@XE> select
  2. 2 case
  3. 3 when commission_pct is null then 0
  4. 4 else commission_pct
  5. 5 end commission_pct
  6. 6 from employees
  7. 7 where commission_pct is null
  8. 8 and rownum = 1;
  9. COMMISSION_PCT
  10. --------------
  11. 0

使用DECODE:

  1. HR@XE> select
  2. 2 decode(commission_pct,null, 0,
  3. 3 commission_pct) commission_pct
  4. 4 from employees
  5. 5 where commission_pct is null
  6. 6 and rownum = 1;
  7. COMMISSION_PCT
  8. --------------
  9. 0

我通常都是使用NVL函数来检查空值的,但是,看上去COALESCE函数更加普遍(可以检查多个参数)并且COALESCE是一个所有关系型数据库系统都支持的标准函数。

那么是不是我该改变一下自己使用NVL的习惯转而使用COALESCE呢?各位有什么建议?



ORACLE里锁有以下几种模式

Oracle Database — 作者 yangbright @ 09:45
0none
1null                                                    
2Row-S     行共享(RS):共享表锁  
3Row-X     行专用(RX):用于行的修改
4Share     共享锁(S):阻止其他DML操作
5S/Row-X   共享行专用(SRX):阻止其他事务操作
6exclusive 专用(X):独立访问使用
 
数字越大锁级别越高, 影响的操作越多。
 
一般的查询语句如select... from...;是小于2的锁, 有时会在v$locked_object出现。
select ... from ... for update;      2的锁。
当对话使用for update子串打开一个游标时,所有返回集中的数据行都将处于行级(Row-X)独占式锁定,
其他对象只能查询这些数据行,不能进行updatedeleteselect...for update操作。
        
insert / update / delete ... ;             3的锁。    
没有commit之前插入同样的一条记录会没有反应, 因为后一个3的锁会一直等待上一个3的锁, 
我们必须释放掉上一个才能继续工作。
 
创建索引的时候也会产生3,4级别的锁。
 
locked_mode2,3,4不影响DML(insert,delete,update,select)操作, 
DDL(alter,drop)操作会提示ora-00054错误。
        
有主外键约束时 update / delete ... ; 可能会产生4,5的锁。
        
DDL语句时是6的锁。
        
DBA角色, 查看当前数据库里锁的情况可以用如下SQL语句:
 
select object_id,session_id,locked_mode from v$locked_object;
 
select t2.username,t2.sid,t2.serial#,t2.logon_time,locked_mode,
object_id from v$locked_object t1,v$session t2 
where t1.session_id=t2.sid order by t2.logon_time;
如果有长期出现的一列,可能是没有释放的锁。
我们可以用下面SQL语句杀掉长期没有释放非正常的锁:
alter system kill session 'sid,serial#';
如果出现了锁的问题, 某个DML操作可能等待很久没有反应。      
你采用的是直接连接数据库的方式,
也不要用OS系统命令 $kill process_num或者$kill -9 process_num来终止用户连接,
因为一个用户进程可能产生一个以上的锁, OS进程并不能彻底清除锁的问题。
记得在数据库级别用alter system kill session 'sid,serial#';杀掉不正常的锁。



經典短語

生活隨想與感悟 — 作者 yangbright @ 09:43

1. 葉子的離開,是因為風的追求,還是因為樹的不挽留?

2. 看成败,人生豪迈,只不过是从头再来!



Oracle Database 10g:最佳新特性(ZT)

Oracle Database — 作者 yangbright @ 13:54

利用 Oracle Database 10g 实用工具数据移动得到了很大的提高。
迄今为止,导出/导入工具集仍是跨多个平台转移数据所需劳动强度最小的首选实用工具,尽管人们常常抱怨它速度太慢。导入只是将每条记录从导出转储文件中读出来,然后使用常见的 INSERT INTO 命令将其插入到目标表中,因此导入可能是个很慢的过程,这一点并不让人感到吃惊。
进入 Oracle Data Pump,Oracle Database 10g 中的导出/导入工具包的更新更快的同类工具,它被设计来成倍地加速这个过程。
Data Pump 反映了整个导出/导入过程的彻底革新。它不是使用常见的 SQL 命令,而是应用专用 API 来以更快得多的速度加载和卸载数据。在我的测试中,我看到导出性能比在直接模式下提高了 10-15 倍,导入过程性能提高了 5 倍。此外,与使用导出实用工具不同,它还能够只取出特定类型的对象(如过程)。
Data Pump 导出
这个新的实用工具称为 expdp,以和原来的导出 exp 区分开。在本例中,我们将用 Data Pump 来导出一个大表 CASES,大小约为 3GB。Data Pump 在服务器端使用文件处理来创建和读取文件;因此,目录作为位置使用。在这种情况下,我们将使用文件系统 /u02/dpdata1 来保存转储文件。
create directory dpdata1 as ’/u02/dpdata1’;
grant read, write on directory dpdata1 to ananda;

接下来,我们将导出数据:
expdp ananda/abc123 tables=CASES directory=DPDATA1
dumpfile=expCASES.dmp job_name=CASES_EXPORT

让我们来分析该命令的各个部分。用户 ID/口令组合、表和转储文件参数的意义是显而易见的。与原来的导出不同,文件是在服务器(不是客户端)上创建的。位置由目录参数值 DPDATA1 指定,它指向之前创建的 /u02/dpdata1。这个进程还在目录参数指定的位置上创建一个日志文件(同样在服务器上)。默认地,这个进程使用一个名称为 DPUMP_DIR 的目录;因此可以创建它来代替 DPDATA1。
注意上面的参数 job_name,这是个特殊的参数,在原来的导出中没有。所有的 Data Pump 工作都通过作业来完成。Data Pump 作业 — 与 DBMS 作业不同 — 只是服务器进程,它代表主进程处理数据。主进程(称为主控制进程)通过高级队列 (AQ) 来协调这项工作;它通过在运行期内创建的一个特殊的表(称为主表)来实现这个目的。在我们的例子中,如果您在 expdp 运行时检查用户 ANANDA 的模式 ,您将注意到一个表 CASES_EXPORT 的存在(对应参数 job_name)。当 expdp 结束时,这个表被丢弃。
导出监控
当 Data Pump Export (DPE) 运行时,按 Control-C;它将阻止消息在屏幕上显示,但不停止导出进程本身。相反,它将显示 DPE 提示符(如下所示)。进程现在被认为处于“交互式”模式:
Export>

这种方法允许在这个 DPE 作业上输入几条命令。要查看概要,在提示符下使用 STATUS 命令:
Export> status
Job:CASES_EXPORT
Operation:EXPORT
Mode:TABLE
State:EXECUTING
Degree: 1
Job Error Count: 0
Dump file:/u02/dpdata1/expCASES.dmp
bytes written = 2048

Worker 1 Status:
State:EXECUTING
Object Schema:DWOWNER
Object Name:CASES
Object Type:TABLE_EXPORT/TBL_TABLE_DATA/TABLE/TABLE_DATA
Completed Objects: 1
Total Objects: 1
Completed Rows: 4687818

记住,这只是状态显示。导出在后台工作。要继续在屏幕上查看消息,从 Export> 提示符下使用命令 CONTINUE_CLIENT。
并行操作
您可以通过 PARALLEL 参数为导出使用一个以上的线程来显著地加速作业。每个线程创建一个单独的转储文件,因此参数 dumpfile 应当拥有和并行度一样多的项目。您可以指定通配符作为文件名,而不是显式地输入各个文件名,例如:
expdp ananda/abc123 tables=CASES directory=DPDATA1
dumpfile=expCASES_%U.dmp parallel=4 job_name=Cases_Export

注意 dumpfile 参数拥有一个通配符 %U,它指示文件将按需要创建,格式将为 expCASES_nn.dmp,其中 nn 从 01 开始,然后按需要向上增加。
在并行模式下,状态屏幕将显示四个工作进程。(在默认模式下,只有一个进程是可见的。)所有的工作进程同步取出数据,并在状态屏幕上显示它们的进度。
分离访问数据文件和转储目录文件系统的输入/输出通道是很重要的。否则,与维护 Data Pump 作业相关的开销可能超过并行线程的效益,并因此而降低性能。并行方式只有在表的数量多于并行值并且表很大时才是有效的。

数据库监控

您还可以从数据库视图获得关于运行的 Data Pump 作业的更多信息。监控作业的主视图是 DBA_DATAPUMP_JOBS,它将告诉您在作业上有多少个工作进程(列 DEGREE)在工作。另一个重要的视图是 DBA_DATAPUMP_SESSIONS,当它与上述视图和 V$SESSION 结合时将给出主前台进程的会话 SID。
select sid, serial#
from v$session s, dba_datapump_sessions d
where s.saddr = d.saddr;

这条指令显示前台进程的会话。更多有用的信息可以从警报日志中获得。当进程启动时,MCP 和工作进程在警报日志中显示如下:
kupprdp:master process DM00 started with pid=23, OS id=20530 to execute -
SYS.KUPM$MCP.MAIN(’CASES_EXPORT’, ’ANANDA’);

kupprdp:worker process DW01 started with worker id=1, pid=24, OS id=20532 to execute -
SYS.KUPW$WORKER.MAIN(’CASES_EXPORT’, ’ANANDA’);

kupprdp:worker process DW03 started with worker id=2, pid=25, OS id=20534 to execute -
SYS.KUPW$WORKER.MAIN(’CASES_EXPORT’, ’ANANDA’);

它显示为数据泵操作启动的会话的 PID。您可以用以下查询找到实际的 SID:
select sid, program from v$session where paddr in
(select addr from v$process where pid in (23,24,25));

PROGRAM 列将对应警报日志文件中的名称显示进程 DM (为主进程)或 DW (为工作进程)。如果一个工作进程使用了并行查询,比如说 SID 23,您可以在视图 V$PX_SESSION 中看到它,并把它找出来。它将为您显示从 SID 23 代表的工作进程中运行的所有并行查询会话:
select sid from v$px_session where qcsid = 23;

从视图 V$SESSION_LONGOPS 中可以获得其它的有用信息来预测完成作业将花费的时间。
select sid, serial#, sofar, totalwork
from v$session_longops
where opname = ’CASES_EXPORT’
and sofar != totalwork;

列 totalwork 显示总工作量,该列的 sofar 数量被加和到当前的时刻 — 因而您可以用它来估计还要花多长时间。
Data Pump 导入
不过,数据导入性能是 Data Pump 真正出色的地方。要导入先前导出的数据,我们将使用
impdp ananda/abc123 directory=dpdata1 dumpfile=expCASES.dmp job_name=cases_import

导入进程的默认行为是创建表和所有相关的对象,然后在表已存在时产生一个错误。如果您想把数据添加到一个现有的表中,您可以在上述命令行中使用 TABLE_EXISTS_ACTION=APPEND。
和使用 Data Pump 导入一样,在进程中按 Control-C 将进入 Date Pump Import (DPI) 的交互模式;同样,提示符是 Import>。
处理特定对象
您是否有过只需要从一个用户导出特定的过程,以在一个不同的数据库或用户中重新创建这些过程的情况?与传统的导出实用工具不同,Data Pump 允许您只导出特定类型的对象。例如,以下命令让您只导出过程,而不导出其它任何东西 — 不导出表、视图、甚至函数:
expdp ananda/iclaim directory=DPDATA1 dumpfile=expprocs.dmp include=PROCEDURE

要只导出一些特定的对象 — 比如说,函数 FUNC1 和过程 PROC1 — 您可以使用
expdp ananda/iclaim directory=DPDATA1 dumpfile=expprocs.dmp
include=PROCEDURE:"=’PROC1’",FUNCTION:"=’FUNC1’"

这个转储文件充当了源对象的一个备份。您甚至可以用它来创建 DDL 脚本,以供之后使用。一个称为 SQLFILE 的特殊参数允许创建 DDL 脚本文件。
impdp ananda/iclaim directory=DPDATA1 dumpfile=expprocs.dmp sqlfile=procs.sql

该指令在 DPDATA1 指定的目录中创建一个名称为 procs.sql 的文件,并将对象的脚本包含在导出转储文件中。这种方法帮助您快速地在另一个模式中创建源对象。
利用参数 INCLUDE 允许您从转储文件中定义要包含或排除的对象。您可以使用子句 INCLUDE=TABLE:"LIKE ’TAB%’" 来仅导出那些名称以 TAB 开头的表。类似地,您可以使用结构 INCLUDE=TABLE:"NOT LIKE ’TAB%’" 来排除所有名称以 TAB 开头的表。作为另一种选择,您可以使用 EXCLUDE 参数来排除特定的对象。
通过外部表,Data Pump 还可以用来传输表空间;它非常强大,能够即时地重定义并行方式,将更多的表添加到一个现有的进程中等等(这超出了本文的范围;关于更多详细信息,请参考 Oracle Database Utilities 10g Release 1 10.1)。以下命令显示Data Pump 导出实用工具提供的所有参数的列表:
expdp help=y

类似地,impdp help=y 将显示 DPI 中的所有参数。
当 Data Pump 作业在运行时,您可以通过在 DPE 或 DPI 提示符下发出 STOP_JOB 来暂停它们,然后用 START_JOB 来重起它们。这个功能在您空间不足和想在继续执行之前进行修改时非常方便。



Tomcat worker (zt)

OAS資料 — 作者 yangbright @ 18:01

A Tomcat worker is a Tomcat instance that is waiting to execute servlets on behalf of some web server. For example, we can have a web server such as Apache forwarding servlet requests to a Tomcat process (the worker) running behind it.

The scenario described above is a very simple one; in fact one can configure multiple Tomcat workers to serve servlets on behalf of a certain web server. The reasons for such configuration can be:

  • We want different contexts to be served by different Tomcat workers to provide a development environment where all the developers share the same web server but own a Tomcat worker of their own.
  • We want different virtual hosts served by different Tomcat processes to provide a clear separation between sites belonging to different companies.
  • We want to provide load balancing, meaning run multiple Tomcat workers each on a machine of its own a nd distribute the requests between them.

There are probably more reasons for having multiple workers but I guess that this list is enough... Tomcat workers are defined in a properties file dubbed workers.properties and this tutorial explains how to work with it.

This document was originally part of Tomcat: A Minimalistic User's Guide written by Gal Shachor, but has been split off for organizational reasons.

Defining Workers

Defining workers to the Tomcat web server plugin can be done using a properties file (a sample file named workers.properties is available in the conf/ directory).

the file contains entries of the following form:

worker.list =<a comma separated list of worker names>

the list of workers

worker.list= worker1, worker2

When starting up, the web server plugin will instantiate the workers whose name appears in the worker.list property, these are also the workers to whom you can map requests.

Workers Type

Each named worker should also have a few entries to provide additional information on his behalf. This information includes the worker's type and other related worker information. Currently the following worker types that exists are (JK 1.2.5):

Defining workers of a certain type should be done with the following property format:

worker . worker name . type =<worker type> Where worker name is the name assigned to the worker and the worker type is one of the four types defined in the table (a worker name may not contain any space (a good naming convention for queue named should follow the Java variable naming rules).

Defines a worker named "local" that uses the ajpv12 protocol to forward requests to a Tomcat process.

worker.local.type=ajp12

Defines a worker named "remote" that uses the ajpv13 protocol to forward requests to a Tomcat process.

worker.remote.type=ajp13

Defines a worker named "fast" that uses JNI to forward requests to a Tomcat process.

worker.fast.type=jni

Defines a worker named "loadbalancer" that loadbalances several Tomcat processes transparently.

worker.loadbalancer.type=lb

Setting Worker Properties

After defining the workers you can also specify properties for them. Properties can be specified in the following manner:

worker.<worker name>.<property>=<property value>

ajp12 Worker properties

The ajp12 typed workers forward requests to out-of-process Tomcat workers using the ajpv12 protocol over TCP/IP sockets.

the ajp12 worker properties are :

host property set the host where the Tomcat worker is listening for ajp12 requests.

port property set The port where the Tomcat worker is listening for ajp12 requests

lbfactor property is used when working with a load balancer worker, this is the load-balancing factor for the worker. We'll see more on this in the lb worker section.

worker "worker1" will talk to Tomcat listening on machine www.x.com at port 8007 using 2.5 lb factor

worker.worker1.host=www.x.com worker.worker1.port=8007 worker.worker1.lbfactor=2.5

Notes: In the ajpv12 protocol, connections are created, used and then closed at each request. The default port for ajp12 is 8007

ajp13 Worker properties

The ajp13 typed workers forward requests to out-of-process Tomcat workers using the ajpv13 protocol over TCP/IP sockets. The main difference between ajpv12 and ajpv13 are that:

  • ajpv13 is a more binary protocol and it try to compress some of the request data by coding frequently used strings as small integers.
  • ajpv13 reuse open sockets and leaves them open for future requests (remember when you've got a Firewall between your WebServer and Tomcat).
  • ajpv13 has special treatment for SSL information so that the container can implement SSL related methods such as isSecure().

You should note that Ajp13 is now the only out-process protocol supported by Tomcat 4.0.x, 4.1.x and 5.

The following table specifies properties that the ajp13 worker can accept:

host property set the host where the Tomcat worker is listening for ajp13 requests.

port property set The port where the Tomcat worker is listening for ajp13 requests

lbfactor property is used when working with a load balancer worker, this is the load-balancing factor for the worker. We'll see more on this in the lb worker section.

cachesize property is usefull when you're using JK in multithreaded web servers such as Apache 2.0, IIS and Netscape. They will benefit the most by setting this value to a higher level (such as the estimated average concurrent users for Tomcat). If cachesize is not set, the connection cache support is disabled.

cache_timeout property should be used with cachesize to specify how to time JK should keep an open socket in cache before closing it. This property should be used to reduce the number of threads on the Tomcat WebServer.

You should know that under heavy load some WebServers, for example Apache's create many childs/threads to handle the load and they destroy the childs/threads only when the load decrease.

Each child could open an ajp13 connection if it have to forward a request to Tomcat, creating a new ajp13 thread on Tomcat side.

The problem is that after an ajp13 connection is created, the child won't drop it until killed. And since the webserver will keep its childs/threads running to handle high-load, even it the child/thread handle only static contents, you could finish having many unused ajp13 threads on the Tomcat side.

socket_keepalive property should be used when you have a firewall between your webserver and the Tomcat engine, who tend to drop inactive connections. This flag will told Operating System to send KEEP_ALIVE message on inactive connections (interval depend on global OS settings, generally 120mn), and sus prevent the firewall to cut the connection.

The problem with Firewall cutting inactive connections is that sometimes, neither webserver or tomcat have informations about the cut and couldn't handle it.

socket_timeout property told webserver to cut an ajp13 connection after some time of inactivity. When choosing an endpoint for a request and the assigned socket is open, it will be closed if it was not used for the configured time. It's a good way to ensure that there won't too old threads living on Tomcat side, with the extra cost you need to reopen the socket next time a request be forwarded. This property is very similar to cache_timeout but works also in non-cache mode.

connect_timeout property told webserver to send a PING request on ajp13 connection after connection is established. The parameter is the delay in milliseconds to wait for the PONG reply.

This features has been added in jk 1.2.6 to avoid problem with hung tomcat's and require ajp13 ping/pong support which has been implemented on Tomcat 3.3.2+, 4.1.28+ and 5.0.13+ . Disabled by default.

prepost_timeout property told webserver to send a PING request on ajp13 connection before forwarding to it a request. The parameter is the delay in milliseconds to wait for the PONG reply.

This features has been added in jk 1.2.6 to avoid problem with hung tomcat's and require ajp13 ping/pong support which has been implemented on Tomcat 3.3.2+, 4.1.28+ and 5.0.13+ . Disabled by default.

reply_timeout property told webserver to wait some time for reply to a forwarded request before considering the remote tomcat is dead and eventually switch to another tomcat in a cluster group. By default webserver will wait forever which could be an issue for you. The parameter is the number of milliseconds to wait for reply, so adjust it carrefully if you have long running servlets.

This features has been added in jk 1.2.6 to avoid problem with hung tomcat's and works on all servlet engines supporting ajp13. Disabled by default.

recovery_options property told webserver how to handle recovery when it detect that tomcat failed. By default, webserver will forward the request to another tomcat in LB mode (or to another ajp thread in ajp13 mode). values are : 0 (full recovery), 1 (don't recover if tomcat failed after getting the request), 2 (don't recover if tomcat failed after sending the headers to client), 3 (don't recover if tomcat failed getting the request or after sending the headers to client).

This features has been added in jk 1.2.6 to avoid problem with hung/broken tomcat's and works on all servlet engines supporting ajp13. Full recovery by default.

worker "worker2" will talk to Tomcat listening on machine www2.x.com at port 8009 using 3.5 lb factor

worker.worker2.host=www2.x.com worker.worker2.port=8009 worker.worker2.lbfactor=3.5

worker "worker2" use up to 10 sockets, which will stay no more than 10mn in cache

worker.worker2.cachesize=10 worker.worker2.cache_timeout=600

worker "worker2" ask operating system to send KEEP-ALIVE signal on the connection

worker.worker2.socket_keepalive=1

worker "worker2" want ajp13 connection to be dropped after 5mn (timeout)

worker.worker2.socket_timeout=300

Notes: In the ajpv13 protocol, the default port is 8009

lb Worker properties

The load-balancing worker does not really communicate with Tomcat workers. Instead it is responsible for the management of several "real" workers. This management includes:

  • Instantiating the workers in the web server.
  • Using the worker's load-balancing factor, perform weighed-round-robin load balancing where high lbfactor means stronger machine (that is going to handle more requests)
  • Keeping requests belonging to the same session executing on the same Tomcat worker.
  • Identifying failed Tomcat workers, suspending requests to them and instead fall-backing on other workers managed by the lb worker.

The overall result is that workers managed by the same lb worker are load-balanced (based on their lbfactor and current user session) and also fall-backed so a single Tomcat process death will not "kill" the entire site. The following table specifies properties that the lb worker can accept:

  • balanced_workers is a comma separated list of workers that the load balancer need to manage. These workers should not appear in the worker.list property.
  • sticky_session specifies whether requests with SESSION ID's should be routed back to the same Tomcat worker. If sticky_session is an int and is not 0 it is set to JK_TRUE and sessions are sticky, otherwise sticky_session is set to false. Set sticky_session to JK_FALSE when Tomcat is using a Session Manager which can persist session data across multiple instances of Tomcat. By default sticky_session is set to JK_TRUE.

The worker balance1 while use "real" workers worker1 and worker2

worker.balance1.balanced_workers=worker1, worker2

Advanced lb Worker properties

With JK 1.2.x, new load-balancing and fault-tolerant support has been added via 2 new properties, local_worker_only and local_worker .

Let's take an example environment:

A cluster with two nodes (worker1+worker2), running a webserver + tomcat tandem on each node and a loadbalancer in front of the nodes.

The advanced router LB worker

worker.list=router

# Define a 'local_worker' worker using ajp13

worker.worker1.port=8009 worker.worker1.host=node1.domain.org worker.worker1.type=ajp13 worker.worker1.lbfactor=1 worker.worker1.local_worker=1

# Define another 'local_worker' worker using ajp13

worker.worker2.port=8009 worker.worker2.host=node2.domain.org worker.worker2.type=ajp13 worker.worker2.lbfactor=1 worker.worker2.local_worker=0

# Define the LB worker

worker.router.type=lb worker.router.balanced_workers=worker1,worker2 worker.router.local_worker_only=1

The local_worker flag on worker1 and worker2 tells the lb_worker which connections are going to the local worker.

If local_worker is an int and is not 0 it is set to JK_TRUE and marked as local worker, JK_FALSE otherwise. If in minimum one worker is marked as local worker, lb_worker is in local worker mode. All local workers are moved to the beginning of the internal worker list in lb_worker during validation.

This means that if a request with a session id comes in it would be routed to the appropriate worker. If this worker is down it will be send to the first local worker which is not in error state.

If a request without a session comes in, it would be routed to the first local worker. If all local worker are in error state, then the 'local_worker_only' flag is important. If it was set to an int and this wasn't 0 it is set to JK_TRUE, JK_FALSE otherwise. With set to JK_TRUE, this request gets an error response. If set to JK_FALSE lb_worker tries to route the request to another balanced worker.

If one of the worker was in error state and has recovered nothing changes. The local worker will be check for requests without a session id (and with a session on himself) and the other worker will only be checked if a request with a session id of this worker comes in.

Why do we need souch a complex behavior ?

We need a graceful shut down of a node for maintenance. The balancer in front asks a special port on each node periodically. If we want to remove a node from the cluster, we switch off this port. The loadbalancer can't connect to it and marks the node as down. But we don't move the sessions to another node. In this environment it is an error if the balancer sends a request without a session to an apache+mod_jk+tomcat which port is switched off. And if the load balancer determines that a node is down no other node is allowed to send a request without a session to it. Only requests with old sessions on the switched off node would be routed to this node. After some time nobody uses the old sessions and the sessions will time out. Then nobody uses this node, because all session are gone and the node is unreachable without a session-id in the request. If someone uses a session which timed out, our servlet system sends a redirect response without a session id to the browser. This is necessary for me, because on a switched off node apache and tomcat can still be up and running, but they are in an old state and should only be asked for valid old sessions. After the last session timed out, I could update the node etc. without killing sessions or moving them to another node. Sometimes we have a lot of big objects in our sessions, so it would be really time consuming to move them.

The defaults are still local_worker: 0 and local_worker_only:0

jni Worker properties

The jni worker opens a JVM inside the web server process and executes Tomcat within it (that is in-process). Following that, messages to and from the JVM are passed using JNI method calls, this makes the jni worker faster then the out-of-process workers that need to communicate to the Tomcat workers by writing AJP messages over TCP/IP sockets.

Note: Since the JVM is multithreaded; the jni worker should be used only within multithreaded servers such as AOLServer, IIS, Netscape and Apache 2.0.
You should also make sure that the threading scheme used by the web servers match the one used to build the JK web server plugin.

Since the jni worker opens a JVM it can accept many properties that it forward to the JVM such as the classpath etc. as we can see in the following table.

class_path is the classpath as used by the in-process JVM. This should point to all Tomcats' jar/file files as well as any class or other jar file that you want to add to the JVM.

To have JSP compile support, you should remember to also add Javac to the classpath. This can be done in Java2 by adding tools.jar to the classpath. In JDK1.xx you should just add classes.zip.

The class_path property can be given in multiple lines. In this case the JK environment will concatenate all the classpath entries together by putting path delimiter (":"/";") between the entries.

Set the classpath for worker "wrkjni"

worker.wrkjni.class_path=/var/tomcat3/lib/tomcat.jar

we don't forget to add JAVAC (tools.jar)

worker.wrkjni.class_path=/opt/IBMJava2-131/lib/tools.jar

bridge indicate the kind of Tomcat you'll use via JNI.

The bridge property could be for now tomcat32 or tomcat33 . Tomcat 3.2.x is deprecated but still present on some distribution like iSeries. By default the bridge type is set tomcat33.

Set bridge type for "wrkjni", we'll use tomcat 3.3

worker.wrkjni.bridge=tomcat33

cmd_line is the command line that is handed over to Tomcats' startup code.

The cmd_line property can be given in multiple lines. In this case the JK environment will concatenate all the cmd_line entries together by putting spaces between the entries.

Set command line for "wrkjni"

worker.wrkjni.cmd_line=-config

Next arg

worker.wrkjni.cmd_line=/etc/tomcat3/conf/alt-server.xml

Very important tomcat.home

worker.wrkjni.cmd_line=-home

Location of tomcat.home

worker.wrkjni.cmd_line=/var/tomcat3

jvm_lib is the full path to the JVM implementation library. The jni worker will use this path to load the JVM dynamically.

Set full path for JVM shared lib (IBM SDK on Linux)

worker.wrkjni.jvm_lib=/opt/IBMJava2-131/jre/bin/classic/libjvm.so

Set full path for JVM shared lib (Sun SDK on Windows)

worker.wrkjni.jvm_lib=c:JDK1.3.1jrebinclassic

stdout is full path to where the JVM write its System.out

Put logs in /var/log/http/jk-jvm-out.log

worker.wrkjni.stdout=/var/log/http/jk-jvm-out.log

stderr is full path to where the JVM write its System.err

Put logs in /var/log/http/jk-jvm-err.log

worker.wrkjni.stderr=/var/log/http/jk-jvm-err.log

ms set initial HEAP size for the JVM

Told JVM to use 64MB of initial heap size

worker.wrkjni.ms=64

mx set maximal HEAP size for the JVM

Told JVM to not use more than 128MB for heap

worker.wrkjni.mx=128

sysprops set the system properties for the JVM

Told JVM to use french language

worker.wrkjni.sysprops=-Duser.region=FR

ld_path set the additional dynamic libraries path (similar in nature to LD_LIBRARY_PATH)

Told system which library path to be added to access Java Env

worker.wrkjni.ld_path=/opt/IBMJava2-131/jre/bin/ worker.wrkjni.ld_path=/opt/IBMJava2-131/jre/bin/classic

Notes: Under Linux it seems that processes can't update their own LD_LIBRARY_PATH, so you'll have to update it BEFORE launching the webserver...

Property file macros

You can define "macros" in the property files. These macros let you define properties and later on use them while constructing other properties and it's very usefull when you want to change your Java Home, Tomcat Home or OS path separator

property example, don't hardcode path separator

workers.tomcat_home=d:tomcat workers.java_home=d:sdkjdk1.2.2

Using macros we'll have : worker.inprocess.class_path=d:tomcatclasses

worker.inprocess.class_path=$(workers.tomcat_home)$(ps)classes

Using macros we'll have : worker.inprocess.class_path=d:sdkjdk1.2.2libtools.jar

worker.inprocess.class_path=$(workers.java_home)$(ps)lib$(ps)tools.jar

A sample worker.properties

Since coping with worker.properties on your own is not an easy thing to do, a sample worker.properties file is bundled along JK.

You could also find here a sample workers.properties defining :

  • An ajp12 worker that used the host localhost and the port 8007
  • An ajp13 worker that used the host localhost and the port 8008
  • A jni worker
  • A lb worker that load balance the ajp12 and ajp13 workers

# Define some properties

workers.apache_log=/var/log/httpd/ workers.tomcat_home=/var/tomcat3 workers.java_home=/opt/IBMJava2-131/ ps=/

# Define 4 workers, 3 real workers using ajp12, ajp13, jni, the last one being a loadbalancing worker

worker.list=worker1, worker2, worker3, worker4

# Set properties for worker1 (ajp12)

worker.worker1.type=ajp12 worker.worker1.host=locahost worker.worker1.port=8007 worker.worker1.lbfactor=5

# Set properties for worker2 (ajp13)

worker.worker2.type=ajp13 worker.worker2.host=locahost worker.worker2.port=8009 worker.worker2.lbfactor=50 worker.worker2.cachesize=10 worker.worker2.cache_timeout=600 worker.worker2.socket_keepalive=1 worker.worker2.socket_timeout=300

# Set properties for worker3 (jni)

worker.worker3.type=jni

# Set worker3 bridge type, here Tomcat 3.3

worker.worker3.bridge=tomcat33

# Set worker3 classpath

worker.worker3.class_path=$(workers.tomcat_home)$(ps)classes worker.worker3.class_path=$(workers.tomcat_home)$(ps)lib$(ps)tomcat.jar

# Set worker3 tomcat command line

worker.worker3.cmd_line=-home worker.worker3.cmd_line=$(workers.tomcat_home)

# Set worker3 Tomcat/JVM settings

worker.worker3.jvm_lib=$(workers.java_home)$(ps)jre$(ps)bin$(ps)classic$(ps)libjvm.so worker.worker3.stdout=$(workers.apache_log)$(ps)inprocess.stdout worker.worker3.stderr=$(workers.apache_log)$(ps)inprocess.stderr worker.worker3.sysprops=tomcat.home=$(workers.tomcat_home)

# Set properties for worker4 (lb) which use worker1 and worker2

worker.worker4.balanced_workers=worker1,worker2



在 oracle 10g 中訪問 SQL Server (2)

Oracle Database — 作者 yangbright @ 15:23

如果global_names=true的話:
大都與global_names=false相似,不同之處在於:
3.增加初始化文件:
在 %oracle_home%hsadmin下,創建一個以 init.ora 文件,內容如下:
HS_FDS_CONNECT_INFO=SQL Server_SID
HS_FDS_TRACE_LEVEL=OFF
HS_DB_NAME = SQL SERVER_SID #所有字母大寫
HS_DB_DOMAIN = YOUR_DB_DOMAIN #所有字母大寫


5.create public database link DB_NAME.DB_DOMAIN connect to user identified by ****** using 'test01';

其他的都是一樣的。

參考 :http://www.oracle.com.cn/viewthread.php?tid=33936



在 oracle 10g 中訪問 SQL Server (1)

Oracle Database — 作者 yangbright @ 09:00
如果global_name為flase的情況下,如下步驟:
1.配置 listener
SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (GLOBAL_DBNAME =sid1)
      (ORACLE_HOME = D:oracleora10g)
      (SID_NAME = sid1)
    )
    (SID_DESC =
      (PROGRAM = hsodbc)
      (SID_NAME = SQL Server_SID)
      (ORACLE_HOME = d:oracleora10g)

    )
  )

LISTENER =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
  )

注意紅色的與藍色的地方;

2.配置tnsnames.ora:
增加如下的一個tnsname:
test01 =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = SQL Server_SID)
    )
    (HS = OK)
  )
注意紅色的地方;

3.增加初始化文件:
在 %oracle_home%hsadmin下,創建一個以 init<SQL Server_SID>.ora 文件,內容如下:
HS_FDS_CONNECT_INFO=SQL Server_SID
HS_FDS_TRACE_LEVEL=OFF

4.重新啟動 listener

5.create public database link link_name connect to user identified by ****** using 'test01';

6.這樣就可以了。

說明:
(1). SQL Server_SID 為創建的訪問 SQL Server 的 odbc 的名稱;
(2). listener 中的program 為什麼要用 hsodbc,還沒有分析出來;
(3). 其他的與 9i 的基本上沒有什麼區別


描述人生之經典短信

生活隨想與感悟 — 作者 yangbright @ 09:44
人生就像火車,愛情停停走走,朋友去去留留,有人中途途下車,有人半路上車,多少人在你的生命列車中與你擦肩而過,但隻有知心朋友留到最後。

Java新手入門的30個基本概念

Java學習資料 — 作者 yangbright @ 08:55

  在我们学习Java的过程中,掌握其中的基本概念对我们的学习无论是J2SE,J2EE,J2ME都是很重要的,J2SEJava的基础,所以有必要对其中的基本概念做以归纳,以便大家在以后的学习过程中更好的理解java的精髓,在此我总结了30条基本的概念。

  Java概述:

  目前Java主要应用于中间件的开发(middleware)---处理客户机于服务器之间的通信技术,早期的实践证明,Java不适合pc应用程序的开发,其发展逐渐变成在开发手持设备,互联网信息站,及车载计算机的开发.Java于其他语言所不同的是程序运行时提供了平台的独立性,称许可以在windows,solaris,linux其他操作系统上使用完全相同的代码.Java的语法与C++语法类似,C++/C程序员很容易掌握,而且Java是完全的彻底的面向对象的,其中提出了很好的GC(Garbage Collector)垃圾处理机制,防止内存溢出。

  Java的白皮书为我们提出了Java语言的11个关键特性。

(1)   Easy:Java的语法比C++的相对简单,另一个方面就是Java能使软件在很小的机器上运行,基础解释其和类库的支持的大小约为40kb,增加基本的标准库和线程支持的内存需要增加125kb

(2)   分布式:Java带有很强大的TCP/IP协议族的例程库,Java应用程序能够通过URL来穿过网络来访问远程对象,由于servlet机制的出现,使Java编程非常的高效,现在许多的大的web server都支持servlet

(3)   OO:面向对象设计是把重点放在对象及对象的接口上的一个编程技术.其面向对象和C++有很多不同,在与多重继承的处理及Java的原类模型。

(4)   健壮特性:Java采取了一个安全指针模型,能减小重写内存和数据崩溃的可能型。

(5)   安全:Java用来设计网路和分布系统,这带来了新的安全问题,Java可以用来构建防病毒和防攻击的System.事实证明Java在防毒这一方面做的比较好。

(6)   中立体系结构:Java编译其生成体系结构中立的目标文件格式可以在很多处理器上执行,编译器产生的指令字节码(Javabytecode)实现此特性,此字节码可以在任何机器上解释执行。

(7)   可移植性:Java中对基本数据结构类型的大小和算法都有严格的规定所以可移植性很好。

(8)   多线程:Java处理多线程的过程很简单,Java把多线程实现交给底下操作系统或线程程序完成.所以多线程是Java作为服务器端开发语言的流行原因之一。

(9)   Appletservlet:能够在网页上执行的程序叫Applet,需要支持Java的浏览器很多,applet支持动态的网页,这是很多其他语言所不能做到的。

1.      OOP中唯一关系的是对象的接口是什么,就像计算机的销售商她不管电源内部结构是怎样的,他只关系能否给你提供电就行了,也就是只要知道can or not而不是how and why.所有的程序是由一定的属性和行为对象组成的,不同的对象的访问通过函数调用来完成,对象间所有的交流都是通过方法调用,通过对封装对象数据,很大限度上提高复用率。

2.      OOP中最重要的思想是类,类是模板是蓝图,从类中构造一个对象,即创建了这个类的一个实例(instance)

3.