为什么 Spring Rest 服务在第一次请求时变慢?
Why are Spring Rest services slow on the first request?
所以这个问题已经被问过几次了,但似乎没有人以可以帮助我的方式回答它。我目前正在为处理产品数据的简单应用程序制作后端。它甚至没有 JSP,只是一个普通的 Rest 后端。 Spring.
使用 RestControllers
“问题”是:启动后的第一个请求比所有其他请求花费更长的时间从服务器获得答案。 (我只是用一个简单的 JPA 用户实体对 Postman 进行测试)
需要考虑的一些事项:
- 它本身可能不是数据库问题,因为它显然只是在第一个传入请求而不是启动时初始化一些东西
- 在日志中,当第一个实际请求(通过 Postman)进入时,它显示“正在初始化 Spring DispatcherServlet 'dispatcherServlet'”。
- 如果我从数据库中提取所有用户(目前只有一个用户),启动后的第一个请求需要 140 毫秒(根据 Postman)。之后,同样的请求最多需要10ms。
- 有一个类似问题的一些答案的标记:spring.mvc.servlet.load-on-startup=1。虽然这只会删除上面提到的(DispatcherServlet 初始化的)日志记录。
- 这似乎是标准行为,与我实际编码我的实体的方式无关and/or RestControllers。
如何使第一个请求更快/如何强制 Spring 在第一个请求进入之前实际初始化所有内容?
一些代码:
User.java:
@Entity
@Table(name = "users")
@Data
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@NonNull
private String firstName;
@NonNull
private String lastName;
@NonNull
@OneToOne(cascade = CascadeType.ALL)
private Address billingAddress;
//a bit more. a list and another address
}
UserController.java:
@RestController
@RequestMapping("users")
public class UserController {
private final UserRepository userRepository;
@Autowired
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}
@GetMapping()
public List<User> getAllUsers() {
return (List<User>) userRepository.findAll();
}
//more stuff
}
您自己回答了问题。 Spring 中的很多东西都是用于性能和资源消耗优化的惰性初始化。用户真的会注意到一个请求花费了 140 毫秒而不是 10 毫秒吗?可能不会。请注意,这不是每个用户一个请求,而是每次启动每个初始化路径一个请求。
综上所述……您还回答了如何“修复”它。部署后(我假设通过 CI/CD 自动执行),您提交一个或多个请求(CI/CD 的一部分),这将触发您需要的所有路径的初始化。 IE。如果您有 5 个数据库连接,则可能需要提交 5 个请求来初始化所有内容。
这是完全可以接受的,是一个称为“预热系统”的过程。
所以这个问题已经被问过几次了,但似乎没有人以可以帮助我的方式回答它。我目前正在为处理产品数据的简单应用程序制作后端。它甚至没有 JSP,只是一个普通的 Rest 后端。 Spring.
使用 RestControllers“问题”是:启动后的第一个请求比所有其他请求花费更长的时间从服务器获得答案。 (我只是用一个简单的 JPA 用户实体对 Postman 进行测试)
需要考虑的一些事项:
- 它本身可能不是数据库问题,因为它显然只是在第一个传入请求而不是启动时初始化一些东西
- 在日志中,当第一个实际请求(通过 Postman)进入时,它显示“正在初始化 Spring DispatcherServlet 'dispatcherServlet'”。
- 如果我从数据库中提取所有用户(目前只有一个用户),启动后的第一个请求需要 140 毫秒(根据 Postman)。之后,同样的请求最多需要10ms。
- 有一个类似问题的一些答案的标记:spring.mvc.servlet.load-on-startup=1。虽然这只会删除上面提到的(DispatcherServlet 初始化的)日志记录。
- 这似乎是标准行为,与我实际编码我的实体的方式无关and/or RestControllers。
如何使第一个请求更快/如何强制 Spring 在第一个请求进入之前实际初始化所有内容?
一些代码:
User.java:
@Entity
@Table(name = "users")
@Data
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@NonNull
private String firstName;
@NonNull
private String lastName;
@NonNull
@OneToOne(cascade = CascadeType.ALL)
private Address billingAddress;
//a bit more. a list and another address
}
UserController.java:
@RestController
@RequestMapping("users")
public class UserController {
private final UserRepository userRepository;
@Autowired
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}
@GetMapping()
public List<User> getAllUsers() {
return (List<User>) userRepository.findAll();
}
//more stuff
}
您自己回答了问题。 Spring 中的很多东西都是用于性能和资源消耗优化的惰性初始化。用户真的会注意到一个请求花费了 140 毫秒而不是 10 毫秒吗?可能不会。请注意,这不是每个用户一个请求,而是每次启动每个初始化路径一个请求。
综上所述……您还回答了如何“修复”它。部署后(我假设通过 CI/CD 自动执行),您提交一个或多个请求(CI/CD 的一部分),这将触发您需要的所有路径的初始化。 IE。如果您有 5 个数据库连接,则可能需要提交 5 个请求来初始化所有内容。
这是完全可以接受的,是一个称为“预热系统”的过程。