`
13shu
  • 浏览: 73417 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Spring3.2异步处理http请求

    博客分类:
  • java
 
阅读更多

解决的问题:

目前系统中,有个别的查询比较慢,大概需要几秒才能返回结果。在大量使用此功能时导致系统变慢。

可能会出现的原因:

1、程序问题(包括业务设计、业务逻辑处理、数据库优化等)

2、架构问题

3、其他原因

此处就第二点做一下分析:

用户查询开始到返回结果到页面,此处是一个同步的过程,如果做成异步的能提高系统响应的性能,最近发现servlet3.0有一个新的特性,新增HTTP请求的异步处理,详细请参考

由于项目采用的SpringMVC做的,所以查看了下SpringMVC的资料,发现3.2版本对于异步处理有良好的封装。开始做实验哭

 

  • 配置servlet3.0

     web.xml中配置

    

 

<web-app version="3.0" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
 

 

<servlet>
		<servlet-name>test</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>2</load-on-startup>
		<async-supported>true</async-supported>
	</servlet>

	<servlet-mapping>
		<servlet-name>test</servlet-name>
		<url-pattern>/</url-pattern>
    <servlet-mapping>

 

  • Spring控制层代码修改返回类型为Callable模型
public Callable<String> processUpload(HttpServletRequest request,
			final HttpServletResponse response) {
		System.out.println("线程名称:"+Thread.currentThread().getName());
		return new Callable<String>() {
			public String call() throws Exception {
				try {
					System.out.println("线程名称:"+Thread.currentThread().getName());
					response.setContentType("text/plain;charset=utf-8");
					response.getWriter().write("nihao");
					response.getWriter().close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				return null;
			}
		};
	}

控制台输出内容:

13:46:59,875 INFO  [stdout] (http-localhost-127.0.0.1-8080-2) 线程名称:http-localhost-127.0.0.1-8080-2

13:48:57,609 INFO  [stdout] (abc-2) 线程名称:abc-2

Callable内部与外部输出了当前线程的名字,发现线程被切换了,request请求的线程被释放到了web容器中(如:tomcat)。

 

问题貌似解决了酷,离下班时间还早于是乎想看下这个神奇的过程是怎么发生的,看了下Spring的源代码,不看不知道,一看吓一跳。

 

Spring返回的Callable被RequestMappingHandlerAdapter拦截处理了,结果发现Callable被SimpleAsyncTaskExecutor线程池处理了,经过细心的查看代码发现SimpleAsyncTaskExecutor,每当任务被提交到此“线程池(这里就交线程池了)”时,线程池产生一个新的线程去执行Callable中的代码,每次都产生新的线程而且没有上线(默认没有上线,可以设置concurrencyLimit属性来设置线程数的大小),郁闷了叫喊.这个肯定不是我需要的。

 

public void execute(Runnable task, long startTimeout) {
		Assert.notNull(task, "Runnable must not be null");
		if (isThrottleActive() && startTimeout > TIMEOUT_IMMEDIATE) {
			this.concurrencyThrottle.beforeAccess();
			doExecute(new ConcurrencyThrottlingRunnable(task));
		}
		else {
			doExecute(task);
		}
	}
 执行任务前会先判断有没有空余的线程空间(concurrencyLimit默认为-1,不执行)

 

 

protected void beforeAccess() {
		if (this.concurrencyLimit == NO_CONCURRENCY) {
			throw new IllegalStateException(
					"Currently no invocations allowed - concurrency limit set to NO_CONCURRENCY");
		}
		if (this.concurrencyLimit > 0) {
			boolean debug = logger.isDebugEnabled();
			synchronized (this.monitor) {
				boolean interrupted = false;
				while (this.concurrencyCount >= this.concurrencyLimit) {
					if (interrupted) {
						throw new IllegalStateException("Thread was interrupted while waiting for invocation access, " +
								"but concurrency limit still does not allow for entering");
					}
					if (debug) {
						logger.debug("Concurrency count " + this.concurrencyCount +
								" has reached limit " + this.concurrencyLimit + " - blocking");
					}
					try {
						this.monitor.wait();
					}
					catch (InterruptedException ex) {
						// Re-interrupt current thread, to allow other threads to react.
						Thread.currentThread().interrupt();
						interrupted = true;
					}
				}
				if (debug) {
					logger.debug("Entering throttle at concurrency count " + this.concurrencyCount);
				}
				this.concurrencyCount++;
			}
		}
	}
 如果没有超过concurrencyLimit,就不会this.monitor.wait();产生新的线程执行任务。

 

Spring中应该有其他线程池来支持此功能。最终选择ThreadPoolTaskExecutor,看起来与ThreadPoolExecutor类似。

 

        private int corePoolSize = 1;

	private int maxPoolSize = Integer.MAX_VALUE;

	private int keepAliveSeconds = 60;

	private boolean allowCoreThreadTimeOut = false;

	private int queueCapacity = Integer.MAX_VALUE;

	private ThreadPoolExecutor threadPoolExecutor;
 具备线程池的功能,可以设置线程的大小,有缓冲队列,空闲线程存活时间等。

 

 默认corePoolSize=1,maxPoolSize、queueCapacity为整型最大值,keepAliveSeconds=60(单位秒)

<bean id="myThreadPool"
		class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
		<property name="corePoolSize" value="5" /><!--最小线程数 -->
		<property name="maxPoolSize" value="10" /><!--最大线程数 -->
		<property name="queueCapacity" value="50" /><!--缓冲队列大小 -->
		<property name="threadNamePrefix" value="abc-" /><!--线程池中产生的线程名字前缀 -->
		<property name="keepAliveSeconds" value="30" /><!--线程池中空闲线程的存活时间单位秒 -->
	</bean>

	<mvc:annotation-driven>
		<mvc:async-support task-executor="myThreadPool"
			default-timeout="600">
			<mvc:callable-interceptors>
				<bean class="com.zhongyu.ABC" />
			</mvc:callable-interceptors>
		</mvc:async-support>
	</mvc:annotation-driven>

采用annotation-driven方式配置线程池,异步操作拦截器

	public <T> Object handleTimeout(NativeWebRequest request, Callable<T> task)
			throws Exception {
		HttpServletResponse servletResponse = request.getNativeResponse(HttpServletResponse.class);
		if (!servletResponse.isCommitted()) {
			servletResponse.setContentType("text/plain;charset=utf-8");
			servletResponse.getWriter().write("超时了");
			servletResponse.getWriter().close();
		}
		return null;
	}

 请求设定default-timeout超时后,会调用拦截器中handleTimeout进行逻辑处理

还需要优化的地方:

  • 由于ThreadPoolTaskExecutor内部缓冲队列采用的是阻塞队列LinkedBlockingDeque,如果队列满了,外部线程会继续等待,需要设置HTTP请求的超时时间
  • 线程池的大小配置
以上问题都需要根据实际业务来做调整。

 

分享到:
评论
2 楼 langzibo112304 2016-07-11  
楼主的qq是多少 有个问题请教
1 楼 lancijk 2015-04-02  
多谢楼主 分享.

相关推荐

    spring3.2参考文档

    3.2版增强了对Spring MVC测试的支持,包括模拟HTTP请求和响应。 7. **Javadoc API**:javadoc-api目录中的文档包含了Spring 3.2的所有公开API的详细说明,是开发者理解框架接口和类的重要资源。 8. **参考文档**:...

    Spring3.2包和配置文件

    在Spring 3.2中,它提供了增强的DispatcherServlet,能更好地处理异步请求。此外,Spring MVC引入了模型绑定、数据验证和类型转换等特性,简化了控制器层的代码。还有改进的视图解析和模板引擎支持,如JSP、...

    spring3.2.jar

    在性能方面,Spring 3.2引入了异步请求处理的支持。通过`@Async`注解,开发者可以声明一个方法为异步执行,从而提高系统的并发处理能力。同时,`@Scheduled`注解则允许定时任务的定义,方便进行计划任务的管理。 ...

    框架springmvc3.2+spring3.2+mybatis3.11+maven整合

    Spring MVC 3.2引入了改进的类型安全的`@RequestMapping`注解,支持异步处理,以及增强的异常处理机制。此外,它还支持JSR-303 Bean验证,使得验证逻辑更加规范。 **Spring 3.2** Spring框架的核心在于依赖注入(DI...

    spring3.2所有jar包和源码

    8. **Spring Integration**:提供异步处理和企业服务总线(ESB)的功能,帮助实现不同系统之间的集成。 9. **Spring Boot**:虽然不在3.2版本中,但提及Spring时不能不提,它是近年来流行的快速启动Spring应用的...

    spring3.2中文参考手册

    - Spring 3.2中集成了Servlet 3.0支持的异步请求处理和基于注解的控制器方法参数。 4. 日志管理 Spring支持多种日志框架,它自身使用的是Commons Logging,但推荐使用SLF4J和Log4j。开发者可以根据项目需求选择...

    Spring3.2中文版.docx

    24. **Servlet 3异步请求处理**:Spring 3.2支持Servlet 3.0的异步处理,提升了高并发场景下的性能。 25. **Spring MVC测试框架**:提供了强大的测试工具,简化了Spring MVC应用的测试。 26. **内容协商改进**:优化...

    spring api 3.2 RC1 真正的api

    对Spring MVC的性能进行了优化,减少了HTTP请求处理的开销,提升了Web应用的响应速度。 12. **RESTful支持**: 强化了对RESTful服务的支持,包括路径变量、HTTP方法映射、超媒体链接等,便于构建基于HTTP的...

    spring3.2+hibernate4

    Spring MVC作为Spring框架的一部分,为构建Web应用程序提供了模型-视图-控制器架构,允许开发者通过声明式的方式处理HTTP请求和响应。 Hibernate 4则在Hibernate 3的基础上进行了优化,提供了更好的性能和更多的...

    【免费】Springmvc3.2所需要的全部jar包

    8. **异步处理**:Spring 3.2引入了异步请求处理,通过@Async注解,开发者可以编写非阻塞的后台任务,提高系统性能。 9. **RESTful支持**:对于构建RESTful服务,Spring MVC提供了强大的支持,包括URI模板、HTTP...

    Spring3.2 jar

    Spring3.2版本的改进还包括了对Java 7和Java EE 6的支持,增强了对RESTful服务和异步处理的支持,提升了性能和内存使用效率。这些jar文件组合在一起,构成了一个强大的Spring框架,可以帮助开发者高效地构建复杂的...

    Spring Boot实现异步请求(Servlet 3.0)

    Spring Boot 实现异步请求是指在 Spring Boot 应用程序中使用异步处理机制来处理请求,以提高系统的性能和吞吐量。在 Spring 3.2 及以后版本中增加了对请求的异步处理,旨在提高请求的处理速度降低服务性能消耗。 ...

    sturts2.3.15.1+Spring3.2+hibernate3.6整合

    Spring3.2版本改进了对其他框架的集成,优化了性能,并引入了新的注解和特性,例如@Async支持异步方法执行。 Hibernate是Java中流行的ORM(Object-Relational Mapping,对象关系映射)框架,它允许开发者用面向对象...

    Spring 最新动态:浅析 Spring 3.1、3.2 和 3.3

    在Web方面,Spring 3.2改进了MVC框架,增加了异步处理支持,提升了Web应用的响应速度。 进入Spring 3.3,框架的稳定性得到了显著提升,许多小的bug被修复,性能得到优化。此版本重点在于提供更好的工具支持,例如,...

    springMVC3.2 简单实现文件的上传和下载

    在Spring MVC 3.2中,文件上传和下载是常见的功能需求,这涉及到HTTP协议、MultipartFile接口以及Spring MVC的处理机制。以下是对这个主题的详细讲解。 **一、文件上传** 1. **HTTP协议中的多部分表单数据**: ...

    springmvc3.2

    7. **Async support**:Spring MVC 3.2引入了异步处理支持,允许控制器方法返回`DeferredResult`或使用`@Async`注解来启动异步任务,提高应用的并发处理能力。 8. **国际化和本地化**:3.2版本提供了更便捷的本地化...

    详解spring mvc对异步请求的处理

    Spring MVC从3.2版本开始,引入了对异步请求的支持,这主要建立在Servlet 3.0及其以上版本的异步处理功能之上。下面将详细介绍如何在Spring MVC中配置和实现异步请求。 ### 1. 配置Web应用以支持异步处理 首先,你...

    Spring3.2.0 框架jar包及Spring依赖jar包

    它支持模型-视图-控制器架构,提供了与Spring IoC容器的深度集成,以及处理HTTP请求的强大工具。 5. **Spring Web Services**:此模块专注于创建基于SOAP和RESTful的Web服务。它提供了一个完整的栈,包括工具支持、...

    Spring3,Spring4,Spring5 jar包

    在HTTP客户端方面,`RestTemplate`被新的`WebClient`取代,提供了一种更强大、更灵活的方式来处理HTTP请求。Spring 5.0还增强了对WebSocket的支持,添加了SSE(Server-Sent Events)支持,以及对HTTP/2协议的内置...

Global site tag (gtag.js) - Google Analytics