uniseraph
大牛写了一个用mina实现的memcached java client.最近正好在研究mina,来的早不如来的巧,现在跟大家分享一下我今天一天的劳动成果,望大家指教
该项目的基本思想是:使用一个IoSession池,当前默认是使用SimpleCircularQueue,借助于mina的机制,实现高并发请求的。目前只有set和get功能。现在从set开始分析。
在session建立之后,通过MemcachedClientHandler#sessionCreated(IoSession)在每个session中加入一个List和一个Map,在MemcachedClient中的set方法中构造SetCommand然后使用pool发送。MemcachedMutexIoSessionPool#send()方法可以选择是否使用异步调用,但是我感觉这里的异步调用有些问题,同步当然是没有问题,通过holder.getContext().await()就可以阻塞send方法等待结果。但是如果是异步方式的话,返回null,我感觉不妥,客户端得到null?如果是取得数据的话,是否可以返回一个MemcachedResponse的子类,但是想得到结果时阻塞呢?当然这只是我自己YY的。MemcachedMutexIoSessionPool#send()代码如下。
public MemcachedResponse send(MemcachedCommand message, boolean sync) {
IoSession session = selectSession();
RequestContextHolder holder = new RequestContextHolder();
holder.getContext().setCommand(message);
if (sync) {
session.write(holder);
try {
holder.getContext().await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (!holder.getContext().isSuccess()) {
if (log.isInfoEnabled())
log.info(String.format("time out"));
}
return holder.getContext().getReponse();
} else {
session.write(holder);
return null;
}
}
调用sessio.write(holder)后,通过await方法阻塞,但是MINA会去调用encoder对消息进行encode,这里使用的是CommandEncoder,代码如下:
public void encode(IoSession session, Object message,
ProtocolEncoderOutput out) throws Exception {
RequestContextHolder holder = (RequestContextHolder) message;
IoBuffer buf = holder.getContext().getCommand().toBuffer(
MemcachedConstants.DEFAULT_CHARSET);
buf.setAutoExpand(true);
buf.flip();
ConcurrentHashMap<IoBuffer, RequestContext> encodedMessage2Message = (ConcurrentHashMap<IoBuffer, RequestContext>) session
.getAttribute("encodedMessage2Message");
RequestContext newItem = encodedMessage2Message.putIfAbsent(buf,
holder.getContext());
if (newItem == null) {
out.write(buf);
} else {
if(log.isDebugEnabled()){
log.debug("reusing command.");
}
holder.setContext(newItem);
}
}
首先将command转换成IoBuffer,然后把IoBuffer和ReuestContext对于放入session中的map中。
消息发送完毕后,MINA的filter机制开始工作,AppendFilter中的messageSent方法拦截session,将刚刚session中map存储的RequestContext取出来,放入到session中的队列中。在memcached通讯层分析
中提到过memcache在同一个socket上,命令处理是按顺序的。根据这个就可以按照先后顺序将RequestContext加入到队列中就可以。
AppenderFilter代码:
public void messageSent(NextFilter nextFilter, IoSession session,
WriteRequest writeRequest) throws Exception {
Object obj = writeRequest.getMessage();
if (obj instanceof IoBuffer) {
IoBuffer buf = (IoBuffer) obj;
if (buf.limit() != 0) {
ConcurrentHashMap<IoBuffer, RequestContext> encodedMessage2Message = SessionUtil
.getEncodedMessage2Message(session);
LinkedBlockingQueue<RequestContext> queue = SessionUtil
.getCommandQueue(session);
RequestContext item = encodedMessage2Message.remove(buf);
if (item == null) {
log.error("Can't find the command :" + buf + "in the map");
log.error("map :" + encodedMessage2Message.toString());
throw new IllegalStateException();
}
queue.add(item);
}
}
nextFilter.messageSent(session, writeRequest);
}
然后就是response的decode,这里使用LinedReponseDecoder,在decode时,先使用TextlineDecoder首先进行decode,这里有一个hint,就是decode方法需要带一个ProtocolDecoderOutput的参数,其实ProtocolDecoderOutput只是decode方法的一个callback,这里,首先从session中取出先前存储的list,在TextlineDecoder decode完成后,将结果加到context中。具体看代码:
public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)
throws Exception {
final List<String> context = (List<String>) session
.getAttribute(MemcachedConstants.LINES_CONTEXT);
decoder.decode(session, in, new ProtocolDecoderOutput() {
public void flush() {
/**
* ignore
*/
}
public void write(Object message) {
context.add(message.toString());
}
});
最后decode方法再根据先前的先来先服务原则,解析对于的response就可以了。这部分比较简单了。
总结这个项目,重点是借助于mina的处理机制,对mina有很深了解的看这个项目应该不难,主要是思维比较好。
学习中……
分享到:
相关推荐
**Memcached Java源码分析——Performance分支** Memcached是一款高性能的分布式内存对象缓存系统,广泛应用于Web应用中,用于缓解数据库的负载。在Java环境中,我们常常使用Java客户端库来与Memcached服务器进行...
接下来,让我们看看如何在Java代码中使用Memcached。首先,我们需要创建一个`MemcachedClient`实例,连接到运行的Memcached服务器: ```java import net.spy.memcached.AddrUtil; import ...
8. **src**: 源代码目录,其中包含了Java Memcached客户端的源码。通过查看源码,开发者可以深入理解其工作原理,甚至进行自定义修改和扩展。 9. **doc**: 可能包含了更详细的项目文档,如用户指南、开发者文档等,...
memcached在Java客户端调用时的源码。memcached源码中有一个bug,ip的传参形式为192.168.1.1:12301,到了sockiopool.java中用split(";")来解析ip和端口。这种情况在ipv6的环境下是行不通的。因为v6地址是[xxxx:xx:...
或者,如果你选择手动编译安装,可以从官方网站获取源代码,然后执行以下步骤: ```bash wget http://www.memcached.org/files/memcached-1.x.x.tar.gz tar -zxvf memcached-1.x.x.tar.gz cd memcached-1.x.x ./...
在实际使用中,通常会开发 Java 客户端库来封装 Memcached 的操作,提供更方便的 API。封装过程可能包括: 1. **连接池管理**:为了提高性能,客户端可以使用连接池管理多个到 Memcached 服务器的连接,避免频繁...
在Java环境中,有很多客户端库可以与Memcached进行交互,其中之一就是我们关注的"memcached java源码"。这个源码来自项目的master分支,意味着它是项目的主要开发线,通常包含了最新的稳定功能和改进。 Memcached ...
本文主要介绍了如何在Java项目中集成和使用Memcached这一开源工具,涉及到源码级别的操作,如创建`MemcachedClient`,设置、获取和删除缓存项。这些都是实际开发中非常实用的技术点,可以帮助开发者有效地优化应用...
在Java代码中,你可以通过`MemcachedClientBuilder`来创建一个连接池实例,然后通过`build()`方法建立到Memcached服务器的连接。 ```java MemcachedClientIF client = new MemcachedClientBuilder().build(); ``` #...
标题 "spring调用memcached client for java" 涉及的是如何在Java应用程序中,特别是Spring框架下,集成和使用Memcached作为缓存系统。Memcached是一个高性能的分布式内存对象缓存系统,常用于减轻数据库负载,提升...
在Java中,我们可以使用各种客户端库与Memcached通信,如Spymemcached、Xmemcached、MemcachedClient等。这些库提供了方便的方法来操作Memcached服务器,包括设置、获取、删除和过期等操作。 3. **源码结构分析** ...
Spring Memcached 是一个用于在Spring应用中集成Memcached缓存服务的框架。Memcached是一种分布式内存对象缓存系统,常用于提高网站数据读取...通过源码分析,我们可以了解其工作原理,并根据实际需求进行调整和优化。
**Memcached与Java实例文档详解** Memcached是一种高性能、分布式内存对象缓存系统,它能够减轻数据库的负担,提高Web应用的性能。在Java开发环境中,Memcached被广泛用于存储临时数据,提升应用响应速度。本文将...
Java 使用 Memcached 演示 Memcached 是一个高性能、分布式的内存对象缓存系统,广泛应用于减轻数据库负载,提高Web应用的响应速度。在Java中,我们可以借助各种客户端库来与Memcached进行交互。本篇文章将深入探讨...
在上述代码中,我们首先创建了一个`MemcachedClient`实例,通过指定服务器地址和端口连接到Memcached服务。然后,我们使用`set`方法存储键值对,`get`方法获取数据,`delete`方法删除键。最后,记得在完成操作后关闭...
5. **源码分析** 压缩包中的源码应该包含了以上操作的实现,你可以通过阅读代码了解具体细节。注意检查配置文件(如:memcached.properties),它可能包含了连接池配置、超时设置等信息。 6. **测试** 编写测试...
这通常通过包管理器(如Ubuntu的`apt-get`或CentOS的`yum`)完成,或者从官方网站下载源代码编译安装。 - 安装完成后,启动Memcached服务。默认情况下,它会在11211端口监听连接。 2. **Java客户端库** - 在Java...
**Memcached之Java客户端开发详解** Memcached是一种高性能、分布式内存对象缓存系统,用于减少数据库负载,提高网站性能。它通过将数据存储在内存中,以快速响应来自应用程序的请求,避免了反复读取数据库的开销。...
本主题将深入探讨如何基于Java客户端对Memcached进行封装,以便更高效地在Java应用中使用它。 首先,我们需要理解Java中的Memcached客户端库,如spymemcached或xmemcached。这两个库都提供了与Memcached服务器通信...
这个压缩包文件包含了`memcached-java`客户端的源代码和CHM格式的API文档,版本为2.8。CHM(Compiled Help Manual)是微软的一种帮助文件格式,通常用于存放程序的离线帮助文档。在这个案例中,CHM API文档是开发者...