面试

本文探讨Hessian与RMI、WebService等远程调用方式的性能差异,分析Hessian的轻量级特性及二进制RPC协议如何提升效率。同时,比较不同远程调用方式在异构系统通信、负载均衡策略、超时时间设置等方面的优劣。

1、hession客户端 ,Spring通过HessianProxyFactoryBean管理Hessian客户端,HessianProxyFactoryBean最核心的功能是在IoC容器回调方法中产生远程调用代理对象,将代理对象的拦截器设置为HessianClientInterceptor。上面源码中最重要的方法是对远程调用拦截的方法invoke,在该方法中使用JDK的反射机制调用Hessian代理对象的指定方法。而Hessian代理是由Hessain代理器工厂HessianProxyFactory产生的,这个Hessian代理器工厂是有Hessian提供的。 接着看Hessian的具体实现,这块已经和Spring没有关系了。 HessianProxy是hessian client处理客户端请求的核心类,采用proxy模式,代理客户端对远程接口的调用, HessianProxy在invoke方法中实现对调用方法数参数的序列化为预定格式的输出流,调用sendRequest发送请求,获取返回输入流。配置url和name

hesssion服务端,HessianServiceExporter,配置name和ref bean的名字 。HessianServiceExporter继承了HessianExporter,调用父类的invoke处理输入流。在HessianExporter的invoke中调用了HessianSkeleton.invoke(InputStream is, OutputStream os)。 HessianSkeleton是Hessian server端的核心类,主要功能是接收网络输入流(被包装为AbstractHessianInput),反序列化输入流得到methodName和参数,然后根据配置的service,通过反射调用实现类的方法,得到结果后序列化为输出流返回给客户端,流程如下:

2、 RMI的性能最高,这已是公认,RMI底层基于Java远程方法协议(JRMP)和对象序列化技术,而JRMP是直接基于TCP/IP协议的封装,在 网络上传输2 byte的有效数据,对于TCP而言,总共有478 byte被额外传输,而对于RMI, 1645byte被额外传输。可见RMI的效率还是相当不错的。JavaEE标准的EJB就是基于RMI的调用。
  hessian是一个轻量级的remoting on http框架。Hessian没有采用WebService标准的SOAP协议,而是自己实现了一种二进制RPC(Remote Procedure Call Protocol,远程过程调用协议)协议。Hessian的设计理念就是简单高效,使用 Hessian 传输数据量比Soap协议要小很多。这也是为什么Hessian的性能要高于WebService。但是,尽管它再简单高效,它始终是基于Http协议上 封装的,所以还是比Java的RMI效率要差一些。我看过其他的一些研究测试报告称Hessian在传输少量对象时,比RMI还要快速高效,但传输数据结 构复杂的对象或大量数据对象时,较RMI要慢20%左右。这个结论在我的测试中还真没有发现,也许与测试环境或方法有关系吧。
  Java6WebService 和 CXF的性能应该说是基本同级别,前者略高于后者。众所周知WebService是基于Soap协议实现的,而Soap协议是在Http协议基础上的 XML定义和封装。所有的请求和响应都要被转化成符合SOAP标准的XML格式。显然这直接会导致效率的降低。
  XML格式的协议是一种易读易理解的协议,但并不高效。解析和组装XML协议数据流都需要耗费系统的处理时间,所以,WebService的性能不如 Hessian。这里要说一下的是Java6原生的WebService,开发起来非常方便,而且无需额外引入一大堆的Jar包。性能又强于CXF,至于 Axis2和Axis1就更不用说,已经有很多测试表明CXF的性能是Axis2的2倍以上,是Axis1的2-6倍。
  那么既然RMI性能那么好,为什么我们需要那么多其他的远程调用方式呢?这个问题又引发到了一个原始的真理。越原始越底层的技术效率就越高,但局限性 也就越大。RMI是Java的特性,那么它必须基于JVM运行,也就是说RMI无法跨语言运行。而WebService就不同了,Soap是基于标准 Http协议的,是一种与语言无关的字符级协议,所以它可以更好的实现异构系统的通信。这在我们现实环境中是非常有用的,相信大家还是 WebService用的比较多点吧。

3、可见hessian4对超时时间已经做了改进,所以使用时只需要通过Spring设置超时时间即可。超时时间设置setConnectTimeout方法在HessianProxyFactory中,Spring的HessianClientInterceptor是它的子类并包含一个HessianProxyFactory实例,所以可以在HessianClientInterceptor中提供一个setConnectionTimeout方法。

hessian3中需要继承并重写该openConnection方法,在创建http连接的时候通过设置连接超时时间来解决因网络问题阻塞程序继续的问题

3、<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd "> <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 --> <dubbo:application name="yzzs-mobile-consumer" /> <dubbo:registry protocol="zookeeper" address="${zookeeper.address}"/> <!-- 生成远程服务代理,可以和本地bean一样使用userService --> <dubbo:consumer timeout="5000" check="false"/> <dubbo:reference id="broadCastDubboService" interface="com.aweb.weixin.dubbo.service.BroadCastDubboService" check="false" retries="0"/> <dubbo:reference id="weiXinDubboService" interface="com.aweb.weixin.dubbo.service.WeiXinDubboService" check="false" retries="0"/> <dubbo:reference id="timeCalcuateDubboService" interface="com.aweb.hqb.dubbo.service.TimeCalcuateDubboService" check="false" retries="0"/> </beans>

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <bean id="broadCastDubboService" class="com.aweb.weixin.dubbo.service.impl.BroadCastDubboServiceImpl" autowire="byName"></bean> <bean id="weiXinDubboService" class="com.aweb.weixin.dubbo.service.impl.WeiXinDubboServiceImpl" autowire="byName"> </bean> <dubbo:application name="yzzs_web_dubbo" /> <dubbo:provider token="true"></dubbo:provider> <dubbo:registry protocol="zookeeper" address="${zookeeper.address}" /> <dubbo:protocol name="dubbo" port="20881" threadpool="fixed" threads="100" accesslog="/data0/logs/dubbo.log"/> <!-- 和本地bean一样实现服务 --> <dubbo:service interface="com.aweb.weixin.dubbo.service.BroadCastDubboService" ref="broadCastDubboService"/> <dubbo:service interface="com.aweb.weixin.dubbo.service.WeiXinDubboService" ref="weiXinDubboService"/> </beans>

4、负载均衡

Random LoadBalance

  • 随机,按权重设置随机概率。
  • 在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。

RoundRobin LoadBalance

  • 轮循,按公约后的权重设置轮循比率。
  • 存在慢的提供者累积请求问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。

LeastActive LoadBalance

  • 最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
  • 使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。

ConsistentHash LoadBalance

  • 一致性Hash,相同参数的请求总是发到同一提供者。
  • 当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
  • 算法参见:http://en.wikipedia.org/wiki/Consistent_hashing。
  • 缺省只对第一个参数Hash,如果要修改,请配置<dubbo:parameter key="hash.arguments" value="0,1" />
  • 缺省用160份虚拟节点,如果要修改,请配置<dubbo:parameter key="hash.nodes" value="320" />

 

5、

  • Dispatcher
    • all 所有消息都派发到线程池,包括请求,响应,连接事件,断开事件,心跳等。
    • direct 所有消息都不派发到线程池,全部在IO线程上直接执行。
    • message 只有请求响应消息派发到线程池,其它连接断开事件,心跳等消息,直接在IO线程上执行。
    • execution 只请求消息派发到线程池,不含响应,响应和其它连接断开事件,心跳等消息,直接在IO线程上执行。
    • connection 在IO线程上,将连接断开事件放入队列,有序逐个执行,其它消息派发到线程池。
  • ThreadPool
    • fixed 固定大小线程池,启动时建立线程,不关闭,一直持有。(缺省)
    • cached 缓存线程池,空闲一分钟自动删除,需要时重建。
    • limited 可伸缩线程池,但池中的线程数只会增长不会收缩。(为避免收缩时突然来了大流量引起的性能问题)。

配置如:

<dubbo:protocol name="dubbo" dispatcher="all" threadpool="fixed" threads="100" />

 

6、memcache

删除过期item:

延迟删除过期item到查找时进行,可以提高memcache的效率,因为不必每时每刻检查过期item,从而提高CPU工作效率

使用LRU(last recently used)算法淘汰数据:

memcache的过期数据删除机制 
1.当某个值过期后,并没有从内存删除。因此,stats统计时,curr_item有其信息 
2.如果之前没有get过,将不会自动删除,当新值来占用位置时,就只接可以占用 
3.当取其值时,判断是否过期,如果过期,返回空,并且清空,curr_item就减少了 

惰性失效机制 
好处--节省了cpu时间和检测成本 

操作系统内存的管理,常用FIFO,LRU删除 
FIFO:删除老的数据添加新的数据 
LRU:删除不长使用的键,添加新的键 

7、http://blackproof.iteye.com/blog/2039040

转载于:https://my.oschina.net/u/2610056/blog/732922

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值