spring rest 容易被忽视的后端服务 chunked 性能问题

spring boot 容易被忽视的后端服务 chunked 性能问题

标签(空格分隔): springboot springmvc chunked


  • 背景
  • 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:chunkedTransfer-Encoding:chunkedHTTP 协议里的意思是无法计算 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 mvcjersey rest 共同存在的问题,我们也不需要将所有的返回 chunked 的接口都改成 JAX-RSrest 服务,只需要将有性能瓶颈的接口改造下即可。

时间: 2024-09-08 05:51:54

spring rest 容易被忽视的后端服务 chunked 性能问题的相关文章

从Docker Hub和docker-registry看优秀的后端服务设计实现

从Docker Hub和docker-registry看优秀的后端服务设计实现 [编者的话] 本文通过研究Docker Hub和docker-registry的架构,介绍了在服务端Docker镜像的存储.管理.安全的架构设计,并给出了一次简单的Docker客户端服务端交互的过程.对于部署实现一个大规模.企业级的镜像库需要做的工作做了初步的探讨,汇总了需要准备的前期知识等.推荐想要搭建一个私有Docker镜像库的同学阅读. 需求 最近因为工作需要,我开始研究docker-registry的实现和服

移动后端服务:功能和部署选项

移动应用程序不断连接,这使得移动后端作为一个服务的理想运行的业务逻辑和数据分析.以下是人们需要知道的云后端服务. 移动应用正在不断连接,从而使移动后端即服务的业务逻辑和数据分析得以理想运行.以下是需要了解云后端服务的内容: 每个公司都需要一个移动战略以保持竞争力,其原因很多.智能手机成为了主要的计算和通信平台,可以安装满足客户和员工需求的应用程序,很少使用网页运行,而竞争对手可能已经使用应用程序提供的新服务,简化业务流程,并进行更深入的客户互动. IT在企业的数字战略的制定和实施中起着关键的作用

springmvc 高并发-SpringMVC基于app后端服务考虑高并发请求如何处理

问题描述 SpringMVC基于app后端服务考虑高并发请求如何处理 要求一个请求并发能处理20000次/S,数据以JSON格式响应给客户端 解决方案 http://www.iteye.com/problems/101314

开源的:helios移动应用后端服务框架

开源的:helios移动应用后端服务框架 发表于2013-04-07 11:20| 次阅读| 来源CSDN| 0 条评论| 作者张宁 helios开源后端服务http://www.aliyun.com/zixun/aggregation/13435.html">开发框架Github移动开发 摘要:helios允许开发人员在短短几分钟的时间内,就配置好应用和服务 端的连接,让移动应用和所提供的这些后端服务 无缝整合.最重要的是,它还是开源的!赞一个! helios,是一个可扩展的开源移动后端

消息称阿里将为Apple,Pay提供后端服务,合作仅限中国

消息称阿里将为Apple,Pay提供后端服务,合作仅限中国 网易科技讯,11月12日消息,据国外媒体报道,阿里巴巴董事局执行副主席蔡崇信周二表示,苹果公司和阿里巴巴的金融服务子公司支付宝之间的支付联盟将专注于 中国市场,而双方目前正在讨论相关合作的细节.阿里巴巴董事局执行副主席蔡崇信在接受采访时表示,"现在我 认为我们可以披露的是,这次合作将专注于苹果的中国市场部分.我们的潜在合作可能性非常大,但依赖于正在被讨论的细节."一种可能的情况是阿里巴巴的金融子公司,也就是中国支付宝电子支付业

后端服务性能压测实践

后端服务性能压测实践 标签(空格分隔): 性能 压测 后端服务 压测实践 作者:王清培(Plen wang) 背景 环境检测 压力机及压力工具检测 Linux openfiles limit 设置 排查周边依赖 空接口压测检测 聚合报告中 throughput 计算 压测及性能排查方法 关注各纬度 log Linux 常规命令 性能排查两种方式(从上往下.从下往上) 总结 背景 最近大半年内有过两次负责性能压测的一些工作.一件事情做了一次可能还无法总结出一些东西,两次过后还是能发现一些共性问题,

事件日志中的"TermService" 服务的性能库

  发现事件记录: "TermService" 服务的性能库 "C:WINDOWSsystem32perfts.dll" 的配置信息  同在注册表中保存的受信任性能库信息不匹配.此库中的函数不会作为受信任函数处理. TermService是系统的一个服务. Terminal Services 提供一个多会话环境,客户端设备可以在此环境中访问虚拟 Windows 桌面会话和服务器上运行的基于 Windows 的程序.Terminal Services 使用户可以远程管

azure-有关云服务的性能问题

问题描述 有关云服务的性能问题 各位大神,你们好! 使用环境是这样的:一台azure虚拟机,里面有IIS,部署了MVC框架的网站,访问sql azure数据库(s0),数据访问是用EntityFramework6.(虚拟机和数据库的数据中心是一样的) 问题是:打开网页的速度比迁移前(之前是托管服务器)慢了不是一星半点.在服务器端记录的log里显示,打开一个网页请求的时间(Milliseconds)在本地是两位数,在云端是四位数.看仪表盘数据,cpu什么dtu什么都挺低,都挺正常的样子. 请问有什

spring mvc前端传json,后端怎么直接对象获取

问题描述 在项目中碰到问题了就是我前端ajax传一个json过了, 我后端用在spring mvc怎么直接用对象去接收? 解决方案 可以在ajax里面填写$.ajax({ url: "/spring-mvc-json/rest/cont/person", type: 'POST', dataType: 'json', data: "{"name":"hmkcode","id":2}", contentTyp