java - 在 SpringBoot 中管理并发 POST 请求最佳实践
问题描述
我正在使用 SpringBoot 构建一个 REST-API 并使用这个控制器。
@RestController
class EmployeeController {
private final EmployeeRepository repository;
EmployeeController(EmployeeRepository repository) {
this.repository = repository;
}
@GetMapping("/employees")
List<Employee> all() {
return repository.findAll();
}
@PostMapping("/employees")
Employee newEmployee(@RequestBody Employee newEmployee) {
return repository.save(newEmployee);
}
我想确保 API-Consumers 不能使用相同的Employee
. 我知道我可以在保存之前检查实体是否已经存在于数据库中,但我担心性能会很差。我也已经注意到你可以像@version
在你的实体中一样使用 Annotation 来更新现有实体的更多保存。
但是在 Spring 中是否还有一种方法或最佳实践如何处理这个带有潜在新实体的 POST 请求?
解决方案
您期望POST /employees
端点的请求吞吐量是多少?虽然性能很重要,但过早的优化几乎总是会导致你的代码比它需要的更难看,而且几乎没有什么收获。
正如您的代码当前所代表的那样,多个并发POST /employees
请求最终将以先到先服务的方式结束,在该基础上创建具有UNIQUE
应用程序中给定约束的第一个用户(希望由您的底层 DBMS 强制执行),以及之后的所有其他请求(对于同一用户)将由于 eg ConstraintViolationException
(映射到 eg DataIntegrityViolationException
)而失败。从这个角度来看(只要你没有复杂的分布式DBMS设置),数据的一致性还是有保证的。
当然,缺点是返回的错误消息是:
- 供应商特定并泄漏底层实现(例如,我们向客户端显示我们正在使用 Hibernate)
- 客户端可能难以解析。
如果您改为将实现更改为如下所示:
@PostMapping("/employees")
Employee newEmployee(@RequestBody Employee newEmployee) {
verifyEmployeeDoesNotExist(newEmployee);
return repository.save(newEmployee);
}
private void verifyUserDoesNotExist(Employee employee) {
if (repository.exists(newEmployee) {
throw new EmployeeAlreadyExistsException("Employee " + newEmployee.getName() + " already exists";
}
}
那么您可以更轻松地控制端点和底层流程的控制流,这可能会允许更容易消化的异常处理。这可以通过添加例如自定义异常来进一步改进,这些异常还包含一些预定义的代码,error code
例如error 409 code 1010 Employee already exists
。
当然,Spring 内置的 Hibernate 异常转换(例如HibernateExceptionTranslator
)对于您的用例可能已经足够好,甚至可以扩展,甚至可以推广此扩展。
最后,最佳实践是使您的代码干净、可读和可维护。然后开始添加功能来监控您的代码。在那之后,只有当你遇到性能问题时,你仍然可以优化它。
推荐阅读
- maven - 在中央找不到工件 jchem:jchem:jar:1.0
- ios - 这是在 UIImageview 上绘制的正确方法吗
- ios - 我们可以知道 iPhone“人像方向锁定”是开/关吗
- docker - 故障转移后,sentinel 无法将初始 master 提升回 MASTER 模式
- git - Perforce中时间点的表示是什么
- parse-platform - 即使使用主密钥,解析云代码查询也会隐藏对象
- python - 烧瓶和减少mysql查询的最佳方法,也许是芹菜?
- angular - 角度单元测试用例中的错误:TypeError: this.userService.currentUser.subscribe is not a function
- php - 在 Laravel 中使用 join 和 group by 编写 SQL 总和?
- php - 具有特定格式的增量数字