- 浏览: 4402826 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (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 84095一开始以为Spring下操 ... -
Memcached笔记——(四)应对高并发攻击
2012-09-13 09:48 29065近半个月过得很痛苦,主要是产品上线后,引来无数机器用户恶意 ... -
征服 Redis + Jedis + Spring (二)—— 哈希表操作(HMGET HMSET)
2012-08-29 18:29 82412不得不说,用哈希操作来存对象,有点自讨苦吃! 不过,既然 ... -
征服 Redis + Jedis + Spring (一)—— 配置&常规操作(GET SET DEL)
2012-08-29 16:30 157642有日子没写博客了,真的是忙得要疯掉。 完成项目基础架构搭建 ... -
Spring 注解学习手札(八)补遗——@ExceptionHandler
2012-08-17 18:35 84308Spring注解,改变了我的 ... -
Spring 注解学习手札(七) 补遗——@ResponseBody,@RequestBody,@PathVariable
2012-08-10 21:27 440230最近需要做些接口服务,服务协议定为JSON,为了整合在Spri ... -
征服 Kestrel + XMemcached + Spring TaskExecutor
2012-07-30 14:43 6268上一篇征服 Kestrel + XMemcached只是对Ke ... -
征服Spring AOP—— @AspectJ
2012-04-10 12:01 18730接N年前写的一篇Spring AOP相关的内容征服Spring ... -
Memcached笔记——(二)XMemcached&Spring集成
2012-04-01 09:55 42413今天研究Memcached的Java的Client,使用XMe ... -
Spring util
2011-02-24 12:02 01,<util:constant/> 取代了之前通 ... -
Spring 注解学习手札(六) 测试
2010-02-05 16:28 53239既然系统基于注解自成一体,那么基于Spring的测试是否可以依 ... -
Spring 注解学习手札(五) 业务层事务处理
2010-02-04 16:11 25429控制器层、持久层都有 ... -
Spring 注解学习手札(四) 持久层浅析
2010-01-29 11:11 22669今天,我们玩玩数据库,搞搞持久层。不搞太复杂的东西,Sprin ... -
Spring 注解学习手札(三) 表单页面处理
2010-01-26 15:21 40588昨天小歇一天,看着两篇博客迅速飙升的点击率,十分欣慰。今天来研 ... -
Spring 注解学习手札(二) 控制层梳理
2010-01-24 15:53 36643昨天对Spring注解有了一 ... -
Spring 注解学习手札(一) 构建简单Web应用
2010-01-23 13:40 83763近来工作发生了一些变化,有必要学习一下Spring注解了! ... -
征服Spring AOP—— Schema
2008-09-03 17:41 6484自从开始使用Spring,就接触到AOP,但一直未能深入,沉淀 ... -
关于Spring中Commons Validator的使用说明
2008-09-01 09:57 8197关于Spring中Commons Validator的使用说明 ... -
acegi 我该从哪里取到用户的信息
2006-09-21 17:32 5838项目需要 用acegi做为安全屏障,按acegi 1.0.1 ...
相关推荐
上文我们利用Spring rmi实现了Spring的远程访问(Spring 实现远程访问详解——rmi),本文主要讲解利用HttpInvoke实现远程访问。 Spring httpInvoker使用标准java序列化机制,通过Http暴露业务服务。如果你的参数和...
**Spring Ioc 实现原理详解** Spring Ioc(Inversion of Control,控制反转)是Spring框架的核心特性之一,它改变了传统应用程序中...在实际开发中,理解并熟练运用Spring Ioc,对于提升开发效率和质量具有重要作用。
Spring Batch 是一个强大的、可扩展的Java框架,专门用于处理批量数据处理任务,包括大量数据库数据的读取、处理和写入。...通过合理配置和优化,可以有效地提升批量处理的效率和稳定性,是企业级应用的理想选择。
论坛系统(Struts 2+Hibernate+Spring实现)!!!!!!!!!!!
论坛系统项目(Struts 2+Hibernate+Spring实现)论坛系统项目(Struts 2+Hibernate+Spring实现)论坛系统项目(Struts 2+Hibernate+Spring实现)论坛系统项目(Struts 2+Hibernate+Spring实现)论坛系统项目(Struts...
- 通常包含src/main/java目录下的Controller、Service、DAO层以及配置类,src/main/resources下可能有Spring MVC和Spring Security的配置文件,webapp下是静态资源和视图文件。 7. **学习重点**: - 理解Spring ...
本篇文章将深入探讨Spring AOP的内部实现,以及如何通过源代码理解其DataSource实现和FactoryBean模式。 首先,让我们了解AOP的基本概念。AOP的核心思想是“切面”,它封装了特定的关注点,如日志记录、事务管理、...
总的来说,"spring+spring mvc+mybatis框架整合实现超市货物管理系统"是一个涵盖后端开发基础技能的项目,涉及了JavaEE的多个层面,从Web层的路由处理,到业务逻辑的实现,再到数据库操作,以及用户认证和分页显示等...
通过分析这些代码,你可以理解如何将Spring Security与数据库集成,实现动态权限管理。 总的来说,Spring Security的动态授权功能使得权限管理变得更加灵活和高效。通过对源代码的适当修改,我们可以构建一个完全可...
Spring IOC(Inversion of Control,控制反转)是Spring框架的核心特性,它负责管理对象的生命周期和依赖关系。在本文中,我们将深入探讨...在实际项目中,还可以结合注解配置和自动装配进一步简化配置,提升开发效率。
本教程将通过一个名为"spring-mvc-demo"的项目,详细介绍如何使用Spring框架来实现RESTful Web服务。 一、Spring MVC与RESTful Web服务 Spring MVC是Spring框架的一部分,专门用于处理Web请求和响应。RESTful Web...
通过学习这些示例,你可以了解到如何定义OAuth2的客户端、如何配置授权服务器和资源服务器,以及如何在实际应用中实现SSO。 总结来说,Spring Cloud结合OAuth2提供了强大的安全机制,可以有效地管理和控制微服务的...
在这个案例中,我们将探讨如何整合OSGI、Spring、Mybatis以及Spring MVC来实现一个登录应用。这个教程旨在帮助开发者理解如何在OSGI环境中集成这些流行的Java技术,以构建灵活且可扩展的应用程序。 首先,我们需要...
本篇文章将详细探讨Spring实现AOP的四种主要方法:基于代理的方式、基于AspectJ的注解方式、基于XML的AOP配置以及基于Java的AOP配置。 1. 基于代理的实现 Spring的AOP支持两种代理类型:JDK动态代理和CGLIB代理。...
通过这些源码,学习者可以了解到Spring Cloud如何集成Eureka实现服务注册与发现,如何利用Feign进行声明式服务调用,以及如何借助Hystrix实现服务容错和降级。同时,配置中心(Config Server)和客户端的使用也展示...
Spring实现简单登录注册功能 1.注册信息写入mysql数据库 2.可以用注册的账号来进行登录 3.利用cookie,实现登录成功界面显示用户名 4.界面使用表单验证和ajax,进行规则判断和相应显示
本项目为spring-boot+webSocket实现的向日葵远程控制项目 向日葵是一款很好用的远程操作软件。 一直很好奇这种软件的基本原理是如何的? 今天带大家通过一个简单的项目来探究一下,并实现一个简单的远程操控软件 ...
这个项目是一个基于Spring MVC和Spring JDBC的简单用户管理应用,旨在帮助初学者理解如何在实际开发中实现用户登录、注册以及信息修改功能。Spring MVC是Spring框架的一个模块,主要用于构建Web应用程序,而Spring ...