该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2008-10-22
问题已经确定,在解析命令响应的时候使用了mina提供的TextLineDecoder,这东东可以把一个IoBuffer分成多个指定间隔符的字符串数组,而使用Serializable序列化的byte数组有些认为是特殊字符,无法识别成字符串。
多谢帮我发现问题,呵呵,所以说开源就是好! 不过我的初衷是觉得java自带的序列化/反序列化效率太低了,所以希望能够自己实现。不管怎么样,我使用TextLineDecoder还是太偷懒了,呵呵,回头改一下。 |
|
返回顶楼 | |
发表时间:2008-10-22
其实JDK还提供了另一个接口Externalizable,相比使用Serializable的性能应该有提高。不知道对你有没有什么帮助
|
|
返回顶楼 | |
发表时间:2008-10-22
Externalizable以前用过,比serialize快得多,但是比较麻烦,会要求每个结构都去实现这个接口,如果消息种类太多,那么开发工作量会比较大。不利于上层应用开发。
其实对于我这个框架来说,不关心是怎么进行序列化/反序列化的,我暴露byte[]出来,如果你关心效率,那么你可以用Externalizable或者hessian的序列化/反序列化,如果你不关心,那么就可以用serialize或者json,总之这属于接口友好性的领域。对项目本身影响不大。 |
|
返回顶楼 | |
发表时间:2008-10-22
liuye 写道 uniseraph 写道 liuye 写道 get/set只能对字符串/字节操作,Object怎么办?另外,是不是没有考虑连接多个memcached服务器呀? 有数据了,再进行序列化和反序列化是很简单的。后续会包装一些接口。 连接多个服务器也是准备后续再做的,以现在的结构而言,支持起来很简单。 现在我正在考虑把单位时间内的多个get合并成一个gets操作,这样对系统性能提升应该有更大的帮助。 根据你的set/get写了read/write方法,对Object进行读写,write方法好像正常,但read方法在运行GetReponse rsp = (GetReponse) pool.send(command, true)时出错。代码如下: public Object read(String key) { GetCommand command = new GetCommand(); command.setValue(key); GetReponse rsp = (GetReponse) pool.send(command, true); if (rsp != null && rsp.isSuccess()) { byte[] result = rsp.getResult(); try { return bytes2Object(result); } catch (Exception e) { log.error(e.getMessage()); e.printStackTrace(); } } return null; } public void write(String key, Serializable value) { byte[] bytes = null; try { bytes = object2Bytes(value); } catch (Exception e) { log.error(e.getMessage()); e.printStackTrace(); } if (bytes != null) { SetCommand setCommand = new SetCommand(); setCommand.setKey(key); setCommand.setValue(bytes); SetReponse rsp = (SetReponse) pool.send(setCommand, true); if (rsp != null && rsp.isSuccess()) { } } } public static Object bytes2Object(byte[] objBytes) throws Exception { if (objBytes == null || objBytes.length == 0) { return null; } ByteArrayInputStream bi = new ByteArrayInputStream(objBytes); ObjectInputStream oi = new ObjectInputStream(bi); return oi.readObject(); } public static byte[] object2Bytes(Serializable obj) throws Exception { if (obj == null) { return null; } ByteArrayOutputStream bo = new ByteArrayOutputStream(); ObjectOutputStream oo = new ObjectOutputStream(bo); oo.writeObject(obj); return bo.toByteArray(); } 问题已经解决,主要是新增加了一个基于IoBuffer的协议解析器NormalReponseDecoder,取消了原来基于TextLineDecoder的LinedReponseDecoder。到现在为止已经有三种协议解析方法了,回头再做个测试,比较一下三个的区别。 代码已经提交到https://commons-client.googlecode.com/svn/branches/0.1.1 ,暂时不提主干,稳定以后再说。 测试代码如下: public class Test { /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { ByteArrayOutputStream bo = new ByteArrayOutputStream(); ObjectOutputStream oo = new ObjectOutputStream(bo); oo.writeObject(new Example(1, "hello")); byte[] buffer = bo.toByteArray(); MemcachedClient mc = new MemcachedClient("10.2.224.34",11211,2); mc.set("aaa", buffer); byte[] result = mc.get("aaa" ); boolean b = Arrays.equals(buffer, result); System.out.println(b); } private static class Example implements Serializable { private int age; private String desc; public Example(int age, String desc) { super(); this.age = age; this.desc = desc; } } } |
|
返回顶楼 | |
发表时间:2008-10-23
贴一下测试代码:
public static void main(String[] args){ //.... MemcachedClient mc = new MemcachedClient(ip, port, size); CountDownLatch cdl = new CountDownLatch(thread); long t = System.currentTimeMillis(); for (int i = 0; i < thread; i++) { new Thread(new TestRunnable(mc, i * 10000, cdl, repeat)).start(); } try { cdl.await(); } catch (InterruptedException e) { } long all = 2 * thread * repeat; long usingtime = (System.currentTimeMillis() - t); log .info(String .format( "thread num=%d, repeat=%d,size=%d, all=%d ,velocity=%d , using time:%d", thread, repeat, size, all, 1000 * all / usingtime, usingtime)); mc.pool.close(); } static private class TestRunnable implements Runnable { private MemcachedClient mc; private CountDownLatch cd; int repeat; int start; public TestRunnable(MemcachedClient mc, int start, CountDownLatch cdl, int repeat) { super(); this.mc = mc; this.start = start; this.cd = cdl; this.repeat = repeat; } public void run() { for (int i = 0; i < repeat; i++) { String key = Integer.toString(i); mc.set(key, key.getBytes()); byte[] value = mc.get(key); if (log.isInfoEnabled()) { String result = new String(value); if (!result.equals(key)) { log.info(String .format("key:%s->result:%s", key, result)); throw new IllegalStateException(); } } } cd.countDown(); // if (log.isDebugEnabled()) // log.debug(String.format("%s count down", Thread.currentThread() // .getName())); } } 基本算法是:启动100个线程,每个线程循环10000次,每次发送两个操作,一个set一个get。100个线程全部退出,则记时结束。 |
|
返回顶楼 | |
发表时间:2008-10-27
鼓励一下,之前我也尝试做过。
不过一个开源软件要取得成功,需要投入很多时间。还需要一些运作,和商业软件一样。 |
|
返回顶楼 | |
发表时间:2008-10-27
这个项目值得研究,我想稳定之后,将来应该是一个趋势了,理论很简单,就是内存越大,机器越快,期望能有更大的发展空间!
|
|
返回顶楼 | |
发表时间:2008-10-28
uniseraph 写道 liuye 写道 get/set只能对字符串/字节操作,Object怎么办?另外,是不是没有考虑连接多个memcached服务器呀? 有数据了,再进行序列化和反序列化是很简单的。后续会包装一些接口。 连接多个服务器也是准备后续再做的,以现在的结构而言,支持起来很简单。 现在我正在考虑把单位时间内的多个get合并成一个gets操作,这样对系统性能提升应该有更大的帮助。 应该优先实现“连接多个memcached服务器” |
|
返回顶楼 | |
发表时间:2009-01-31
简单看了一下源码,给后来要的朋友提醒:使用了jdk6里面String的str.getBytes(charset)方法,jdk5支持不了(我下载了jdk6后再看看)。顺便说一下,mina使用的是2.0版本。
不知道楼主可不可以改一下源码让JDK5也可以支持? |
|
返回顶楼 | |