spring rest 容易被忽视的后端服务 chunked 性能问题
spring boot 容易被忽视的后端服务 chunked 性能问题
标签(空格分隔): springboot springmvc chunked
作者:王清培(Plen wang) 沪江Java资深架构师
- 背景
- spring boot 创建的默认 spring mvc 项目
- 集成 JAX-RS 规范框架 Jersey
背景
在之前的一次性能压测的时候我们发现一个细节问题,我们使用 spring boot 创建的 web rest 项目,使用默认 spring mvc 作为 web rest 框架。
这在使用上没有太大问题,但是有一个影响性能的细节问题被发现了,说实话这个问题很难被发现。
spring boot 创建的默认 spring mvc 项目
我们来看一个简单的 demo,我使用 IDEA 创建一个 spring boot 项目,创建过程中没有什么特别的选项需要调整,一路 next 。然后我们创建一个简单的 controller 。
package springboot.demo.controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springboot.demo.model.User;
/**
* Created by plen on 2017/11/25.
*/
@RestController
public class SpringMvcController {
@RequestMapping("/user/{id}")
public User hello(@PathVariable Long id) {
User user = new User();
user.setID(id);
user.setUserName("mvc.");
return user;
}
}
再创建一个简单的 model 。
package springboot.demo.model;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* Created by plen on 2017/11/25.
*/
@Data
@EqualsAndHashCode
public class User {
private Long ID;
private String userName;
}
然后启动访问这个 controller ,注意看下返回的 http 信息里多了一个 Transfer-Encoding:chunked 。Transfer-Encoding:chunked 在 HTTP 协议里的意思是无法计算 Content-Length 长度,需要分块传输。
这是 spring mvc 的默认 complex object 传输方式,如果我们返回的是一个简单的对象就不会有这个问题。
Transfer-Encoding:chunked 带来的性能问题就是访问一次数据在 __http__层面看确实是一次 http 请求,而通过 tcp 抓包工具查看会发现多了一次 tcp 传输。
集成 JAX-RS 规范框架 Jersey
解决这个问题两个层面都可以,一种是采用比较粗暴的方式在 servlet 容器层面解决,但是这个会带来一个后果就是当我们计算 complex object 大小的时候会比较复杂而且容易出错,也会影响项目未来的分块传输功能,效果不太好。
还有一种就是在应用层面解决,比较柔性也易于扩展,我们可以集成一个 rest 框架,最好是符合 JAX-RS 规范,本文我们集成 Jersey 框架。
jersey 集成如果通过 @Component 方式那么 jersey 会默认接管所有的 web servlet 请求处理,所以就需要我们手动的配置专门用来处理 jersey servlet 的容器。
spring boot 解决了以前 spring 繁重的配置,提供了 auto config 功能,原来通过 web.xml 配置 servlet 的,现在需要用代码来配置。spring boot 提供了让我们手动注册 servlet bean 的方式。
org.springframework.boot.web.servlet.ServletRegistrationBean
ServletRegistrationBean 可以让我们注册servlet,我们来看下完整代码。
package springboot.demo.config;
import org.glassfish.jersey.servlet.ServletContainer;
import org.glassfish.jersey.servlet.ServletProperties;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
/**
* Created by plen on 2017/11/25.
*/
@Component
public class JerseyServletBeanConfig {
@Bean
public ServletRegistrationBean jerseyServlet() {
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new ServletContainer(), "/rest/v1/*");
registrationBean.addInitParameter(ServletProperties.JAXRS_APPLICATION_CLASS, JerseyResourceConfig.class.getName());
return registrationBean;
}
}
这和原来在 web.xml 配置的是一样的,设置 routing 地址,设置 Init 初始化参数,对应的 servlet class name 。
所有的 "rest/v1/*" 请求都将被 ServletContainer jersey servlet 容器接管。
package springboot.demo.config;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.spring.scope.RequestContextFilter;
import springboot.demo.controller.JerseyController;
/**
* Created by plen on 2017/11/25.
*/
public class JerseyResourceConfig extends ResourceConfig {
public JerseyResourceConfig() {
register(JerseyController.class);
register(RequestContextFilter.class);
}
}
ResourceConfig 其实是一个 jersey Application 类型。这是 __jersey 注册 servlet 时规定的。
package springboot.demo.controller;
import springboot.demo.model.User;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
/**
* Created by plen on 2017/11/25.
*/
@Path("/user/")
public class JerseyController {
@Path("{id}")
@GET
@Produces(MediaType.APPLICATION_JSON)
public User hello(@PathParam("id") Long id) {
User user = new User();
user.setID(id);
user.setUserName("jersey.");
return user;
}
}
这是我们应用代码 Controller ,使用 JAX-RS 规范的注解进行设置即可。
这样就解决了 sprng mvc 和 jersey rest 共同存在的问题,我们也不需要将所有的返回 chunked 的接口都改成 JAX-RS 的 rest 服务,只需要将有性能瓶颈的接口改造下即可。
spring rest 容易被忽视的后端服务 chunked 性能问题的更多相关文章
- 容易被忽视的后端服务 chunked 性能问题
容易被忽视的后端服务 chunked 性能问题 标签(空格分隔): springboot springmvc chunked 背景 spring boot 创建的默认 spring mvc 项目 集成 ...
- Spring Cloud(二):Web服务客户端之Ribbon
上文介绍了服务如何通过Eureka实现注册,以及如何从Eureka获取已经注册的服务列表.那么拿到注册服务列表后, 如何进行服务调用?一个简单的实现是可以从被调用服务的实例列表中选择一个服务实例,通过 ...
- mormort 土拨鼠,做后端服务那是杠杠的,基于http.sys
http.sys你可以用 mormort 土拨鼠,做后端服务那是杠杠的,基于http.sys并且还是开源的,作者天天更新代码,非常勤奋,官方论坛提问,回答也快其实,稍微看看,就能玩的挺好的
- 使用Ratpack和Spring Boot打造高性能的JVM微服务应用
使用Ratpack和Spring Boot打造高性能的JVM微服务应用 这是我为InfoQ翻译的文章,原文地址:Build High Performance JVM Microservices wit ...
- 基于Spring Cloud和Netflix OSS构建微服务,Part 2
在上一篇文章中,我们已使用Spring Cloud和Netflix OSS中的核心组件,如Eureka.Ribbon和Zuul,部分实现了操作模型(operations model),允许单独部署的微 ...
- Apple使用Apache Mesos重建Siri后端服务
苹果公司宣布,将使用开源的集群管理软件Apache Mesos,作为该公司广受欢迎的.基于iOS的智能个人助理软件Siri的后端服务.Mesosphere的博客指出,苹果已经创建了一个命名为J.A.R ...
- Spring Cloud 入门教程 - 搭建配置中心服务
简介 Spring Cloud 提供了一个部署微服务的平台,包括了微服务中常见的组件:配置中心服务, API网关,断路器,服务注册与发现,分布式追溯,OAuth2,消费者驱动合约等.我们不必先知道每个 ...
- 快速新建简单的koa2后端服务
既然前端工程化是基于NodeJS,那么选择NodeJs做前后端分离部署也是理所应当的.其实只需要实现静态资源和代理的话,用nginx才是最好的选择,用NodeJS是为了日后能进一步在服务端上实现自动构 ...
- vue,vuex的后台管理项目架子structure-admin,后端服务nodejs
之前写过一篇vue初始化项目,构建vuex的后台管理项目架子,这个structure-admin-web所拥有的功能 接下来,针对structure-admin-web的不足,进行了补充,开发了具有登 ...
随机推荐
- 移动端1px问题
.component-confirm__buttons { border-top: 1px solid #eceef0; box-shadow: 0 1px 1px #fff; } 造成边框变粗的原因 ...
- 51Nod1773 A国的贸易 多项式 FWT
原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1773.html 题目传送门 - 51Nod1773 题意 给定一个长度为 $2^n$ 的序列,第 $ ...
- P1101 单词方阵 简单dfs
题目描述 给一n \times nn×n的字母方阵,内可能蕴含多个“yizhong”单词.单词在方阵中是沿着同一方向连续摆放的.摆放可沿着 88 个方向的任一方向,同一单词摆放时不再改变方向,单词与单 ...
- PAT (Basic Level) Practise - 继续(3n+1)猜想
题目链接:https://www.patest.cn/submissions/4414905 1005. 继续(3n+1)猜想 (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限 ...
- jquery开发插件提供的几种方法
http://caibaojian.com/jquery-extend-and-jquery-fn-extend.html
- 基本标签-html-1
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- vue-cli之打包多入口配置
在使用vue-cli初始化vue项目时,默认打包为单入口,有时候一个项目可能会有不同入口,在这种情况下,就需要我们稍微修改下webpack配置文件了,具体步骤如下: 1.修改webpack.base. ...
- ReentrantLock和condition源码浅析(二)
转载请注明出处... 接着上一篇的ReentrantLock和condition源码浅析(一),这篇围绕着condition 一.condition的介绍 在这里为了作对比,引入Object类的两个方 ...
- windows下z3安装
从 github 上 clone Z3 git clone https://github.com/Z3Prover/z3.git 命令行中进入 Z3 文件夹,执行命令: python scripts/ ...
- shell编程第二天