- 浏览: 4382392 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (163)
- 职场 && 心情 (22)
- Java/Basic (17)
- Java/Compression (7)
- Java/Security (20)
- Java/Maven (3)
- Java/Cache (11)
- Eclipse (4)
- Spring (19)
- ORM/Hibernate (2)
- ORM/iBatis (3)
- DB/NoSQL (11)
- DB/MySQL (7)
- DB/MS SQL Server (4)
- OS/Linux (11)
- OS/Mac (7)
- C/C++ (4)
- Server Architecture/Basic (13)
- Server Architecture/Distributed (17)
- Moblie/Andriod (2)
- WebService (3)
- Objective-C (1)
- Html (1)
- 设计模式 (1)
- Scala (0)
- Kafka (1)
最新评论
-
w47_csdn:
证书安装:在"浏览"选项中选择" ...
Java加密技术(九)——初探SSL -
w47_csdn:
spiritfrog 写道你好,我按照你的步骤,tomcat中 ...
Java加密技术(九)——初探SSL -
liuyachao111:
11楼说的对 用@ControllerAdvicepublic ...
Spring 注解学习手札(八)补遗——@ExceptionHandler -
irayslu:
作者你好, 我把你的源码放在jdk6, jdk7 中运行正常, ...
Java加密技术(五)——非对称加密算法的由来DH -
夏季浅忆-卖小子:
为什么不能解压rar格式的压缩包呢
Java压缩技术(三) ZIP解压缩——Java原生实现
最近接手服务器总被人质疑效率问题,说到底是质疑Spring HttpInvoke的效率问题。好在经过同事们的努力,找到了问题的根源,最终解决了这个问题。
我也顺道整理一下Spring HttpInvoke——那曾经最为熟悉的东西。
Spring HttpInvoke,一种较为常用的、基于Spring架构的服务器之间的远程调用实现,可以说是轻量级的RMI。
最初,我们使用Spring HttpInvoke同步配置数据,刷新多个服务器上的缓存,当然如果用分布式缓存是不是更好 !
使用Spring HttpInvoke,你可以调用远程接口,进行数据交互、业务逻辑操作等等。
废话不说了,上代码!
用户操作接口:
用户类,注意实现Serializable接口,这是执行远程调用传递数据对象的第一要求——数据对象必须实现Serializable接口,因为,要执行序列化/反序列化操作!
覆盖toString()方法,输出用户信息!
再看UserServiceImpl实现:
只把用户信息打出来即可说明调用效果!
看applicationContext.xml
我们要把userService暴露出去,这样外部就可以通过http接口调用这个接口的实现了。
说说HttpInvokerServiceExporter,这个类用来在服务器端包装需要暴露的接口。
熟悉service,定义具体的实现类!
熟悉serviceInterface指向需要暴露的接口,注意使用value标注接口名称!
最后再看servlet.xml配置
直接将请求指向刚才配置的userService
现在我们之间访问一下http://localhost:8080/spring/service/
这就说明,服务器端配置已经成功了!如果在日志中频繁得到这种异常,那很可能服务器被恶意访问了!
再看客户端实现:
我们做了什么?Nothing!就跟调用一般Spring容器中的实现一样!
再看applicationContext.xml:
这里我们可以通过Spring容器调用userService,而实际上,他是一个HttpInvokerProxyFactoryBean,在这个配置里,定义了访问地址serviceUrl,和访问接口serviceInterface。
执行测试!
如果我们这样写,其实默认调用了SimpleHttpInvokerRequestExecutor做实现,这个实现恐怕只能作为演示来用!
这也是效率问题所在!!!
为提高效率,应该通过Commons-HttpClient!
我们需要做什么?导入这个jar,改改xml就行!
通过HttpClient,我们可以配置超时时间timeout和连接超时connectionTimeout两个属性,这样,服务器执行操作时,如果超时就可以强行释放连接,这样可怜的tomcat不会因为HttpInvoke连接不释放而被累死!
回头看了一眼我N多年前的代码,万岁,我当时确实是这么实现的!好在没有犯低级错误!!!
执行操作!
这时,转为org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor实现了!
不过同事认为,这个效率还是不够高!!!
再改,改什么?还是xml!
改用MultiThreadedHttpConnectionManager,多线程!!!
测试就不说了,实践证明:
默认实现,服务器平均10s左右才能响应一个请求。
多线程实现,服务器平均20ms左右响应一个请求。
这简直不是一个数量级!!!
注意:在HttpClient的3.1版本中,已不支持如下配置,相应的方法已经废弃!
如果仔细看看文档,
commons 系列的实现怎么会不考虑多线程呢?人家默认实现就是多线程的!同事多虑了!
当然,同事还补充了一句,需要控制连接数!
难怪,这里要设置
默认啥情况?
技高一筹!
赶紧记下来,供大家参考!
详情见附件!
许久没写博客了,今天终于舒展了一把!
我也顺道整理一下Spring HttpInvoke——那曾经最为熟悉的东西。
Spring HttpInvoke,一种较为常用的、基于Spring架构的服务器之间的远程调用实现,可以说是轻量级的RMI。
最初,我们使用Spring HttpInvoke同步配置数据,刷新多个服务器上的缓存,当然如果用分布式缓存是不是更好 !
使用Spring HttpInvoke,你可以调用远程接口,进行数据交互、业务逻辑操作等等。
废话不说了,上代码!
用户操作接口:
/** * @author <a href="mailto:zlex.dongliang@gmail.com">梁栋</a> * @since 1.0 */ public interface UserService { /** * 获得用户 * * @param username * 用户名 * @return */ User getUser(String username); }
用户类,注意实现Serializable接口,这是执行远程调用传递数据对象的第一要求——数据对象必须实现Serializable接口,因为,要执行序列化/反序列化操作!
/** * @author <a href="mailto:zlex.dongliang@gmail.com">梁栋</a> * @since 1.0 */ public class User implements Serializable { private static final long serialVersionUID = 5590768569302443813L; private String username; private Date birthday; /** * @param username * @param birthday */ public User(String username, Date birthday) { this.username = username; this.birthday = birthday; } // 省略 /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { return String.format("%s\t%s\t", username, birthday); } }
覆盖toString()方法,输出用户信息!
再看UserServiceImpl实现:
/** * @author <a href="mailto:zlex.dongliang@gmail.com">梁栋</a> * @since 1.0 */ public class UserServiceImpl implements UserService { private Logger logger = Logger.getLogger(UserServiceImpl.class); /* * (non-Javadoc) * * @see * org.zlex.spring.httpinvoke.service.UserService#getUser(java.lang.String) */ @Override public User getUser(String username) { if (logger.isDebugEnabled()) { logger.debug("username:[" + username + "]"); } User user = new User(username, new Date()); if (logger.isDebugEnabled()) { logger.debug("user:[" + user + "]"); } return user; } }
只把用户信息打出来即可说明调用效果!
看applicationContext.xml
<bean id="userService" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter"> <property name="service"> <bean class="org.zlex.spring.httpinvoke.service.impl.UserServiceImpl" /> </property> <property name="serviceInterface" value="org.zlex.spring.httpinvoke.service.UserService" /> </bean>
我们要把userService暴露出去,这样外部就可以通过http接口调用这个接口的实现了。
说说HttpInvokerServiceExporter,这个类用来在服务器端包装需要暴露的接口。
熟悉service,定义具体的实现类!
<property name="service"> <bean class="org.zlex.spring.httpinvoke.service.impl.UserServiceImpl" /> </property>
熟悉serviceInterface指向需要暴露的接口,注意使用value标注接口名称!
<property name="serviceInterface" value="org.zlex.spring.httpinvoke.service.UserService" />
最后再看servlet.xml配置
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="urlMap"> <map> <entry key="*" value-ref="userService" /> </map> </property> </bean>
直接将请求指向刚才配置的userService
现在我们之间访问一下http://localhost:8080/spring/service/
这就说明,服务器端配置已经成功了!如果在日志中频繁得到这种异常,那很可能服务器被恶意访问了!
再看客户端实现:
/** * @author <a href="mailto:zlex.dongliang@gmail.com">梁栋</a> * @since 1.0 */ public class UserServiceTest { private Logger logger = Logger.getLogger(UserServiceTest.class); private ApplicationContext context; private UserService userService; @Before public void initialize() { context = new ClassPathXmlApplicationContext("applicationContext.xml"); userService = (UserService) context.getBean("userService"); } @Test public void getUser() { User user = userService.getUser("zlex"); if (logger.isDebugEnabled()) { logger.debug("user[" + user + "]"); } } }
我们做了什么?Nothing!就跟调用一般Spring容器中的实现一样!
再看applicationContext.xml:
<bean id="userService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean"> <property name="serviceUrl" value="http://localhost:8080/spring/service" /> <property name="serviceInterface" value="org.zlex.spring.httpinvoke.service.UserService" /> </bean>
这里我们可以通过Spring容器调用userService,而实际上,他是一个HttpInvokerProxyFactoryBean,在这个配置里,定义了访问地址serviceUrl,和访问接口serviceInterface。
执行测试!
如果我们这样写,其实默认调用了SimpleHttpInvokerRequestExecutor做实现,这个实现恐怕只能作为演示来用!
这也是效率问题所在!!!
为提高效率,应该通过Commons-HttpClient!
我们需要做什么?导入这个jar,改改xml就行!
<bean id="userService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean"> <property name="serviceUrl" value="http://localhost:8080/spring/service" /> <property name="serviceInterface" value="org.zlex.spring.httpinvoke.service.UserService" /> <property name="httpInvokerRequestExecutor"> <ref bean="httpInvokerRequestExecutor" /> </property> </bean> <bean id="httpInvokerRequestExecutor" class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor"> <property name="httpClient"> <bean class="org.apache.commons.httpclient.HttpClient"> <property name="connectionTimeout" value="2000" /> <property name="timeout" value="5000" /> </bean> </property> </bean>
通过HttpClient,我们可以配置超时时间timeout和连接超时connectionTimeout两个属性,这样,服务器执行操作时,如果超时就可以强行释放连接,这样可怜的tomcat不会因为HttpInvoke连接不释放而被累死!
回头看了一眼我N多年前的代码,万岁,我当时确实是这么实现的!好在没有犯低级错误!!!
执行操作!
这时,转为org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor实现了!
不过同事认为,这个效率还是不够高!!!
再改,改什么?还是xml!
<bean id="httpInvokerRequestExecutor" class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor"> <property name="httpClient"> <bean class="org.apache.commons.httpclient.HttpClient"> <property name="connectionTimeout" value="2000" /> <property name="timeout" value="5000" /> <property name="httpConnectionManager"> <ref bean="multiThreadedHttpConnectionManager" /> </property> </bean> </property> </bean> <bean id="multiThreadedHttpConnectionManager" class="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager"> <property name="params"> <bean class="org.apache.commons.httpclient.params.HttpConnectionManagerParams"> <property name="maxTotalConnections" value="600" /> <property name="defaultMaxConnectionsPerHost" value="512" /> </bean> </property> </bean>
改用MultiThreadedHttpConnectionManager,多线程!!!
测试就不说了,实践证明:
默认实现,服务器平均10s左右才能响应一个请求。
多线程实现,服务器平均20ms左右响应一个请求。
这简直不是一个数量级!!!
注意:在HttpClient的3.1版本中,已不支持如下配置,相应的方法已经废弃!
<property name="connectionTimeout" value="2000" /> <property name="timeout" value="5000" />
如果仔细看看文档,
引用
HttpClient that uses a default MultiThreadedHttpConnectionManager.
commons 系列的实现怎么会不考虑多线程呢?人家默认实现就是多线程的!同事多虑了!
当然,同事还补充了一句,需要控制连接数!
难怪,这里要设置
<bean class="org.apache.commons.httpclient.params.HttpConnectionManagerParams"> <property name="maxTotalConnections" value="600" /> <property name="defaultMaxConnectionsPerHost" value="512" /> </bean>
默认啥情况?
引用
maxConnectionsPerHost 每个主机的最大并行链接数,默认为2
public static final int DEFAULT_MAX_HOST_CONNECTIONS = 2;
maxTotalConnections 客户端总并行链接最大数,默认为20
public static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 20;
public static final int DEFAULT_MAX_HOST_CONNECTIONS = 2;
maxTotalConnections 客户端总并行链接最大数,默认为20
public static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 20;
技高一筹!
赶紧记下来,供大家参考!
详情见附件!
许久没写博客了,今天终于舒展了一把!
评论
8 楼
jd2bs
2015-05-12
3.1版本,俩个超时时间已经移到params里面了
client.getHttpConnectionManager().getParams()
.setConnectionTimeout(3000);
client.getHttpConnectionManager().getParams().setSoTimeout(3000);
client.getHttpConnectionManager().getParams()
.setConnectionTimeout(3000);
client.getHttpConnectionManager().getParams().setSoTimeout(3000);
7 楼
icur
2011-04-27
楼主写的不错哦
6 楼
wu_yong988
2011-03-30
不错,楼主,学习啦
5 楼
qkjava
2011-01-05
这个为工程与项目间的关系,既代码的模块化提供了一个很好的解决方案。
如果我们把代码归为工程,而市场认为是个项目的话。
市场所推的一个项目由若干个 工程模块来组成。
它比webservice更好的解决模块化问题。
如果我们把代码归为工程,而市场认为是个项目的话。
市场所推的一个项目由若干个 工程模块来组成。
它比webservice更好的解决模块化问题。
4 楼
newwpp
2010-12-23
受用 正好用到
3 楼
ilovehome
2010-07-02
不错,
2 楼
ligh0209
2010-07-01
1 楼
sdtm1016
2010-07-01
发表评论
-
征服 Redis + Jedis + Spring (三)—— 列表操作
2013-03-06 16:16 83966一开始以为Spring下操 ... -
Memcached笔记——(四)应对高并发攻击
2012-09-13 09:48 28935近半个月过得很痛苦,主要是产品上线后,引来无数机器用户恶意 ... -
征服 Redis + Jedis + Spring (二)—— 哈希表操作(HMGET HMSET)
2012-08-29 18:29 82320不得不说,用哈希操作来存对象,有点自讨苦吃! 不过,既然 ... -
征服 Redis + Jedis + Spring (一)—— 配置&常规操作(GET SET DEL)
2012-08-29 16:30 157467有日子没写博客了,真的是忙得要疯掉。 完成项目基础架构搭建 ... -
Spring 注解学习手札(八)补遗——@ExceptionHandler
2012-08-17 18:35 84117Spring注解,改变了我的 ... -
Spring 注解学习手札(七) 补遗——@ResponseBody,@RequestBody,@PathVariable
2012-08-10 21:27 439665最近需要做些接口服务,服务协议定为JSON,为了整合在Spri ... -
征服 Kestrel + XMemcached + Spring TaskExecutor
2012-07-30 14:43 6207上一篇征服 Kestrel + XMemcached只是对Ke ... -
征服Spring AOP—— @AspectJ
2012-04-10 12:01 18658接N年前写的一篇Spring AOP相关的内容征服Spring ... -
Memcached笔记——(二)XMemcached&Spring集成
2012-04-01 09:55 42322今天研究Memcached的Java的Client,使用XMe ... -
Spring util
2011-02-24 12:02 01,<util:constant/> 取代了之前通 ... -
Spring 注解学习手札(六) 测试
2010-02-05 16:28 53161既然系统基于注解自成一体,那么基于Spring的测试是否可以依 ... -
Spring 注解学习手札(五) 业务层事务处理
2010-02-04 16:11 25350控制器层、持久层都有 ... -
Spring 注解学习手札(四) 持久层浅析
2010-01-29 11:11 22581今天,我们玩玩数据库,搞搞持久层。不搞太复杂的东西,Sprin ... -
Spring 注解学习手札(三) 表单页面处理
2010-01-26 15:21 40482昨天小歇一天,看着两篇博客迅速飙升的点击率,十分欣慰。今天来研 ... -
Spring 注解学习手札(二) 控制层梳理
2010-01-24 15:53 36569昨天对Spring注解有了一 ... -
Spring 注解学习手札(一) 构建简单Web应用
2010-01-23 13:40 83405近来工作发生了一些变化,有必要学习一下Spring注解了! ... -
征服Spring AOP—— Schema
2008-09-03 17:41 6436自从开始使用Spring,就接触到AOP,但一直未能深入,沉淀 ... -
关于Spring中Commons Validator的使用说明
2008-09-01 09:57 8138关于Spring中Commons Validator的使用说明 ... -
acegi 我该从哪里取到用户的信息
2006-09-21 17:32 5777项目需要 用acegi做为安全屏障,按acegi 1.0.1 ...
相关推荐
上文我们利用Spring rmi实现了Spring的远程访问(Spring 实现远程访问详解——rmi),本文主要讲解利用HttpInvoke实现远程访问。 Spring httpInvoker使用标准java序列化机制,通过Http暴露业务服务。如果你的参数和...
Spring配置 Spring 配置 映射 加注释!!!!Spring配置 Spring 配置 映射 加注释!!!!
spring ioc指的是控制反转,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。交由Spring容器统一进行管理,从而实现松耦合
论坛系统(Struts 2+Hibernate+Spring实现)!!!!!!!!!!!
论坛系统项目(Struts 2+Hibernate+Spring实现)论坛系统项目(Struts 2+Hibernate+Spring实现)论坛系统项目(Struts 2+Hibernate+Spring实现)论坛系统项目(Struts 2+Hibernate+Spring实现)论坛系统项目(Struts...
基于Spring Boot和Spring Cloud实现微服务架构学习(一).pdf基于Spring Boot和Spring Cloud实现微服务架构学习(一).pdf基于Spring Boot和Spring Cloud实现微服务架构学习(一).pdf基于Spring Boot和Spring Cloud实现...
基于Spring Boot和Spring Cloud实现微服务架构学习(一).docx基于Spring Boot和Spring Cloud实现微服务架构学习(一).docx基于Spring Boot和Spring Cloud实现微服务架构学习(一).docx基于Spring Boot和Spring Cloud...
Spring IoC实现Spring IoC实现Spring IoC实现Spring IoC实现
基于SpringCloud微服务实现的互联网招聘平台源码 基于SpringCloud微服务实现的互联网招聘平台源码 基于SpringCloud微服务实现的互联网招聘平台源码 基于SpringCloud微服务实现的互联网招聘平台源码 基于...
用STS(Spring Tool Suite)开发的,spring mvc + spring security 实现的最简单的登录系统,无数据库。
springboot+ spring security实现登录认证
仅用四步就整合好SpringSecurity+JWT实现登录认证!.doc
Spring实现AOP以及AOP的定义Spring实现AOP以及AOP的定义
Spring通过xml实现IOC,Spring通过xml实现IOC,Spring通过xml实现IOC
代码用spring hibernate实现;分层很清晰;实现了一个完整的网上购物过程....
mysql+spring mvc 实现分页,可以实现增加修改删除等操作
使用Spring的注解方式实现AOP的细节
基于注解实现SpringAop基于注解实现SpringAop基于注解实现SpringAop
狂神Spring Cloud源码 免费下载!!!