java - 添加更多 Controller 时,Spring mvc 性能显着下降

标签 java spring performance spring-mvc

在我提出问题之前,请注意实际数字并不代表性能。重要的是它们相对于彼此的值(value)以及我在两次运行之间获得一致的数字(当然是在一个小范围内)这一事实。

因此,我在 Jetty 上运行了以下 Spring Boot 应用程序:

// Application.java
package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
// HelloController1.java
package hello;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/v1/foo/{foo}/bar/{bar}/dog")
@RestController
public class HelloController1 {
    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<String> m() {
        return ResponseEntity.ok("dog");
    }
}

使用这些 Maven 依赖项:
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>LATEST</version>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jetty</artifactId>
        <version>LATEST</version>
    </dependency>
</dependencies>

唯一的配置属性集是:logging.level.org.springframework.web=ERROR
我用 wrk 对应用程序进行基准测试:
wrk -t 10 -c 10 -d 40s http://localhost:8080/v1/foo/foo/bar/bar/dog

而且我每秒收到一致的 45K 请求。

现在,我添加了另外 4 个 Controller ,除了类名和请求路径之外,与上面的相同:
  • HelloController2 -> /v1/foo/{foo}/bar/{bar}/giraffe
  • HelloController3 -> /v1/foo/{foo}/bar/{bar}/cat
  • HelloController4 -> /v1/foo/{foo}/bar/{bar}/tacocat
  • HelloController5 -> /v1/foo/{foo}/bar/{bar}/parrot

  • 现在,如果我再次运行测试,我平均只能得到 35K RPS。

    我希望第二个测试得到更低的值,特别是因为这 5 条路由共享相同的前缀——我可以想象一些实现可能比其他实现更差——但 20 % 似乎很多。

    在我开始深入研究 spring (boot) 源代码之前,我希望这里可能有人熟悉路由器/匹配器的实现并能弄清楚发生了什么。为什么RPS差异如此之大?

    稍微查看一下 Spring 源代码后进行编辑 .如果我错了,请纠正我:

    似乎路由路径匹配器对每个请求的所有可用路由路径进行线性搜索。对于每个路由路径,如果它没有模式,它只是进行字典查找,一切都很好。但是,如果路径有参数(如我的示例中的 {foo}{bar}),它必须转到 AntMatcher以匹配那些与实际路径。匹配器进行从左到右的搜索,因此一旦找到不匹配的内容就会失败。由于我所有的路线都以相同的模式开始,因此必须在每条路线上做很多工作,因此添加更多路线时性能会变得更差。

    顺便说一句,我愿意接受有关如何使其表现更好的建议。我们的应用程序因此而受到影响。

    最佳答案

    在不更改 Spring 代码的情况下,您可以做的是重构代码以仅使用一个匹配所有有问题的模式的 RequestMapping,并自己编写一些性能算法来将调用委托(delegate)给正确的类并传递参数。

    您可以使用 开始算法。如果 树和一些正则表达式,不要忘记编译正则表达式并将其保存为常量,这样你就不会有 performance issues .

    关于java - 添加更多 Controller 时,Spring mvc 性能显着下降,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41788087/

    相关文章:

    java - RabbitMQ:如何限制路由键格式

    java - 使用传递参数的第三方 RESTful API

    spring - 非默认端口上的Docker-compose,spring app + mongoDB

    java - 任何使用 hibernate 和 spring MVC 的在线教程/示例

    performance - iOS/核心动画 : Performance tuning

    java - 在JavaFX应用程序的Main方法中获取.fxml文件中定义的TextArea

    java - 对象类型列表和扩展类型的对象列表之间的区别

    java - Spring RedirectAttributes 导致 "Cannot create a session after the response has been committed"错误

    java - 检测java web应用程序中cpu使用率15%的原因

    mysql - 从mysql订单表获取上升率但是太慢