该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2008-07-21
* 作者:张荣华 * 日期:2008-07-21 **/ 看看mina和memcached的联姻 先来解释一下这两个东东的身世 Mina,是什么? Minan是一个network 应用框架,她能很方便的帮助用户开发出高性能和高可扩展性的网络应用程序。官方地址请看:http://mina.apache.org/ Memcached是什么? memcached一个remote cache,它只提供数据存储服务,不过它得java客户端比较不错,还有很多其他语言的客户端,也就是说其周边比较丰富。Memcached的文章太多了,随便一搜一大堆。 现在相信大家对这两个东西有点了解了,接着转入正题吧,我估计猛一看标题,很多童鞋估计都有那么一点云中子的感觉(因为云中子一般在云里或者雾里,所以云中子==云里雾里),从上面的解释来看mina和memcached好像是八竿子打不到一起去的东西。这两个东西怎么能走到一起呢。先看他们能解决什么样的需求。 需求:我们知道,所有的互联网服务几乎都离不开connection这个东东,比如我们打开一个网页,从浏览器发起请求到tomcat接受请求并返回数据,这个过程就开启了一个短连接,数据返回之后这个连接就关闭了,也就是说每个请求其实都是一个新连接的开启和关闭。然后,tomcat中的application向数据库发送一个查询语句,它需要从连接池中拿到一个connection,这个connection一直在pool中,显然这个connection是一个长连接,由此可见一次请求,从浏览器到db再到浏览器既经过了短连接有经过了长连接,我们的生活是离不开连接的。 上面说的这个例子是一个请求的最简单模型,因为我们的application可不只是依赖数据库,尤其在互联网应用中,通常我们的application还依赖于其他的server,比如说我们的互联网应用可能还连接着memcached server,通常,这里也有一个连接池,维护着一堆长连接,那么结束了吗,不,再通常我们的application还依赖于其他的application。好及了,一个相对有点复杂的应用网络,接着往下说,快到重点了 重点: 一般情况下,我们的application依赖于其他application的的时候我们会直接使用http协议,或者再次封装过的http协议(诸如webservice之流),而且这种情况是大多数情况,但是不是全部情况,因为在互联网上我们会遇到各种各样的需求。因为http连接是短连接,每次发起连接的3次握手不可避免,这是造成其并发量不高的重要原因之一(有的人也许会说,即使http并发高有什么用,你的application还是撑不住,但是我想说的是不是所有的应用都是这样的,只是你没有遇到过而已)。那么假设我有一个数据中心,这个数据中心可以提供common数据的服务,这些common的数据会被网站的各个地方获取,这些common的数据之间可能还有一些计算,我可以通过请求的参数来执行对应的操作,比如查询,统计等等(哇,看来能有效的降低数据库的压力啊),那么看来memcached是不行了(不能定制计算),只能自己写这样的应用了,不过以什么样的形势发布接口呢,短连接不行,并发量有限,只能长连接,还要考虑到一点,我的服务的客户端是不定的,有可能是php,也有可能是java,也有可能是python,也有可能是ruby,如何是好啊。 首先长连接是不二选择,高并发,高连接数是我们最中意的,有了这两个特性,我们这个application就可以被其他很多app使用了,就象共享memcached server一样。 其次支持多客户端语言最好是能够有效利用现有资源,比如说不需要自己去开发客户端。 这时候memcached就可以抱着mina出场了。理由: 1 Memcached有众多的客户端,可谓周边齐全,看来非它莫数。 2 mina可以非常方便的开发出server端程序,好姑娘啊。 来吧,看看最简单的示例: Server端主类: import java.io.IOException; import java.net.InetSocketAddress; import java.nio.charset.Charset; import org.apache.mina.common.ByteBuffer; import org.apache.mina.common.IoAcceptor; import org.apache.mina.common.SimpleByteBufferAllocator; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.transport.socket.nio.SocketAcceptor; import org.apache.mina.transport.socket.nio.SocketAcceptorConfig; /** * @author ahuaxuan(aaron zhang) * @since 2008-7-21 * @version $Id$ */ public class MinaServer { private static final int PORT = 11211; public static void main(String[] args) throws IOException { // code will go here next ByteBuffer.setUseDirectBuffers(false); ByteBuffer.setAllocator(new SimpleByteBufferAllocator()); IoAcceptor acceptor = new SocketAcceptor(); SocketAcceptorConfig cfg = new SocketAcceptorConfig(); // cfg.getFilterChain().addLast("logger", new LoggingFilter()); cfg.getFilterChain().addLast( "codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset .forName("UTF-8")))); acceptor.bind(new InetSocketAddress(PORT), new ServerHandler(), cfg); System.out.println("------------ Mina Server start up -----------"); } } 这样,启动这个main方法,就可以建立一个socket server的实例了,欢迎大家来连!!! 相当简单啊,再看看一个重要的ServerHandler类 其中有一个重要的方法: public void messageReceived(IoSession session, Object msg) throws Exception { String str = msg.toString(); String[] parts = str.split(" "); if (parts != null && "get".equals(parts[0])) { StringBuilder sb = new StringBuilder(); sb.append("VALUE").append(" key "); sb.append("1").append(" "); sb.append(str.length()).append(" \r\n "); sb.append(str + "\r\n").append(""); //看看这里吧 session.write(sb.toString()); session.write("END\r\n"); System.out.println("Message written..." + sb.toString()); } else { throw new IOException("unsupportoperation"); } } 哟,这么多\r\n,还有”END\r\n”这种东西?不好意思,这个是memcached协议定的我也没有办法(说到这里大家终于知道了本文其实只不过是用mina来实现memcached协议而已,前面被我那么多废话解释弄晕了吧,嘿嘿)。 看到这里,我想要提醒一下,msg通常是这样的get aaabbbccc,其中aaabbbccc是key,但是用在我们自己的server上,它就可以不是key了,比如说它可以是/getDistrict.do?name=xx&cc=yy`````````,server拿到这样的字符串之后,一解析就知道客户端要什么了,那么就可以返回数据了,是我的话我会用json序列化我的对象,然后返回。只是一定要告诉客户端我的数据包括哪些内容,又快并发又高(再次提醒,我的application可以高并行计算,比如说大多数数据都在内存中哦),hoho,而且任何一个客户端语言都可以享受这种服务哦。 好了,数据成功返回之后,为了让memcached的客户端能够成功解析,我们必须使用memcacached协议,看一段get协议的解释吧(目前主要是使用这个): 一行取回命令如下: get <key>*\r\n <key>* 表示一个或多个键值,由空格隔开的字串 这行命令以后,客户端的等待0个或多个项目,每项都会收到一行文本,然后跟着数据区块。所有项目传送完毕后,服务器发送以下字串: "END\r\n"来指示回应完毕。 服务器用以下形式发送每项内容:VALUE <key> <flags> <bytes>\r\n <data block>\r\n <key> 是所发送的键名 - <flags> 是存储命令所设置的记号 <bytes> 是随后数据块的长度,*不包括* 它的界定符“\r\n” - <data block> 是发送的数据如果在取回请求中发送了一些键名,而服务器没有送回项目列表,这意味着服务器没这些键名(可能因为它们从未被存储,或者为给其他内容腾出空间而被删除,或者到期,或者被已客户端删除)。 这样就可以了,注意,这里只不过是很简单的测试代码(正式代码不便给出),也只不过是提供一个思路而已,大家如果也需要用到这样的场景可以沿着这个思路走下去。 声明:由于ahuaxuan水平有限,文中难免有不妥之处,希望大家不吝赐教。 ps:如果你没有memcached的客户端,最快的见效的是通过telnet,在windows console里输入telnet localhost 11211,就可以了 [/size] 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-07-21
我还是没搞明白这个东西要干什么的?理解没错的话是在memcached和客户端之间又加入了一个tcp server,客户端的请求转发给这个server,由这个server统一去操作memcached以及一些可能的逻辑操作?这个有必要吗?
明白了,原来是用memcached协议实现一个server,这个server不仅仅是缓存,还做其他事情,仅仅是借用memcached协议,适用多种客户端。 |
|
返回顶楼 | |
发表时间:2008-07-21
dennis_zane 写道 明白了,原来是用memcached协议实现一个server,这个server不仅仅是缓存,还做其他事情,仅仅是借用memcached协议,适用多种客户端。 对了,因为很多时候http是不适合的,所以才有这样的需求,尤其是一个互联网站内部,各种应用的交互也是非常频繁,而且性能要求又非常的高,所以才选用长连接,而利用memcached协议又可以让不同的客户端都可以访问,一举两得。 |
|
返回顶楼 | |
发表时间:2008-07-21
ahuaxuan 写道 dennis_zane 写道 明白了,原来是用memcached协议实现一个server,这个server不仅仅是缓存,还做其他事情,仅仅是借用memcached协议,适用多种客户端。 对了,因为很多时候http是不适合的,所以才有这样的需求,尤其是一个互联网站内部,各种应用的交互也是非常频繁,而且性能要求又非常的高,所以才选用长连接,而利用memcached协议又可以让不同的客户端都可以访问,一举两得。 嗯,这是个好思路。可是memcached协议种类有限,对类似RPC这样的请求你们是怎么处理的呢? |
|
返回顶楼 | |
发表时间:2008-07-21
dennis_zane 写道 ahuaxuan 写道 dennis_zane 写道 明白了,原来是用memcached协议实现一个server,这个server不仅仅是缓存,还做其他事情,仅仅是借用memcached协议,适用多种客户端。 对了,因为很多时候http是不适合的,所以才有这样的需求,尤其是一个互联网站内部,各种应用的交互也是非常频繁,而且性能要求又非常的高,所以才选用长连接,而利用memcached协议又可以让不同的客户端都可以访问,一举两得。 嗯,这是个好思路。可是memcached协议种类有限,对类似RPC这样的请求你们是怎么处理的呢? 一般来说,对于企业应用系统,尤其是业务系统(不同group的)之间都是直接面向接口编程,使用spring对http的支持,或者使用hessian,如果是和其他公司互连,web service是第一选择,相同group的业务系统之间我一般会采用jms通信。不过这是一个总体的思路,具体问题还是要具体分析 对于高性能要求,适应多种客户端,提供简单高性能计算功能的应用采用本文的方法比高好,这种情形适合互连网应用,所以说这种方法是为互联网应用而产生的。 而对于rpc,我到现在也没有直接使用过rpc,呵呵,没什么经验 |
|
返回顶楼 | |
发表时间:2008-07-21
已经有现成的jmemcached,也是基于mina:
http://www.thimbleware.com/projects/jmemcached |
|
返回顶楼 | |
发表时间:2008-07-22
已经有现成的GMemcached,是基于Grizzly:
http://code.google.com/p/gmemcached/ |
|
返回顶楼 | |
发表时间:2008-07-22
Grizzly 和 mina 感觉都是基于java NIO的网络框架,功能上有些重叠
|
|
返回顶楼 | |
发表时间:2008-07-22
感觉就是用nio实现了一个memcache的java client吧。跟多语言一点关系都没有把。
|
|
返回顶楼 | |
发表时间:2008-07-22
nickcen 写道 感觉就是用nio实现了一个memcache的java client吧。跟多语言一点关系都没有把。
是吗?你认真看了吗? 楼主这个思路可以作为WS、REST的替代品,做内部应用(异构同构皆可)间的交互。 |
|
返回顶楼 | |