容易被忽视的后端服务 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 服务,只需要将有性能瓶颈的接口改造下即可。
容易被忽视的后端服务 chunked 性能问题的更多相关文章
- spring rest 容易被忽视的后端服务 chunked 性能问题
spring boot 容易被忽视的后端服务 chunked 性能问题 标签(空格分隔): springboot springmvc chunked 作者:王清培(Plen wang) 沪江Java资 ...
- mormort 土拨鼠,做后端服务那是杠杠的,基于http.sys
http.sys你可以用 mormort 土拨鼠,做后端服务那是杠杠的,基于http.sys并且还是开源的,作者天天更新代码,非常勤奋,官方论坛提问,回答也快其实,稍微看看,就能玩的挺好的
- Apple使用Apache Mesos重建Siri后端服务
苹果公司宣布,将使用开源的集群管理软件Apache Mesos,作为该公司广受欢迎的.基于iOS的智能个人助理软件Siri的后端服务.Mesosphere的博客指出,苹果已经创建了一个命名为J.A.R ...
- 快速新建简单的koa2后端服务
既然前端工程化是基于NodeJS,那么选择NodeJs做前后端分离部署也是理所应当的.其实只需要实现静态资源和代理的话,用nginx才是最好的选择,用NodeJS是为了日后能进一步在服务端上实现自动构 ...
- vue,vuex的后台管理项目架子structure-admin,后端服务nodejs
之前写过一篇vue初始化项目,构建vuex的后台管理项目架子,这个structure-admin-web所拥有的功能 接下来,针对structure-admin-web的不足,进行了补充,开发了具有登 ...
- [转]快速新建简单的koa2后端服务
本文转自:https://blog.csdn.net/saucxs/article/details/83788259 既然前端工程化是基于NodeJS,那么选择NodeJs做前后端分离部署也是理所应当 ...
- chrome debug 服务端性能
设置 http header 在 chrome 查看服务端性能 \Yii::$app->getResponse()->headers->set('Server-Timing', 'c ...
- Web服务端性能提升实践
随着互联网的不断发展,日常生活中越来越多的需求通过网络来实现,从衣食住行到金融教育,从口袋到身份,人们无时无刻不依赖着网络,而且越来越多的人通过网络来完成自己的需求. 作为直接面对来自客户请求的Web ...
- 微信后端服务架构及其过载控制系统DAGOR
微信架构介绍 眼下的微信后端包含3000多个移动服务,包括即时消息.社交网络.移动支付和第三方授权.该平台每天收到的外部请求在10 ^10个至10^11个.每个这样的请求都会触发多得多的内部微服务 ...
随机推荐
- 一款低延迟的分布式数据库同步系统--databus
每次看到马路对面摩托罗拉的大牌子,都想起谷歌125亿美元收购摩托罗拉移动,后来又以29亿美元卖给联想的事情.谷歌所做的决策都比较考虑长远利益,在这串交易中,谷歌获得了摩托罗拉最有价值的几千项专利,稳健 ...
- Windows环境部署并调试pyspark(一)
准备: windows环境说明:Python2.7 + pipspark版本:spark-1.6.1-bin-hadoop2.6 step1: 下载并解压tar包到自定义的路径.(下载链接 https ...
- win10 UWP 隐式转换
implicit operator string <script type="text/javascript"> $(function () { $('pre.pret ...
- MySQL自定义函数用法详解-复合结构自定义变量/流程控制
自定义函数 (user-defined function UDF)就是用一个象ABS() 或 CONCAT()这样的固有(内建)函数一样作用的新函数去扩展MySQL. 所以UDF是对MySQL功能的一 ...
- mysql的并发处理机制_下篇
MySQL的并发处理机制,有MVCC及锁机制来处理,上篇简要说明了 MVCC及隔离级别,这篇来说说mysql下的锁. 温馨提示:下文有几个表格长度较长,右下角的博文导航目录会挡道,浏览 ...
- SpringMVC Spring MyBatis整合配置文件
1.spring管理SqlSessionFactory.mapper 1)在classpath下创建mybatis/sqlMapConfig.xml <?xml version="1. ...
- 423. Reconstruct Original Digits from English (leetcode)
Given a non-empty string containing an out-of-order English representation of digits 0-9, output the ...
- ps之雪碧图制作
图片拖入后 一般取同行同列最高最宽 自动在所选目录生成 打开: 修改 四次请求有点多啊. 打开 css sprite 自动生成坐标地址. 不过我们要把它排远一点 OK了. 我们生成以后: 坐标地址就可 ...
- mybatis generator eclipse插件的安装
mybatis generator 可以提高开发速度,这个插件可以自动生成代码,创建DAO层相关代码,就像利用HIbernate反相生成一样,安装前可以先到百度网盘下载: 文件:MyBatisGene ...
- thinkphp3.2开发网页实现第三方登录
1.在要添加登录的html里添加登录按钮: <a href="{:U('Public/login/',array('type'=>'weixin'))}">< ...