当前位置: 首页 > news >正文

数据库连接使用问题 - 1

原理       

 open-in-view 是 Spring Boot ⾃动加载 Spring Data JPA 提供的⼀个配置,全称为 spring.jpa.open-in-view=true,它只有 true 和 false 两个值,默认是 true。
        这个配置为true时,会导致Web MVC请求处理的一开始,就从连接池取一个数据库连接放到本地线程变量;Web MVC请求处理结束后,才会归还给连接池
open-in-view 机制是为了解决在 mvc 的 controller 中使用了 hibernate 的 lazy load 的属性时 no session 抛出的LazyInitializationException 异常

        这个处理逻辑位于OpenEntityManagerInViewInterceptor.preHandle,在Sentinel处理代码SentinelResourceAspectExt之前,所以Sentinel限流无法阻止JPA取数据库连接。
 

隐患一


        如果业务代码中,有耗时操作,就导致数据库连接还回连接池变慢,进而引起雪崩效应,导致tomcat处理线程大量增加,而处理性能却无法提高,所有Web MVC请求都无法响应,应用提供的服务中断。

@ResponseBody
@RequestMapping(value = "/xxx/send", method = RequestMethod.POST)
@SentinelResource(value = "xxxdcc#send", entryType = EntryType.IN)
public SendXXXResp sendSms(@RequestBody SendXXXVo sendXXXVo) {//同步调用第三方系统,耗时超过一定时间,如3sSendXXXResp sendXXXResp = new SendXXXResp();return sendXXXResp;
}

        如果数据库连接池最大连接数为200,同步调用第三方系统耗时3s。那么这个接口的QPS达到70时,会导致应用雪崩,整个应用无法提供服务。

隐患二

        当jpa与mybatis等框架混合使用时,存在死锁的问题。一个Web MVC请求处理时,JPA框架会从连接池中取一个数据库连接放入本地线程变量,业务处理代码使用mybatis访问数据库,也需要取一个数据库连接,在极端情况下,取不到就会等待,导致JPA取的连接也没有还给连接池,导致死锁。
也会导致tomcat处理线程大量增加,而处理性能却无法提高,所有Web MVC请求都无法响应,应用提供的服务中断。
示例代码:

@ResponseBody
@RequestMapping(value = "/xxx/send", method = RequestMethod.POST)
@SentinelResource(value = "xxx#send", entryType = EntryType.IN)
public SendXXXResp sendSms(@RequestBody SendSmsVo sendSmsVo) {//使用mybatis框架访问数据库CallingConfig callingConfig=callingConfigMapper.selectById(sendXXXVo.getXXXAccount());SendXXResp sendXXXResp = new SendXXXResp();return sendXXXResp;
}

        如果数据库连接池最大连接数为200,这个接口QPS达到200。即使方法体中没有耗时操作,也会导致应用雪崩,整个应用无法提供服务。

修改建议
  1. 将spring.jpa.open-in-view配置为false,注意不要设置成了“spring.shardingsphere.jpa.open-in-view”
  2. 不要使用JPA 的关联查询,如不要使用@OneToMany等关联查询的注解。以免open-in-view为false时,出现LazyInitializationException 异常。

annel_account_config账号表与calling_config主叫号码表是一对多的关系;

JPA中设置的关联查询:

@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "channelAccountId")
private List<CallingConfigInfo> callingConfigList = new ArrayList<>();

在Controller中进行了查询使用:

ChannelAccountConfigInfo channelAccountConfigInfo= channelAccountConfigRepository.findOne(1L);
List<CallingConfigInfo> callingConfigList = ObjectUtil.getOptional(()->channelAccountConfigInfo.getCallingConfigList()).orElse(new ArrayList<>());
for(CallingConfigInfo callingConfigInfo:callingConfigList){log.info("Calling:"+callingConfigInfo.getCalling());
}

http://www.lryc.cn/news/275207.html

相关文章:

  • 【已解决】You have an error in your SQL syntax
  • 如何在Ubuntu安装SVN服务并结合cpolar实现公网TCP地址远程访问本地服务
  • windows监控进程是否还活着,查看内存使用率
  • C#-词法结构
  • GitHub pull request(傻瓜式入门版)
  • Studio 3T客户端连接Mongodb数据库服务
  • 算法每日一题:赎金信 | 字符和整数
  • 数字孪生在虚拟现实(VR)中的应用
  • iOS实时查看App运行日志
  • 论文阅读:通过时空生成卷积网络合成动态模式(重点论文)
  • html2canvas+jsPDF导出超长网页的PDF
  • 云计算:OpenStack 分布式架构管理VXLAN网络(单控制节点与多计算节点)
  • MATLAB --- dlmread( )函数的用法
  • STM32CubeMX RS485接口使用
  • ClickHouse(20)ClickHouse集成PostgreSQL表引擎详细解析
  • R304S 指纹识别模块功能实现示例
  • 2、Excel:基础概念、表格结构与常见函数
  • 鱼类识别Python+深度学习人工智能+TensorFlow+卷积神经网络算法
  • ThreadLocal线程重用导致用户信息错乱的 Bug
  • 洛谷——P1143 进制转换
  • linux stop_machine 停机机制应用及一次触发 soft lockup 分析
  • ARM 链接器优化功能介绍
  • 动手学深度学习之卷积神经网络之池化层
  • HackTheBox - Medium - Linux - Ambassador
  • 嵌入式——循环队列
  • 2024.1.7-实战-docker方式给自己网站部署prometheus监控ecs资源使用情况-2024.1.7(测试成功)
  • 20240107 SQL基础50题打卡
  • 阿里云公网带宽出网和入网是什么?上行和下行是什么?
  • eureka工作原理是什么
  • Vue中的事件委托(事件代理)使用方法介绍