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 容易被忽视的后端服务 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 服务,只需要将有性能瓶颈的接口改造下即可。

目录
相关文章
|
2月前
|
Web App开发 JavaScript 前端开发
构建高效后端服务:Node.js与Express框架的实战指南
【9月更文挑战第6天】在数字化时代的潮流中,后端开发作为支撑现代Web和移动应用的核心,其重要性不言而喻。本文将深入浅出地介绍如何使用Node.js及其流行的框架Express来搭建一个高效、可扩展的后端服务。通过具体的代码示例和实践技巧,我们将探索如何利用这两个强大的工具提升开发效率和应用性能。无论你是后端开发的新手还是希望提高现有项目质量的老手,这篇文章都将为你提供有价值的见解和指导。
|
3月前
|
JavaScript 前端开发 中间件
构建高效后端服务:Node.js与Express框架的完美搭档
【8月更文挑战第28天】在追求高性能、可扩展和易维护的后端开发领域,Node.js和Express框架的组合提供了一种轻量级且灵活的解决方案。本文将深入探讨如何利用这一组合打造高效的后端服务,并通过实际代码示例展示其实现过程。
|
10天前
|
存储 缓存 持续交付
后端世界的微妙平衡:性能与可维护性的博弈###
【10月更文挑战第15天】 在软件开发的浩瀚宇宙里,后端开发犹如一颗星辰,既需璀璨夺目以支撑业务辉煌,又得稳若磐石确保系统长青。本文探讨了后端开发中性能优化与代码可维护性之间的微妙平衡,通过实例分析与策略建议,揭示了如何在追求极致速度的同时,保持代码的清晰、可读与易于迭代,实现技术与艺术的和谐共生。我们相信,正如印度圣雄甘地所言:“你必须成为你希望在世界上看到的改变。”开发者在面对复杂系统挑战时,也应主动寻求变革,探索更高效的解决方案。 ###
27 3
|
2月前
|
Java API 对象存储
微服务魔法启动!Spring Cloud与Netflix OSS联手,零基础也能创造服务奇迹!
这段内容介绍了如何使用Spring Cloud和Netflix OSS构建微服务架构。首先,基于Spring Boot创建项目并添加Spring Cloud依赖项。接着配置Eureka服务器实现服务发现,然后创建REST控制器作为API入口。为提高服务稳定性,利用Hystrix实现断路器模式。最后,在启动类中启用Eureka客户端功能。此外,还可集成其他Netflix OSS组件以增强系统功能。通过这些步骤,开发者可以更高效地构建稳定且可扩展的微服务系统。
47 1
|
2月前
|
JavaScript 前端开发 数据库
优化后端性能:如何使用异步编程提升系统响应速度
异步编程已成为现代后端系统性能优化的重要策略。通过避免阻塞操作,异步编程可以显著提高系统的响应速度和并发处理能力。本文章深入探讨了异步编程的基本概念,比较了常见的异步编程模型,并通过实际案例演示如何在Node.js和Python中实现异步操作,以提升系统性能。
|
26天前
|
Java API Maven
使用 Smart-doc 记录 Spring REST API
使用 Smart-doc 记录 Spring REST API
29 0
|
3月前
|
JavaScript 安全 API
构建高效后端服务:RESTful API 设计与实现
【8月更文挑战第31天】在数字化时代,一个清晰、高效且安全的后端服务是应用程序成功的关键。本文将深入探讨如何设计并实现一个遵循REST原则的API,确保服务的可扩展性和维护性。我们将从基础概念出发,逐步引入真实代码示例,展示如何利用现代技术栈创建高性能的后端服务。无论你是初学者还是有经验的开发者,这篇文章都将为你提供新的视角和实用的技巧。
|
3月前
|
存储 SQL 缓存
深入浅出:构建高效后端服务的五大原则
在数字化浪潮中,后端服务作为技术架构的核心,承载着数据处理和业务逻辑的重要任务。本文将深入探讨如何构建一个高效、稳定且可扩展的后端服务,从五个关键原则出发,带领读者一步步理解并实践这些原则,以确保后端系统能够灵活应对各种挑战。
|
3月前
|
Prometheus 监控 Cloud Native
Spring Boot 性能护航!Prometheus、Grafana、ELK 组合拳,点燃数字化时代应用稳定之火
【8月更文挑战第29天】在现代软件开发中,保证应用性能与稳定至关重要。Spring Boot 作为流行的 Java 框架,结合 Prometheus、Grafana 和 ELK 可显著提升监控与分析能力。Prometheus 负责收集时间序列数据,Grafana 将数据可视化,而 ELK (Elasticsearch、Logstash、Kibana)则管理并分析应用日志。通过具体实例演示了如何在 Spring Boot 应用中集成这些工具:配置 Prometheus 获取度量信息、Grafana 显示结果及 ELK 分析日志,从而帮助开发者快速定位问题,确保应用稳定高效运行。
96 1
|
3月前
|
监控 JavaScript 前端开发
深入浅出Node.js: 打造高效的后端服务
【8月更文挑战第27天】在这个数字化飞速发展的时代,后端技术成为支撑互联网服务的基石。Node.js作为其中的佼佼者,以其非阻塞I/O模型、事件驱动架构和丰富的生态系统,赢得了开发者的青睐。本文将带领读者深入理解Node.js的核心概念,通过实际案例分析其应用模式,并探讨如何利用Node.js构建高效、可扩展的后端服务。无论你是初学者还是有经验的开发者,都能在这篇文章中找到提升你的Node.js技能的灵感和知识。