星云 ERP
项目简介
下载源码
项目部署
项目模块
liyade-dependencies-common
liyade-dependencies-web-starter
启用缓存机制
实现图片验证码
解决Lettuce连接池超时问题
ImportSelector实战解析
liyade-admin
liyade-settle
liyade-sc
liyade-chart
liyade-basedata
liyade-common
liyade-dependencies-activemq-starter
liyade-core
liyade-template
liyade-dependencies-cloud-starter
liyade-dependencies-mq-starter
liyade-dependencies-websocket-starter
liyade-template-core
liyade-dependencies-web-common
spring.factories
lombok.config
event
lombok.config 文件详解
使用手册
登录功能
系统管理
菜单管理
部门管理
数据库字典
菜单收藏(sys_menu_collect)
库存成本调整单明细(tbl_stock_cost_adjust_sheet_detail)
库存盘点参数设置(tbl_take_stock_config)
库存盘点任务(tbl_take_stock_plan)
库存盘点任务明细(tbl_take_stock_plan_detail)
库存盘点单(tbl_take_stock_sheet)
库存盘点单明细(tbl_take_stock_sheet_detail)
系统参数(sys_parameter)
门店(tbl_shop)
角色与菜单关系表(sys_role_menu)
角色(sys_role)
岗位(sys_position)
库存成本调整单(tbl_stock_cost_adjust_sheet)
菜单(sys_menu)
部门(sys_dept)
商品库存变动记录(tbl_product_stock_log)
商品库存(tbl_product_stock)
商品批次库存(tbl_product_lot_stock)
商品批次(tbl_product_lot)
库存预先盘点单明细(tbl_pre_take_stock_sheet_detail)
库存预先盘点单(tbl_pre_take_stock_sheet)
订单图表数据(tbl_order_chart)
用户绑定手机号表(sys_user_telephone)
零售出库单批次明细(tbl_retail_out_sheet_detail_lot)
采购参数设置(tbl_purchase_config)
采购订单(tbl_purchase_order)
采购订单明细(tbl_purchase_order_detail)
采购退单(tbl_purchase_return)
采购退单明细(tbl_purchase_return_detail)
采购收货单(tbl_receive_sheet)
采购收货单明细(tbl_receive_sheet_detail)
零售参数设置(tbl_retail_config)
零售出库单(tbl_retail_out_sheet)
零售出库单明细(tbl_retail_out_sheet_detail)
用户与角色关系表(sys_user_role)
零售退单(tbl_retail_return)
零售退单明细(tbl_retail_return_detail)
销售参数设置(tbl_sale_config)
销售订单(tbl_sale_order)
销售订单明细(tbl_sale_order_detail)
销售出库单(tbl_sale_out_sheet)
销售出库单明细(tbl_sale_out_sheet_detail)
销售出库单批次明细(tbl_sale_out_sheet_detail_lot)
销售退单(tbl_sale_return)
销售退单明细(tbl_sale_return_detail)
商品零售价(base_data_product_retail)
代码生成基本信息(gen_generate_info)
数据对象列信息(gen_data_object_column)
数据对象(gen_data_object)
新增功能代码生成配置(gen_create_column_config)
地区字典表(dic_city)
供应商(base_data_supplier)
仓库(base_data_store_center)
商品和销售属性值关系表(base_data_product_saleprop_item_relation)
商品销售属性值(base_data_product_saleprop_item)
商品销售属性组(base_data_product_saleprop_group)
商品销售价(base_data_product_sale)
查询功能代码生成配置(gen_query_column_config)
商品采购价(base_data_product_purchase)
商品属性值(base_data_product_property_item)
商品属性(base_data_product_property)
商品SPU和商品属性关系表(base_data_product_poly_property)
商品SPU(base_data_product_poly)
商品类目和商品属性关系表(base_data_product_category_property)
商品类目(base_data_product_category)
商品品牌(base_data_product_brand)
商品(base_data_product)
会员(base_data_member)
收入项目(settle_in_item)
用户与岗位关系表(sys_user_position)
用户与部门关系表(sys_user_dept)
用户(sys_user)
详情功能代码生成配置(gen_detail_column_config)
系统设置(sys_config)
供应商结算单明细(settle_sheet_detail)
供应商结算单(settle_sheet)
供应商预付款单明细(settle_pre_sheet_detail)
供应商预付款单(settle_pre_sheet)
支出项目(settle_out_item)
客户(base_data_customer)
供应商费用单明细(settle_fee_sheet_detail)
供应商费用单(settle_fee_sheet)
供应商对账单明细(settle_check_sheet_detail)
供应商对账单(settle_check_sheet)
树形数据节点关系表(recursion_mapping)
操作日志(op_logs)
修改功能代码生成配置(gen_update_column_config)
数据库单表列信息(gen_simple_table_column)
数据库单表(gen_simple_table)
查询参数功能代码生成配置(gen_query_params_column_config)
-
+
首页
解决Lettuce连接池超时问题
本文分析了使用Lettuce连接Redis时遇到的超时问题,问题表现为长时间未连接后重新连接会超时,但多次尝试后可以成功。解决方案包括切换到jedis连接池以及通过定时任务保持连接活跃。对于方案一,详细介绍了从pom.xml中排除Lettuce并引入jedis,以及相应的配置和RedisTemplate的设置。方案二则提出通过定时任务每隔一段时间验证连接,以防止连接因闲置被关闭。 ## 问题分析定位 一直连着没问题,只要间隔一段时间不连,再去连的时候就会出现超时问题,超时几次后就可以连上,再去操作就没问题,但是再次间隔一段时间去连,又会出现超时问题。 所以,问题不是出在代码逻辑上,而是出现在lettuce连接池上面! ## 解决方案 第一种. 简单直接 ,换jedis连接池(缺陷:还是没解决lettuce超时问题); 第二种. 找到超时原因 ,解决它; ### 方案一 第一步:添加maven依赖(排除lettuce,添加jedis) ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <exclusions> <exclusion> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency> ``` 第二步:改配置 ``` redis: open: false # 是否开启redis缓存 true开启 false关闭 database: 0 host: 127.0.0.1 port: 6379 password: # 密码(默认为空) timeout: 6000ms # 连接超时时长(毫秒) jedis: pool: max-active: 1000 # 连接池最大连接数(使用负值表示没有限制) max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制) max-idle: 10 # 连接池中的最大空闲连接 min-idle: 5 # 连接池中的最小空闲连接 ``` 第三步:修改配置类 ``` @Configuration public class RedisConfig { @Autowired private RedisConnectionFactory factory; @Bean public RedisTemplate<String, Object> redisTemplate() { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new StringRedisSerializer()); redisTemplate.setConnectionFactory(factory); return redisTemplate; } @Bean public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) { return redisTemplate.opsForHash(); } @Bean public ValueOperations<String, String> valueOperations(RedisTemplate<String, String> redisTemplate) { return redisTemplate.opsForValue(); } @Bean public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) { return redisTemplate.opsForList(); } @Bean public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) { return redisTemplate.opsForSet(); } @Bean public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) { return redisTemplate.opsForZSet(); } } ``` 以上三步就可以了,这里贴出来一个redis工具类,省得来回找了; ``` @Component public class RedisUtils { @Autowired private RedisTemplate<String, Object> redisTemplate; @Autowired private ValueOperations<String, String> valueOperations; @Autowired private HashOperations<String, String, Object> hashOperations; @Autowired private ListOperations<String, Object> listOperations; @Autowired private SetOperations<String, Object> setOperations; @Autowired private ZSetOperations<String, Object> zSetOperations; /** 默认过期时长,单位:秒 */ public final static long DEFAULT_EXPIRE = 60 * 60 * 24; /** 不设置过期时长 */ public final static long NOT_EXPIRE = -1; private final static Gson gson = new Gson(); public void set(String key, Object value, long expire){ valueOperations.set(key, toJson(value)); if(expire != NOT_EXPIRE){ redisTemplate.expire(key, expire, TimeUnit.SECONDS); } } public void set(String key, Object value){ set(key, value, DEFAULT_EXPIRE); } public <T> T get(String key, Class<T> clazz, long expire) { String value = valueOperations.get(key); if(expire != NOT_EXPIRE){ redisTemplate.expire(key, expire, TimeUnit.SECONDS); } return value == null ? null : fromJson(value, clazz); } public <T> T get(String key, Class<T> clazz) { return get(key, clazz, NOT_EXPIRE); } public String get(String key, long expire) { String value = valueOperations.get(key); if(expire != NOT_EXPIRE){ redisTemplate.expire(key, expire, TimeUnit.SECONDS); } return value; } public String get(String key) { return get(key, NOT_EXPIRE); } public void delete(String key) { redisTemplate.delete(key); } /** * Object转成JSON数据 */ private String toJson(Object object){ if(object instanceof Integer || object instanceof Long || object instanceof Float || object instanceof Double || object instanceof Boolean || object instanceof String){ return String.valueOf(object); } return gson.toJson(object); } /** * JSON数据,转成Object */ private <T> T fromJson(String json, Class<T> clazz){ return gson.fromJson(json, clazz); } } ``` ### 方案二 既然是长时间没有连导致的链接超时,那连一个就好了,就像心跳一样,这样链接池就不会关闭了; 搜来的方案先贴出来:(思路可行,后期校验) ``` 1.定时校验来解决 /** * 每隔2秒校验异常lettuce连接是否正常,解决长期空闲lettuce连接关闭但是netty不能及时监控到的问题 * @author hujun */ @Component @Slf4j public class LettuceConnectionValidTask { @Autowired private RedisConnectionFactory redisConnectionFactory; @Scheduled(cron="0/2 * * * * ?") public void task() { if(redisConnectionFactory instanceof LettuceConnectionFactory){ LettuceConnectionFactory c=(LettuceConnectionFactory)redisConnectionFactory; c.validateConnection(); } } } 2.开启获取连接的校验 @Component @Slf4j public class LettuceConnectionValidConfig implements InitializingBean { @Autowired private RedisConnectionFactory redisConnectionFactory; @Override public void afterPropertiesSet() throws Exception { if(redisConnectionFactory instanceof LettuceConnectionFactory){ LettuceConnectionFactory c=(LettuceConnectionFactory)redisConnectionFactory; c.setValidateConnection(true); } } } ``` ## 本项目使用 
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码