Hycz's Blog

Life is a game. Why so serious?

Monthly Archives: June 2011

2011/06/29 难道论文这样写?

今天李葆春教授来实验室交流,他的presentation题目是<<Seen As Stable Marriages>>,介绍了一个关于stable matching的新用法,将stable matching的方法和optimization的方法做了比较。话说我觉得他的鸟文肯定讲的比中文好。

重点不在于他的主题,而是他的presentation的组织方法。虽然是介绍一个方法,但是他从一个男女配对的故事入手,引出了主题,然后用两个用例,VM迁移,和content ISP与eyeball ISP,介绍了他的方法的用法。这个presentation来自于一篇已经发表的paper,不过不是full paper,两个用例只留下了一个,但无论如何,他的方法有个故事。这让我想到了另一篇paper,Lamport写的<<The Part-Time Parliament>>,也就是那篇Paxos算法的原始论文,那篇论文也是用了一个故事作为引子。同学研究算法,老师也是让他为自己的算法想出一个故事。《算法导论》中的算法也都是有相应的故事作为依托,比如动态规划,贪心算法等

看来研究算法或方法时,还是需要一个好的故事,让算法生动起来,并且让别人看到算法或方法的使用价值。

Advertisements

2011/06/28 BigTable中与Cassandra中的数据模型比较

一、Cassandra中的典型数据结构

二、BigTable中与Cassandra中的数据模型比较

BigTable中的数据模型更加像是建立在关系型数据库的表之上的,一个KeySpace就类似于从前的一个Table。所不同的是,BigTable中加入了几个新的特点:

1,按列存储,对于稀疏表更加友好;

2,Column Family,翻译过来就是列族,其实呢,就是把几个关联性强的列储存在一起,这个概念既是逻辑上的,也是物理上的,但是使用者其实并不需要太过关心于Column Family,设计时也不会从Column Family开始

3,历史数据,这里像是借鉴了数据库概念中的时态数据库(Temporal Database),保留了一个column中的历史数据,于是引入了timestamp。

所以呢,BigTable的数据模型更像是这样:

其中的值部分可能是稀疏的,但是按列存储避免了稀疏大表的资源浪费。

Cassandra中的数据模型更加像是建立在BigTable之上,然后加入了一个SuperColumn的概念。然后无论是网上流传的Cassandra中的数据模型使用方法,还是《Cassandra The Definitive Guide》中所介绍的数据模型部分,似乎都与BigTable中的数据模型迥异了,原本的BigTable还有与传统的Table的类比之处,如KeySpace与Table,Column与Column,但是在Cassandra中,KeySpace类似于Application,ColumnFamily类似于Table。个人觉得原因有两个:

1,由于引入了SuperColumn的概念,使得数据模型从BigTable中的KeySpace->Key->ColumnFamily->Column,变成了KeySpace->Key->ColumnFamily->Column或者KeySpace->Key->ColumnFamily->SuperColumn->SubColumn,于是数据维数上升了,而且变得不确定了,有时4维有时5维的数据模型就缺少一个通用的使用方法。虽然SuperColumn的引入丰富了整个数据模型,但是我认为由于原本的四维数据模型已经足够简约和使用,SuperColumn只能算作锦上添花,而且由于Cassandra本身功能不够强大,如果使用SuperColumn回来带来一些问题,例如索引问题,条件搜索的实现更加困难。

2,Cassandra的固有实现问题。可能在一开始的时候,Cassandra的开发人员对BigTable的模型理解就有偏差(这里并没有对不对的问题,只是与更广泛的理解略有不同),所以KeySpace的实现就不是当做一个Table来实现的,所以才会出现早期版本中必须重启整个Cassandra集群才能添加新KeySapce的情况,在后来的版本中,多KeySpace也并不被鼓励。

所以,Cassandra的数据模型更像是这样:

如图中所示,虽然这是一个KeySpace,但是这个KeySpace实际上是被切成了几份,Key虽然看似是同等的地位,但是实际上是分别专用于不同的ColumnFamily,并不能通用,他们的命名方式也各不相同。总的来说,这也是一个稀疏的大表,只不过空洞部分更加集中(图中XX部分),而有意义的ColumnFamily中(着色部分)空洞则少得多。而由于按列存储的机制,确实使得ColumnFamily看起来更像一个Table了。

比较BigTable和Cassandra中的数据模型,二者其实很相似,如果真的愿意的话,实际上可以互相转化。不过针对BigTable的设计更偏重于以row为单位,一个row中的内容可以非常丰富,而针对Cassandra的设计更偏重于以ColumnFamily为单位,KeySpace的意义被淡化了。

2011/06/23 2PC和现实业务处理

看了一篇2004年的博文(地址:http://www.eaipatterns.com/ramblings/18_starbucks.html),作者从架构师的角度分析了starbucks的业务流程,然后将其与2PC做了下比较,虽然是04年的文章,但是还是很有启发性。

现实中的业务流程往往是同步加异步的模式,同步的部分是收银员,那里有一定的程序必须得按顺序完成,当订单下了之后,便进入异步的业务处理,这样既可以灵活的调整各个部分的服务能力,也不会浪费资源。2PC虽然过程很简单,但是由于在业务完成前,无论是服务者还是客户都不能离开,这降低了整体的效率,浪费了很多资源。

一个简单的例子是我亲身经历的,那就是麦当劳和肯德基,在麦当劳中,使用的是同步加异步的策略,收银员接受订单,然后把订单放到一边,然后就接受下个人的订单,另有员工按照订单把食物手机好给客户,于是各司其职,收银员不够那就加收银员,后面的订单处理不够那就加订单处理人员,虽然会出现由于食物没做出来而使后下订单的人先拿到食物,但是这只是很小的问题。相对的,肯德基的策略更像2PC,策略很简单,一个员工既要收钱,也要去收集食物,排队的客户必须等前面的人拿到食物才能轮到自己,虽然正在服务的客户感觉很好,但是对服务者来说,花费了大量的时间在不用业务的转换上,各个业务的专业性也不够,对客户来说,本可以下完订单就去干自己的事,比如洗个手,坐着等,但是实际上却需要站着等待所有队伍前面的人的服务时间。

另一个例子是google的架构,那篇文章的作者就是google的架构师,因而那篇文章的思想与google的策略十分相似。众所周知,google的架构是主从模式,为了防止主节点成为瓶颈,google做了大量的优化,实际上,主节点处理的就是同步的部分,每个业务的开始都需要与主节点通信,然后真正处理的,是从节点,这部分的处理就是异步的部分,这里的处理跟业务到来的顺序没有必然关系,而是跟各个业务的特点和实际内容有关。

所以,2pc可能看起来很美,而且简单,但是真的使用的话,可能需要高超的技巧,不然很容易成为一场灾难。同步加异步的方法恐怕是更为有效的方案

2011/06/20-21 在Eclipse中配置Cassandra_3

9. cassandra-cli在Eclipse中的配置

服务端搞定之后,接下来配置客户端,先分析bin版本中bin目录下的cassandra-cli.bat,有这么一段

:okClasspath
REM Include the build\classes\main directory so it works in development
set CASSANDRA_CLASSPATH=%CLASSPATH%;"%CASSANDRA_HOME%\build\classes\main";"%CASSANDRA_HOME%\build\classes\thrift"
goto runCli

说明在开发环境中,客户端的classpath需要”%CASSANDRA_HOME%\build\classes\main”和”%CASSANDRA_HOME%\build\classes\thrift”这两个地址,同样的,我们在Eclipse项目中加入以上地址,在Properties->Java Build Path->Libraries点Add Class Folder,加入这两个地址。这样就能成功运行客户端了。

客户端其实是个命令行控制的程序,具体的入口是org.apache.cassandra.cli.CliMain。

10.jline在Windows下的Eclipse中不能正常运行的问题

在Eclipse中虽然运行了cli,但是Eclipse中运行cli会直接跳到了结束,虽然出现了cli启动时的输出,但是还没等输入命令cli就已经中止了(terminated)。那么就一步步运行看看,发现之所以会结束,问题出在下面的代码

String prompt;
        String line = "";
        String currentStatement = "";
        boolean inCompoundStatement = false;

        while (line != null)
        {
            prompt = (inCompoundStatement) ? "...\t" : getPrompt(cliClient);

            try
            {
                line = reader.readLine(prompt);
            }
            catch (IOException e)
            {
                // retry on I/O Exception
            }

            if (line == null)
                return;

            line = line.trim();

            // skipping empty and comment lines
            if (line.isEmpty() || line.startsWith("--"))
                continue;

            currentStatement += line;

            if (line.endsWith(";") || line.equals("?"))
            {
                processStatement(currentStatement);
                currentStatement = "";
                inCompoundStatement = false;
            }
            else
            {
                currentStatement += " "; // ready for new line
                inCompoundStatement = true;
            }
        }

其中

line = reader.readLine(prompt);

这里调用jline包中的方法从Console中读一行,但是实际上在eclipse中反悔了null于是在下面的代码中

if (line == null)
    return;

导致了运行的结束。而真正的原因是在我步进了jline包的源码中时,才发现的(jline-0.9.94下载:http://sourceforge.net/projects/jline/files/jline/0.9.94/),当调用reader.readLine()方法时总是返回null。后来google了一下,发现这个问题不是个别情况,而是一个非常知名的问题,如这篇文章(http://whitesock.iteye.com/blog/692816)中所说,“JLine最知名的问题莫过于在Windows平台下的Eclipse中启动的程序中调用reader.readLine()方法时总是返回null(正确的行为是等待用户输入)”,我下载了最新的版本jline-1.0,问题仍然存在。

根据那篇文章中的解决办法,“笔者发现通过设置jline.WindowsTerminal.directConsole属性为false,可以解决返回null的问题”,我确实解决了问题,代码如下:

jline.WindowsTerminal winTerm=(jline.WindowsTerminal)reader.getTerminal();
winTerm.setDirectConsole(false);

然后,我想看看究竟是哪里导致了这个问题,在CliMain.java中,初始化reader时,调用了jline.ConsoleReader的构造器,在jline.ConsoleReader.class中,发现时以下语句初始化了terminal

this(in, out, bindings, Terminal.getTerminal());

继续跟进,Terminal.getTerminal()是个静态方法,下面是其代码

    public static Terminal getTerminal() {
        return setupTerminal();
    }

这里调用了Terminal.setupTerminal()方法,这个方法实际上是用来判断操作系统是windows还是unix,然后根据情况创建WindowsTerminal或者UnixTerminal,既然出问题的是Windows系统下,那么再继续跟进到WindowsTerminal类中,在这里发现了上文提到的directConsole属性,其初始化的代码写在构造器中,如下:

        String dir = System.getProperty("jline.WindowsTerminal.directConsole");
        if ("true".equals(dir)) {
            directConsole = Boolean.TRUE;
        } else if ("false".equals(dir)) {
            directConsole = Boolean.FALSE;
        }

而具体使用到这个变量的地方,是这里:

    public int readCharacter(final InputStream in) throws IOException {
        // if we can detect that we are directly wrapping the system
        // input, then bypass the input stream and read directly (which
        // allows us to access otherwise unreadable strokes, such as
        // the arrow keys)
        if (directConsole == Boolean.FALSE) {
            return super.readCharacter(in);
        } else if ((directConsole == Boolean.TRUE)
            || ((in == System.in) || (in instanceof FileInputStream
                && (((FileInputStream) in).getFD() == FileDescriptor.in)))) {
            return readByte();
        } else {
            return super.readCharacter(in);
        }
    }

根据我在debug的过程中的步进,发现实际上在这个3分支的判断中,进入的是第二个,也就是directConsole == Boolean.TRUE,这说明在WindowsTerminal的构造器中,System.getProperty(“jline.WindowsTerminal.directConsole”)得到的是true,
但是这种情况是很奇怪的,我在CliMain中加入了以下代码进行debug

        System.out.println("true".equals(System.getProperty("jline.WindowsTerminal.directConsole")));

发现这里打印出的值是false,也就是说,在WindowsTerminal的构造器中directConsole被赋予了错误的值,这就是为什么要手动将其设为false

[转]JLine

原帖地址:http://whitesock.iteye.com/blog/692816

Overview

JLine 是一个用来处理控制台输入的Java类库,目前最新的版本是0.9.94。其官方网址是http://jline.sourceforge.net。在介绍JLine之前,首先还是介绍一下Java 6中的Console类,以便进行对比。

2 Java Console

通过调用System.console()方法可以得到与当前虚拟机对应的Console对象。但是该方法并不保证其返回值一定非null,这取决于底层平台和虚拟机启动的方式:如果是通过交互式的命令行启动,并且标准输入和输出流没有被重定向,那么该方法的返回值通常是非null;如果是被自动启动(例如cron)或者通过Eclipse启动,那么返回值通常为null。

Console类支持的功能有限,其中一个比较有用的功能是以非回显(echo)的方式从控制台读取密码。

3 JLine

JLine不依赖任何core Java以外的类库,但是其不是纯Java的实现。

  • 在Windows平台下,JLine通过自带的.dll文件初始化终端。jline.jar中包含了jline32.dll和jline64.dll,在Windows平台上使用的时候, JLine会自动将其解压缩到临时目录并进行加载。
  • 在Unix或者Max OS X平台下,JLine通过stty命令初始化终端。例如通过调用stty -icanon min 1将控制台设置为character-buffered模式。以及通过调用stty -echo禁止控制台回显。在修改终端的属性之前,JLine会对终端的属性进行备份,然后注册一个ShutdownHook,以便在程序退出时进行恢复。由于JVM在非正常退出时(例如收到SIGKILL信号)不保证ShutdownHook一定会被调用,因此终端的属性可能无法恢复。

JLine使用起来非常简单,jline.jar中一共只有20几个类,源码也不难懂。以下是个简单的例子,其中readLine函数的参数指定了命令行提示符:

ConsoleReader reader = new ConsoleReader();
String line = reader.readLine(">");

3.1 Features

3.1.1 Command History

通过按下键盘的上下箭头键,可以浏览输入的历史数据。此外JLine也支持终端快捷键,例如Ctrl+A, Ctrl+W,Ctrl+K, Ctrl+L等等,使用的时候非常便捷。

可以通过ConsoleReader的setUseHistory(boolean useHistory)方法启用/禁用Command History功能。ConsoleReader的history成员变量负责保存历史数据,默认情况下历史数据只保存在内存中。如果希望将历史数据保存到文件中,那么只需要以File对象作为参数构造History对象,并将该History对象设置到ConsoleReader即可。

3.1.2 Character Masking

ConsoleReader提供了一个readLine(final Character mask) 方法,用来指定character mask。如果参数为null,那么输入的字符正常回显;如果为0,那么不回显;否则回显mask指定的字符。

3.1.3 Tab Completion

JLine中跟自动补全相关的接口是Completor,它有以下几个实现:

  • SimpleCompletor: 对一系列指定的字符串进行自动补全。
  • FileNameCompletor: 类似于bash中的文件名自动补全。
  • ClassNameCompletor: 对classpath中出现的全路径类名进自动补全。
  • NullCompletor: 不进行自动补全。
  • ArgumentCompletor: 为每个属性使用指定的Completor。

以下是个简单的例子:

ConsoleReader reader = new ConsoleReader();
List<Completor> completors = new ArrayList<Completor>();
completors.add(new SimpleCompletor(new String[]{"abc", "def"}));
completors.add(new FileNameCompletor());
completors.add(new ClassNameCompletor());
completors.add(new NullCompletor());
reader.addCompletor(new ArgumentCompletor(completors));
reader.readLine(">");

以上例子中首先在命令行上键入a,然后按下TAB后会自动补全第一个属性abc;然后键入空格,再按下TAB会进行文件名的自动补全;再键入空格和按下TAB后会进行类名的自动补全; 再键入空格和按下TAB后不再有自动补全。需要注意的是,ArgumentCompletor会对命令行上所有索引超过completors长度的属性使用completors中最后一个元素指定的Completor。如果要禁用这个行为,那么将completors的最后一个元素设置为NullCompletor对象。

3.1.4 Custom Keybindings

通过创建 HOME/.jlinebindings.properties文件(或者制定 jline.keybindings 系统变量),可以定制keybindings。

4 Known Issues

JLine最知名的问题莫过于在Windows平台下的Eclipse中启动的程序中调用reader.readLine()方法时总是返回null(正确的行为是等待用户输入)。通过debug, 笔者发现通过设置jline.WindowsTerminal.directConsole属性为false,可以解决返回null的问题,但是感觉还是有些其它的问题。总之,笔者没有发现好的对策,只能work around,即对JLine再进行一层封装,在某些场景下仍然使用原始的基于System.in的流处理。

5 Usage

想必很多项目都会为其应用做一层Application之类的抽象。对应用进行监控的常见方式是使用JMX,JMX从逻辑上可以认为是应用程序的一个Shell。笔者为项目中的Application提供了一套完整的Shell抽象,包括Shell、Console、 Process 和 Command等等。其中JLine是一种Console的具体实现。如果是后台应用,那么可以通过基于Socket的Console连接到应用,从而进行监控,例如停止应用程序等。如果前台的交互式应用,那么可以直接使用基于终端的Console实现, 例如笔者项目中为Spring Batch实现的CommandLine Scheduler等。

2011/06/20 在Eclipse中配置Cassandra——配置文件介绍2

接上回

https://hycz.wordpress.com/2011/06/17/cassandra-yaml/

8.

今天介绍一下conf文件夹下的其他配置文件

首先是log4j-server.proprties,这个和cassandra.yaml一样是必须的配置文件。具体的用法参见http://kdboy.iteye.com/blog/208851

下面是passwd.properties,这是一个SimpleAuthenticator的用户密码配置,每行格式是username=password,如果-Dpasswd.mode=MD5,那么密码部分是md5 digest,否则,密码部分是明文。(用户名中空格用’\ ‘)

接下来是access.properties,这是一个SimpleAuthority的访问配置,每行格式是KEYSPACE[.COLUMNFAMILY].PERMISSION=USERS,其中,KEYSPACE是keyspace名,COLUMNFAMILY是column family名,PERMISSION是<ro>或者<rw>,意思是read only或read-write,USERS是一系列用户名,用逗号隔开,这些用户名必须在passwd.properties中定义。例:Keyspace1.Standard1.<rw>=jsmith,Elvis Presley,dilbert

最后是cassandra-topology.properties,这是一个定义cassandra集群拓扑的配置,每行格式是Cassandra Node IP=Data Center:Rack,其中,等号左边是ip,右边是数据中心名和机架名(似乎只是个名字,不用定义),这里主要是用来判断节点的临近性,由org.apache.cassandra.locator.PropertyFileSnitch使用。注意,如果ip不明的话,比如后来加入的节点,那么ip部分就用default代替。如果需要使用ipv6,那么需要在cassandra-env.sh中把其中一个参数设置改为:JVM_OPTS=”$JVM_OPTS -Djava.net.preferIPv4Stack=true”。

[转]Log4j使用总结

一、介绍

Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务 器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。

Log4j由三个重要的组件构成:日志信息的优先级,日志信息的输出目的地,日志信息的输出格式。日志信息的优先级从高到低有ERROR、WARN、 INFO、DEBUG,分别用来指定这条日志信息的重要程度;日志信息的输出目的地指定了日志将打印到控制台还是文件中;而输出格式则控制了日志信息的显示内容。

二、配置文件

其实您也可以完全不使用配置文件,而是在代码中配置Log4j环境。但是,使用配置文件将使您的应用程序更加灵活。

Log4j支持两种配置文件格式,一种是XML格式的文件,一种是properties格式的文件。下面我们介绍使用properties格式做为配置文件的方法:

示例:

log4j.rootLogger=INFO, A1

log4j.appender.A1=org.apache.log4j.ConsoleAppender

log4j.appender.A1.layout=org.apache.log4j.PatternLayout

log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x – %m%n

1. 配置根Logger,其语法为:

log4j.rootLogger = [ level ] , appenderName, appenderName, …

其中,level 是日志记录的优先级,分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别。Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来。

appenderName就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。

2. 配置日志信息输出目的地Appender,其语法为:

log4j.appender.appenderName = fully.qualified.name.of.appender.class

log4j.appender.appenderName.option1 = value1

log4j.appender.appenderName.option = valueN

其中,Log4j提供的appender有以下几种:

org.apache.log4j.ConsoleAppender(控制台),

org.apache.log4j.FileAppender(文件),

org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),

org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),

org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

(1).ConsoleAppender选项

Threshold=WARN:指定日志消息的输出最低层次。

ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。

Target=System.err:默认情况下是:System.out,指定输出控制台

(2).FileAppender 选项

Threshold=WARN:指定日志消息的输出最低层次。

ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。

File=mylog.txt:指定消息输出到mylog.txt文件。

Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。

(3).DailyRollingFileAppender 选项

Threshold=WARN:指定日志消息的输出最低层次。

ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。

File=mylog.txt:指定消息输出到mylog.txt文件。

Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。

DatePattern=’.’yyyy-ww:每周滚动一次文件,即每周产生一个新的文件。当然也可以指定按月、周、天、时和分。即对应的格式如下:

1)’.’yyyy-MM: 每月

2)’.’yyyy-ww: 每周

3)’.’yyyy-MM-dd: 每天

4)’.’yyyy-MM-dd-a: 每天两次

5)’.’yyyy-MM-dd-HH: 每小时

6)’.’yyyy-MM-dd-HH-mm: 每分钟

(4).RollingFileAppender 选项

Threshold=WARN:指定日志消息的输出最低层次。

ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。

File=mylog.txt:指定消息输出到mylog.txt文件。

Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。

MaxFileSize=100KB: 后缀可以是KB, MB 或者是 GB. 在日志文件到达该大小时,将会自动滚动,即将原来的内容移到mylog.log.1文件。

MaxBackupIndex=2:指定可以产生的滚动文件的最大数。

3. 配置日志信息的布局,其语法为:

log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class

log4j.appender.appenderName.layout.option1 = value1

log4j.appender.appenderName.layout.option = valueN

其中,Log4j提供的layout有以下几种:

org.apache.log4j.HTMLLayout(以HTML表格形式布局),

org.apache.log4j.PatternLayout(可以灵活地指定布局模式),

org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),

org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)

4、输出格式设置

在配置文件中可以通过log4j.appender.A1.layout.ConversionPattern设置日志输出格式。

参数:

%p: 输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL,

%d: 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921

%r: 输出自应用启动到输出该log信息耗费的毫秒数

%c: 输出日志信息所属的类目,通常就是所在类的全名

%t: 输出产生该日志事件的线程名

%l: 输出日志事件的发生位置,相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)

%x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。

%%: 输出一个”%”字符

%F: 输出日志消息产生时所在的文件名称

%L: 输出代码中的行号

%m: 输出代码中指定的消息,产生的日志具体信息

%n: 输出一个回车换行符,Windows平台为”\r\n”,Unix平台为”\n”输出日志信息换行

可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如:

1)%20c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,默认的情况下右对齐。

2)%-20c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,”-”号指定左对齐。

3)%.30c:指定输出category的名称,最大的宽度是30,如果category的名称大于30的话,就会将左边多出的字符截掉,但小于30的话也不会有空格。

4)%20.30c:如果category的名称小于20就补空格,并且右对齐,如果其名称长于30字符,就从左边交远销出的字符截掉。

三、在程序中的使用

在程序中使用Log4j之前,首先要将commons-logging.jar和logging-log4j-1.2.9.jar导入到classpath中,并将log4j.properties放于src根目录中。接下来就可以使用了。

1.得到记录器

使用Log4j,第一步就是获取日志记录器,这个记录器将负责控制日志信息。其语法为:

public static Logger getLogger( String name),

通过指定的名字获得记录器,如果必要的话,则为这个名字创建一个新的记录器。Name一般取本类的名字,比如:

static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () ) ;

注:推荐使用commons-logging结合log4j进行日志记录

private static Log logger = LogFactory.getLog(Yourclass.class);

2.插入记录信息(格式化日志信息)

当上两个必要步骤执行完毕,您就可以轻松地使用不同优先级别的日志记录语句插入到您想记录日志的任何地方,其语法如下:

Logger.debug ( Object message ) ;

Logger.info ( Object message ) ;

Logger.warn ( Object message ) ;

Logger.error ( Object message ) ;

四、Log4j比较全面的配置

LOG4J的配置之简单使它遍及于越来越多的应用中了:Log4J配置文件实现了输出到控制台、文件、回滚文件、发送日志邮件、输出到数据库日志表、自定义标签等全套功能。择其一二使用就够用了。

log4j.rootLogger=DEBUG,CONSOLE,A1,im
log4j.addivity.org.apache=true
# 应用于控制台
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.Threshold=DEBUG
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
#log4j.appender.CONSOLE.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[thread] n%c[CATEGORY]%n%m[MESSAGE]%n%n
#应用于文件
log4j.appender.FILE=org.apache.log4j.FileAppender
log4j.appender.FILE.File=file.log
log4j.appender.FILE.Append=false
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
# Use this layout for LogFactor 5 analysis
# 应用于文件回滚
log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender
log4j.appender.ROLLING_FILE.Threshold=ERROR
log4j.appender.ROLLING_FILE.File=rolling.log //文件位置,也可以用变量${java.home}、rolling.log
log4j.appender.ROLLING_FILE.Append=true //true:添加 false:覆盖
log4j.appender.ROLLING_FILE.MaxFileSize=10KB //文件最大尺寸
log4j.appender.ROLLING_FILE.MaxBackupIndex=1 //备份数
log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

#应用于socket
log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender
log4j.appender.SOCKET.RemoteHost=localhost
log4j.appender.SOCKET.Port=5001
log4j.appender.SOCKET.LocationInfo=true
# Set up for Log Facter 5
log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout
log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[thread]%n%c[CATEGORY]%n%m[MESSAGE]%n%n

# Log Factor 5 Appender
log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender
log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000
# 发送日志给邮件
log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
log4j.appender.MAIL.Threshold=FATAL
log4j.appender.MAIL.BufferSize=10
log4j.appender.MAIL.From=web@www.wuset.com
log4j.appender.MAIL.SMTPHost=www.wusetu.com
log4j.appender.MAIL.Subject=Log4J Message
log4j.appender.MAIL.To=web@www.wusetu.com
log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
# 用于数据库
log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test
log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver
log4j.appender.DATABASE.user=root
log4j.appender.DATABASE.password=
log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES (’[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n’)
log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A1.File=SampleMessages.log4j
log4j.appender.A1.DatePattern=yyyyMMdd-HH’.log4j’
log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout
#自定义Appender
log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender
log4j.appender.im.host = mail.cybercorlin.net
log4j.appender.im.username = username
log4j.appender.im.password = password
log4j.appender.im.recipient = corlin@cybercorlin.net
log4j.appender.im.layout=org.apache.log4j.PatternLayout
log4j.appender.im.layout.ConversionPattern =[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

2011/06/15-17 在Eclipse中配置Cassandra——配置文件介绍

接上回https://hycz.wordpress.com/2011/06/14/20110614-%E5%9C%A8eclipse%E4%B8%AD%E9%85%8D%E7%BD%AEcassandra2/

7.
今天要对Cassandra进行配置,这话有点拗口,简单来说,就是改一下conf文件夹里的配置文件,因为原来的是默认设置,而且是针对linux的文件系统的,这里要改成windows下的。首先是cassandra.yaml文件(这坑好大。。。慢慢填),主要翻译翻译注释。。。。

1、cluster_name:集群名,主要用来防止机器加入到其他的逻辑集群中
2、initial_token:cassandra中有个token环,每个节点都负责其中的一部分,这个参数就是用来设定这台机器负责哪部分的。如果空着不写,那么就自动取负载最重的节点所拥有的token范围的一半。如果取不到负载信息,那么就随机取一段。
3、auto_bootstrap:cassandra中的节点其实还是分了2种,一个是seed节点,一个是non-seed节点,一个节点要加入集群实际上还是要一个入口,这个入口就是种子节点,所以一次能够加入集群的节点数量是有限的,即种子节点的数量,如果需要加入集群的节点数量多于这个阀值,那么就需要分阶段进行加入操作。这个参数是用来设定一个非种子节点是否在启动时自动从已有节点中迁移数据进来。默认false
4、hinted_handoff_enable:这个参数涉及了cassandra的一个机制,当一个写操作所针对的副本节点down掉的时候,cassandra会在另一台活着的副本几点上写一个hint(提示?暗示?还不如说是个便签。。。),这个hint用来表明那台down掉的节点需要重新执行这个写操作。如果所有的副本节点都死了,而且一致性等级是ConsistencyLevel.ANY(五种?ZERO,ONE,QUORUM,ALL,ANY,这里ANY是说只要一个写操作在任何地方成功了,hint写也算。。。那就算成功。。),协调节点(coordinating node)会在本地写下这个hint。这个机制主要是用来减少暂时失效节点通过活着的节点重新恢复到一致状态 所需要的时间,并且在不需要一致性的情况下提供额外的可用性。
     max_hint_window_in_ms:节点死掉之后保留hint的最长时间,死太久了,超过这个时间那么之前写的hint就被丢弃。
     hinted_handoff_throttle_delay_in_ms:每发送一行或者行碎片时sleep这么长时间?这里不确定
6、authenticator:认证后端,实现接口IAuthenticator,用来识别用户
7、authority:授权后端,实现接口IAuthority,用来限制访问,提供通行权
8、partitioner:这里是Cassandra中很重要的一部分,设置了Cassandra中数据的数据分割方式,用通俗的话来说,就是数据是以怎样的规则分布在整个集群的许多节点中的,数据的分割是以row为单位的,row使用key来唯一辨别的,所以其实就是key的分布。设置的值是个类名,这个类需要实现IPartitioner接口。Cassandra提供了几种分布方式如下

org.apache.cassandra.dht.RandomPartitioner
org.apache.cassandra.dht.ByteOrderedPartitioner
org.apache.cassandra.dht.OrderPreservingPartitioner (deprecated)
org.apache.cassandra.dht.CollatingOrderPreservingPartitioner(deprecated)

第一个是随机分割,使用md5;第二个是根据key的每个byte的字母顺序进行排序,这种排序支持row级别的(其实就是key啊)范围查询,但是对于顺序插入的负载,这种分割会存在热点问题,但是没办法啊。。。不然怎么顺序查询。。。泪奔;第三个是第二个的废弃版本,格式比第二个低效,使用UTF-8编码的字符串当做key;第四个似乎是和第三个差不多的,不过用了另一种排序方式,反正都被废弃了,不管了。
9、data_file_directories:存data的目录
     commitlog_directory:存commitlog的目录
     saved_caches_directory:存cache的目录
     commitlog_rotation_threshold_in_mb:一个阀值,单位MB,当commitlog超过这个大小时,就产生一个新的段
10、commitlog_sync:这里设置commitlog的同步方式,应该就是从内存中同步到磁盘上做持久化,这里有2种设置,一个是batch,一个是periodic。在batch模式中,只有当commit log同步到了磁盘上之后才会执行写操作,在执行同步之前,将会等待CommitLogSyncBatchWindowInMS毫秒,等其他的写操作结束。在periodic模式中,写操作会被立即执行,无视commitlog有没有写到磁盘上,而commitlog则是每隔commitlog_sync_period_in_ms这么长时间才周期性的进行同步。
      commitlog_sync_period_in_ms:commitlog以periodic模式同步时的周期值,单位毫秒。
11、seed_provider:这个参数是seed节点的设置,首先是要设置seed_provider的子参数- class_name,这里需要制定一个类来提供seed功能,这个类需要实现SeedProvider接口,然后设置子参数- seeds,也就是seed节点的地址,多个地址间用逗号隔开
12、flush_largest_memtables_at:这是第一个紧急状况压力阀值,这里的值设置在0-1.0之间,这个值的意思是每当full garbage collection之后,如果堆的使用率高于这个阀值的话,那么就会把最大的memtable flush到磁盘上。设到1.0就是永远不执行,也最好不要低于CMSInitiatingOccupancyFraction。
13、reduce_cache_sizes_at:这是第二个紧急状况压力阀值,在full garbage collecion之后,如果首次出现堆使用率高于这个阀值,那么cassandra就会降低cache的最大容量,并且降低cache的当前大小。
reduce_cache_capacity_to:当上述情况发生时,cache的最大容量降低比例
14、concurrent_reads:并发读的数量,当负载高于内存中能满足的数据时,读会成为cassandra的瓶颈,建议设置成16*驱动器数量
      concurrent_writes:并发写的数量,一般对于写操作,IO不会成为瓶颈,计算机的处理器core数才是影响其性能的关键,所以可以设置成8*core数量
15、memtable_total_space_in_mb:memtable的最大值,省略的话自动设置成堆的三分之一大小
        memtable_flush_writers:memtable flush的进程数量,由于flush进程会被磁盘io所阻塞,而且当被阻塞时,每个进程都会持有一个memtable,所以当堆很大,而且有很多数据目录时再去提高这个值。省略的话默认设置为数据目录的数量
      memtable_flush_queue_size:当memtable满了的时候能够进入等待flush队列的数目,最小应该设置为一个Column Family中辅助索引的最大数目
16、sliced_buffer_size_in_kb:处理连续的column slice的buffer大小
17、storage_port:TCP的端口
18、listen_address:其他节点用来连接的地址,也就是本机的地址,空着的话会自动调用InetAddress.getLocalHost()来填这个空,一般是填本机的hostname,不能填0.0.0.0
19、rpc_address:Thrift RPC service所绑定的地址,客户端会连接这个地址,0.0.0.0意味着监听所有,空着同上。
      rpc_port:Thrift RPC service绑定的端口
      rpc_keepalive:是否保持rpc连接存活,也就是用不用长连接吧
20、rpc_min_threads:对于客户端RPC,Cassandra使用一个进程进行处理,这是很昂贵的消耗,所以更好的方法是使用连接池。不过这里还是提供了rpc数量设置,这个参数是最小进程数。注释掉就默认16
      rpc_max_threads:这个参数是最大进程数,注释掉默认无上限
21、rpc_send_buff_size_in_bytes:rpc连接的socket buffer大小,可以注释掉
      rpc_recv_buff_size_in_bytes:rpc连接的socket buffer大小,可以注释掉
22、thrift_framed_transport_size_in_mb:thrift的框架大小,设成0就不用TFramedTransport,而用TSocket,但是不推荐设成0
23、thrift_max_message_length_in_mb:thrift消息的最大长度,包括所有的字段(field)和thrift内部的开销
24、incremental_backups:如果设为true的话,Cassandra会建立到每个已在本地flush后或stream之后的sstable的硬链接,这些sstable在Keyspace数据的备份或者子目录中。移除这些链接将是操作者的职责。一般设成false?这个参数没看懂。。。
25、snapshot_before_compaction:是否在每次compaction之前做snapshot,注意,如果设为true的话,cassandra是不会去清理这些snapshot的,所以要手动清理,估计会很多,很麻烦。。。一般设成false吧
26、compaciton_thread_priority:设置compaciton进程的优先级,注释掉的话默认设为1,在java中1是最低。。。。
27、column_index_size_in_kb:当一个row的内容超过这里设置的大小时,会添加column索引,默认设成了64,如果column的值都很大,或者有很多column的话,可以相应设置更大的值。这带来了另一个很矛盾的问题,即使只是读一个单独的column,Cassandra也需要反序列化(deserialize)这部分索引数据,所以这些索引数据是越小越好,一个column的情况可能比较极端,但至少能在读一行的一部分时(这种情况比较多见)能小一些;但是每次存取时是都需要先访问索引数据的,所以我们也不能一味图小,而使得索引中无法包括足够有用的信息。说了这么多废话,意思就是这个值要根据应用好好斟酌,不能太大,不能太小。默认64KB
28、in_memory_compaction_limit_in_mb:在内存中进行compaction的row的最大大小,超过这个值的话,超过的部分会暂时放到磁盘上,那么这个compaction效率就不行了。一个消息会log下来,用来辨别这个row key
29、concurrent_compactors:compation进程的数量,注释掉默认设置为处理器的数量,建议是使用多个进程进行处理,这样可以在读写混合型负载中保持读性能,原因是这样避免了在长时间的compaciton中sstable的积聚。。。其实嘛,就是compaciton的快一些。。
30、compaction_throughput_mb_per_sec:设置了一个阀值限制compaction输出的速率,单位是MB/s,要知道,compaciton是一个很差火的操作,同时消耗CPU,MEMORY,IO资源,所以compaction的时机非常重要,否则会对整个系统产生重大影响。compaction的相关设置都值得好好研究,如果希望系统高效的话,这个值的设置还是要结合实际使用情况。插入数据的速度越快,那么compaction的速度也要越快,以控制sstable的数量。一般设置这个值为插入数据速率的16到32倍比较好。设为0的话就没有阀值。
31、compaction_preheat_key_cache:是否在compaction过程中跟踪已缓存的row key,并且重新缓存这些row key在compact之后的sstable中的新位置。如果有足够大的key缓存的话,可以设为false(为什么。。。。)
32、rpc_timeout_in_ms:等待其他节点回复的时间,超过这个时间则执行的命令失败
33、phi_convict_threshold:这里就是论文中提到的Failure Detection所用到的phi,这里有一个算法,算出一个节点的phi值,如果超过阀值,那么就判断这个节点已经down掉。一般用不到,注释掉
34、endpoint_snitch:这里的参数值是一个实现了IEndpointSnitch接口的类,用来让Cassandra知晓网络拓扑,以更高效的route(这里忍不住吐槽一下,翻译成路由真是不知所云,还不如直接翻译成寻路)请求。snitch也是一个不好理解的地方,原意为告密,实际是理解为告知别人自己的拓扑结构么?那这个参数叫端点告知?Cassandra提供了3个策略

org.apache.cassandra.locator.SimpleSnitch:
org.apache.cassandra.locator.RackInferringSnitch:
org.apache.cassandra.locator.PropertyFileSnitch:

第一个是是简单策略,就是一个简单的邻近策略,能够提高缓存的locality(本地性?或者说集中性?),但是不能进行读修复(读修复能够进一步提高吞吐?);第二个是机架策略,邻近性由机架和数据中心决定,这里假设邻近性由不同节点的ip(ipv4)的第三个和第二个8位数(A.B.C.D中的B和C。。。)来决定,也就是说ip相近,那就认为更邻近;第三个是用配置文件显性地写好了哪些节点邻近,配置文件是cassandra-topology.properties。
35、dynamic_snitch:是否使用dynamic_snitch。dynamic_snitch是包裹在endpoint_snitch外,用来监控读延迟,以避免从已经变慢的主机上进行读取。
      dynamic_snitch_update_interval_in_ms:多久进行一次分数计算(代价昂贵?)
      dynamic_snitch_reset_interval_in_ms:多久充值所有机器的分数,通过这样的操作很可能可以让坏掉的节点恢复
      dynamic_snitch_badness_threshold:这里又提到了另一个机制,副本的pin(钉住?不知怎么翻译),意思就是反复从一个副本上读数据,这样cache的能力会得到提高。当这个参数的值(0.0到1.0闭区间)设置为大于0的时候,这个机制就会启动。但是基于dynamic snitch机制,副本是有分数的,dynamic snitch是用来监控读延迟,并且给主机打分,以评出优劣,然后选择更优的副本提供读,当一个已经pinned的副本变坏时,就需要换一个性能更优的副本pin住提供读。那么如何判断一个副本已经很坏了,需要换一个副本提供读呢?这里就用到了这个阀值,举个例子,当这个值为0.2时,当已经被pin的副本的分数比最快的副本的分数低20%时,cassandra就会选择另一个副本。

36、request_scheduler:这个参数是一个实现了RequestScheduler的类,用来基于特定的策略来调度传入的客户端请求,当一个Cassandra集群上有多租户时,这个调度会很有用。这个调度只是针对客户端请求,并不会影响内部节点通信。下面是提供的几个类

org.apache.cassandra.scheduler.NoScheduler
org.apache.cassandra.scheduler.RoundRobinScheduler

第一个是不使用任何调度;第二个是使用round robin调度客户端请求,每一个不同的request_scheduler_id都有一个单独的队列,具体的option会由request_scheduler_options设置
      request_scheduler_options:如果用NoScheduler,那么没有option,如果用RoundRobin,那么会有3个子选项:1,throttle_limit,每个客户端的请求数量阀值,超过这个数量的请求都会进入队列,大小设置一般是(并行读+并行写)*2;2,default_weight,可选选项,默认权值的设置,原先是1,但是可以自己设定;3,weights,也是可选选项,如果不写,那么权值会被设置成default_weight,这个参数是设定每轮RoundRobin中,基于scheduler id的权值,有多少请求会被处理,scheduler id的设置在下面。
      request_scheduler_id:基于这个id来进行请求调度,当前唯一的选择是keyspace
37、index_interval:对一个sstable的row key进行采样的大小,采样越大,index越有效,但是要消耗更多的空间
38、encryption_options:节点间的加密

2011/06/14 在Eclipse中配置Cassandra_2

接上回https://hycz.wordpress.com/2011/06/13/20110613-%E5%9C%A8eclipse%E4%B8%AD%E9%85%8D%E7%BD%AEcassandra/

  1. 见上回
  2. 见上回
  3. 见上回
  4. 遇到问题,开始Debug的时候出现
    “‘Launching CassandraDaemon’ has encountered a problem.
    Cannot connect to VM”Details中:
    “Cannot connect to VMselect failed”不光是这个项目,我新建了一个最简单的project写了个helloworld都不能用debug,说明这是eclipse层的问题。具体出错处是什么socket出错,网上的说法就几种:1,有其他程序占用了Eclipse的Debug端口,导致出错;2,操作系统的socket出了问题要重置。对于第一种解释,虽然我表示同意是另一个程序影响了Eclipse,但是实在难以找到相应的程序,对于第二种解释,我又找不到win7下的重置sock的工具。无奈之下,就用了360的LSP修复,修复之后Debug能用了,但是不能打开网页了。我在修复前看了一下,使用到LSP的非系统程序只有2个,都是我的游戏代理,一个是27代理,一个是迅雷加速器,恐怕问题就出在他们身上。无论如何,网页是打不开了,qq还在,于是重启看看。重启之后,依然不能上网,连qq都上不去了,打开360,居然要求自动修复,那就自动修复吧,结果瑞星狂叫360是木马,现在吧,我觉得瑞星更像木马一些。修复完了,按要求重启,qq能上了,但是网页打不开,这种情况好像DNS坏了一样,就用cmd ping了一下百度,居然ping的通,然后我又用Access Connections诊断了一下网络故障,他叫我检查防火墙设置。360防火墙怎么莫名其妙开了,关掉,不能开网页,瑞星防火墙,关掉,能开网页了。瑞星果然是娱乐货,没事弄个免费,天天弹那些狗屎免费游戏,真的考虑要不用它了。又启动了一下迅雷网游加速器,果然问题再现了,使用他自带的LSP修复,然后问题消失。果然还是LSP引起的问题么。这种诡异的问题不要再碰到了啊!这样一来,代理还是能用,只是用完了要修复,不能一边wow一边debug了。。
  5. 类中的static{}属性,似乎是在调用类的方法时,会首先执行的代码,在Cassandra的org.apache.cassandra.service.AbstractCassandraDaemon类中,就有这么一段,是用来初始化logging的
    //Initialize logging in such a way that it checks for config changes every 10 seconds.
        static
        {
        	String config = System.getProperty("log4j.configuration", "log4j-server.properties");
            URL configLocation = null;
            try
            {
                // try loading from a physical location first.
                configLocation = new URL(config);
            }
            catch (MalformedURLException ex)
            {
                // load from the classpath.
                configLocation = AbstractCassandraDaemon.class.getClassLoader().getResource(config);
                if (configLocation == null)
                    throw new RuntimeException("Couldn't figure out log4j configuration.");
            }
            PropertyConfigurator.configureAndWatch(configLocation.getFile(), 10000);
            org.apache.log4j.Logger.getLogger(AbstractCassandraDaemon.class).info("Logging initialized");
        }

    这里首先定义了一个变量config,这个config的属性关键字是log4j.configuration,然后给了一个默认值log4j-server.properties,这个变量的主要目的是储存log4j的配置文件地址,默认的文件名是log4j-server.properties,如果在启动时手动设置了其他值的话,那么就会是那个手动设置的值。

    然后首先尝试通过物理地址查找这个配置文件(try中),如果找不到(catch中),那么就到启动时设置的CLASSPATH中去找这个文件。

  6. 再看cassandra-0.8.0的bin版本中的bin文件夹中的cassandra.bat文件(我用的是windows7。。。) ,通过分析这个文件中所作的操作,可以知道如何在Eclipse中配置Cassandra的运行参数。以下摘自cassandra.bat文件。
    if "%OS%" == "Windows_NT" setlocalif NOT DEFINED CASSANDRA_HOME set CASSANDRA_HOME=%~dp0..
    if NOT DEFINED CASSANDRA_MAIN set CASSANDRA_MAIN=org.apache.cassandra.thrift.CassandraDaemon
    if NOT DEFINED JAVA_HOME goto err

    这段分别定义了cassandra的根目录地址,cassandra的入口程序,检查了JAVA_HOME是否定义。

    REM ***** JAVA options *****
    set JAVA_OPTS=^
     -ea^
     -Xms1G^
     -Xmx1G^
     -XX:+HeapDumpOnOutOfMemoryError^
     -XX:+UseParNewGC^
     -XX:+UseConcMarkSweepGC^
     -XX:+CMSParallelRemarkEnabled^
     -XX:SurvivorRatio=8^
     -XX:MaxTenuringThreshold=1^
     -XX:CMSInitiatingOccupancyFraction=75^
     -XX:+UseCMSInitiatingOccupancyOnly^
     -Dcom.sun.management.jmxremote.port=7199^
     -Dcom.sun.management.jmxremote.ssl=false^
     -Dcom.sun.management.jmxremote.authenticate=false^
     -Dlog4j.configuration=log4j-server.properties^
     -Dlog4j.defaultInitOverride=true

    这段是各种参数,需要把这段复制到Eclipse中Run->Debug Configration中建立的Debug项中的VM arguments中(注意把每行最后的^删掉)。

    REM Ensure that any user defined CLASSPATH variables are not used on startup
    set CLASSPATH="%CASSANDRA_HOME%\conf"

    这里就定义了CLASSPATH,原来这里把conf文件夹加入到了CLASSPATH里(CLASSPATH里不止一个地址),怪不得能找到。所以在Eclipse的项目的Properties->Java Build Path->Libraries点Add Class Folder,加入这个conf地址,就不会报错了

    bat文件中其他的设置也是大同小异,就不写了。

[转]svn命令行工具安装使用(windows)

源帖地址:http://hi.baidu.com/daralis_dy/blog/item/4755e77a48cae0e10bd187fe.html
svn命令行工具安装使用(windows)
2011-03-30 08:52

从http://subversion.tigris.org获取subversion for windows的版本,安装之后就有了svn.exe这个基于命令行的客户端工具。

安装装程序会自动把svn.exe的路径加入了path环境变量,但是默认路径c盘内,需要修改为安装到的盘符路径。

在“我的电脑”上右键选择“属性”-》“高级”-》“环境变量”,

如安装在d盘,修改用户变量中的APR_ICONV_PATH为

d:\Program Files\Subversion\iconv

在系统变量中的PATH后面添加

d:\Program Files\Subversion\bin(记得加;号隔开两项路径)

修改了环境变量之后要重启电脑才能生效。

现在在命令行中输入svn –help,如能正确执行,则安装成功。