
-
日志
-
org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis; nested exception is org.springframework.data.redis.connection.PoolException: Could not get a resource from the pool; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to 192.168.10.143:6350 at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.translateException(LettuceConnectionFactory.java:1534) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1442) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getNativeConnection(LettuceConnectionFactory.java:1228) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getConnection(LettuceConnectionFactory.java:1211) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getSharedReactiveConnection(LettuceConnectionFactory.java:985) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getReactiveConnection(LettuceConnectionFactory.java:446) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getReactiveConnection(LettuceConnectionFactory.java:99) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE] at reactor.core.publisher.MonoSupplier.call(MonoSupplier.java:85) ~[reactor-core-3.3.11.RELEASE.jar:3.3.11.RELEASE] at reactor.core.publisher.FluxSubscribeOnCallable$CallableSubscribeOnSubscription.run(FluxSubscribeOnCallable.java:225) ~[reactor-core-3.3.11.RELEASE.jar:3.3.11.RELEASE] at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:68) ~[reactor-core-3.3.11.RELEASE.jar:3.3.11.RELEASE] at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:28) ~[reactor-core-3.3.11.RELEASE.jar:3.3.11.RELEASE] at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266) ~[na:1.8.0_251] at java.util.concurrent.FutureTask.run(FutureTask.java) ~[na:1.8.0_251] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_251] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_251] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_251] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_251] at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_251] Caused by: org.springframework.data.redis.connection.PoolException: Could not get a resource from the pool; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to 192.168.10.143:6350 at org.springframework.data.redis.connection.lettuce.LettucePoolingConnectionProvider.getConnection(LettucePoolingConnectionProvider.java:109) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1440) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE] ... 16 common frames omitted Caused by: io.lettuce.core.RedisConnectionException: Unable to connect to 192.168.10.143:6350 at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:78) ~[lettuce-core-5.3.5.RELEASE.jar:5.3.5.RELEASE] at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:56) ~[lettuce-core-5.3.5.RELEASE.jar:5.3.5.RELEASE] at io.lettuce.core.AbstractRedisClient.getConnection(AbstractRedisClient.java:242) ~[lettuce-core-5.3.5.RELEASE.jar:5.3.5.RELEASE] at io.lettuce.core.RedisClient.connect(RedisClient.java:206) ~[lettuce-core-5.3.5.RELEASE.jar:5.3.5.RELEASE] at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.lambda$getConnection(StandaloneConnectionProvider.java:115) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE] at java.util.Optional.orElseGet(Optional.java:267) ~[na:1.8.0_251] at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.getConnection(StandaloneConnectionProvider.java:115) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE] at org.springframework.data.redis.connection.lettuce.LettucePoolingConnectionProvider.lambda$null<(LettucePoolingConnectionProvider.java:97) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE] at io.lettuce.core.support.ConnectionPoolSupport$RedisPooledObjectFactory.create(ConnectionPoolSupport.java:211) ~[lettuce-core-5.3.5.RELEASE.jar:5.3.5.RELEASE] at io.lettuce.core.support.ConnectionPoolSupport$RedisPooledObjectFactory.create(ConnectionPoolSupport.java:201) ~[lettuce-core-5.3.5.RELEASE.jar:5.3.5.RELEASE] at org.apache.commons.pool2.BasePooledObjectFactory.makeObject(BasePooledObjectFactory.java:58) ~[commons-pool2-2.8.1.jar:2.8.1] at org.apache.commons.pool2.impl.GenericObjectPool.create(GenericObjectPool.java:899) ~[commons-pool2-2.8.1.jar:2.8.1] at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:429) ~[commons-pool2-2.8.1.jar:2.8.1] at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:354) ~[commons-pool2-2.8.1.jar:2.8.1] at io.lettuce.core.support.ConnectionPoolSupport.borrowObject(ConnectionPoolSupport.java:122) ~[lettuce-core-5.3.5.RELEASE.jar:5.3.5.RELEASE] at io.lettuce.core.support.ConnectionPoolSupport.borrowObject(ConnectionPoolSupport.java:117) ~[lettuce-core-5.3.5.RELEASE.jar:5.3.5.RELEASE] at org.springframework.data.redis.connection.lettuce.LettucePoolingConnectionProvider.getConnection(LettucePoolingConnectionProvider.java:103) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE] ... 17 common frames omitted Caused by: io.lettuce.core.RedisCommandTimeoutException: Command timed out after 12 millisecond(s) at io.lettuce.core.ExceptionFactory.createTimeoutException(ExceptionFactory.java:51) ~[lettuce-core-5.3.5.RELEASE.jar:5.3.5.RELEASE] at io.lettuce.core.protocol.CommandExpiryWriter.lambda$potentiallyExpire<(CommandExpiryWriter.java:172) ~[lettuce-core-5.3.5.RELEASE.jar:5.3.5.RELEASE] at io.netty.util.concurrent.PromiseTask.runTask(PromiseTask.java:98) ~[netty-common-4.1.53.Final.jar:4.1.53.Final] at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:170) ~[netty-common-4.1.53.Final.jar:4.1.53.Final] at io.netty.util.concurrent.DefaultEventExecutor.run(DefaultEventExecutor.java:66) ~[netty-common-4.1.53.Final.jar:4.1.53.Final] at io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.53.Final.jar:4.1.53.Final] at io.netty.util.internal.ThreadExecutorMap.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.53.Final.jar:4.1.53.Final] at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.53.Final.jar:4.1.53.Final] ... 1 common frames omitted
-
-
由于lettuce没有心跳检测,直接能判断为查询redis数据超时了。
-
网上百度了一波,发现有结论说是替换lettuce 为 jedis 就能解决问题**【此方案无效】**
-
修改pom文件
-
dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-data-redis<artifactId> <exclusions> exclusion> <groupId>redis.clientsgroupId> artifactId>jedis<artifactId> <exclusion> exclusion> <groupId>io.lettucegroupId> artifactId>lettuce-coreartifactId> exclusion> <exclusions> <dependency> dependency> <groupId>redis.clientsgroupId> artifactId>jedis- 前面将redis的连接池从lettuce换成了jedis,但是依然出现了redis超时异常,由此可见应该从配置问题找起。不过首先先定位下报错位置,从错误日志最底部的方法栈排查java.net.SocketInputStream.socketRead0为本地方法,可以从java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
artifactId>Caused by: java.net.SocketTimeoutException: Read timed out at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) at java.net.SocketInputStream.read(SocketInputStream.java:171) at java.net.SocketInputStream.read(SocketInputStream.java:141) at java.net.SocketInputStream.read(SocketInputStream.java:127) at redis.clients.jedis.util.RedisInputStream.ensureFill(RedisInputStream.java:199) ... 111 common frames omitteddependency>
-
-
-
替换后,使用jedis链接池运行一段时间,又报出了JedisConnectionException: java.net.SocketTimeoutException: Read timed out异常,接下去继续分析
-
org.springframework.data.redis.RedisConnectionFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.fetchJedisConnector(JedisConnectionFactory.java:282) at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.getConnection(JedisConnectionFactory.java:476) at org.springframework.data.redis.core.RedisConnectionUtils.doGetConnection(RedisConnectionUtils.java:134) at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:97) at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:84) at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:215) at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:188) at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:96) at org.springframework.data.redis.core.DefaultSetOperations.size(DefaultSetOperations.java:330) at com.rivtower.rivus.product.service.impl.ProductDefServiceImpl.handlePublishingQty(ProductDefServiceImpl.java:279) at com.rivtower.rivus.product.service.impl.ProductDefServiceImpl$$FastClassBySpringCGLIB$$e459cf51.invoke() at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:687) at com.rivtower.rivus.product.service.impl.ProductDefServiceImpl$$EnhancerBySpringCGLIB$$85b0914f.handlePublishingQty( ) at com.rivtower.rivus.product.controller.ProductDefController.queryProductDefByRegisterId(ProductDefController.java:85) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter.doFilterInternal(BearerTokenAuthenticationFilter.java:130) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92) at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:747) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748) Caused by: redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out at redis.clients.jedis.util.RedisInputStream.ensureFill(RedisInputStream.java:205) at redis.clients.jedis.util.RedisInputStream.readByte(RedisInputStream.java:43) at redis.clients.jedis.Protocol.process(Protocol.java:155) at redis.clients.jedis.Protocol.read(Protocol.java:220) at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:278) at redis.clients.jedis.Connection.getStatusCodeReply(Connection.java:196) at redis.clients.jedis.BinaryClient.connect(BinaryClient.java:119) at redis.clients.jedis.BinaryJedis.connect(BinaryJedis.java:1904) at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.fetchJedisConnector(JedisConnectionFactory.java:277) ... 103 common frames omitted Caused by: java.net.SocketTimeoutException: Read timed out at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) at java.net.SocketInputStream.read(SocketInputStream.java:171) at java.net.SocketInputStream.read(SocketInputStream.java:141) at java.net.SocketInputStream.read(SocketInputStream.java:127) at redis.clients.jedis.util.RedisInputStream.ensureFill(RedisInputStream.java:199) ... 111 common frames omitted
-
由于排查SocketInputStream这个IO类没有识别性,最终定位错误日志最终在redis.clients.jedis.util.RedisInputStream.ensureFill(RedisInputStream.java:199),
定位代码报错位置
- SocketInputStream
下断点后排查,发现超时时间是SocketInputStream的一个属性,那么就找下这个属性的初始化赋值。
- <
-
方向查询SocketInputStream的初始化创建过程
-
- RedisInputStream( InputStream,int in) < size- .. redis.clients.jedisconnectConnection()<- newRedisInputStream ( .getInputStreamsocket())<- .createSocket jedisSocketFactory()<- DefaultJedisSocketFactory. createSocket()@Overridepublic
-
-
查看createSocket()源码,发现超时时间是 通过getSoTimeout()获取,getSoTimeout()方法获取的是DefaultJedisSocketFactory的属性值soTimeout,那么接下去追溯DefaultJedisSocketFactory创建过程
-
Socket createSocket ( )throwsIOException Socket = { null socket ; try= new { socket Socket ( );.setReuseAddress // ->@wjw_add socket(true);.setKeepAlive socket(true);// Will monitor the TCP connection is// valid . setTcpNoDelay socket(true);// Socket buffer Whetherclosed, to// ensure timely delivery of data . setSoLinger socket(true,0) ;// Control calls close () method,// the underlying socket is closed // immediately // <-@wjw_add . connect socket(newInetSocketAddress( getHost(),getPort( )),getConnectionTimeout( ));//超时时间. setSoTimeout socket(getSoTimeout());if( ) ifssl( { null ==) = sslSocketFactory( { sslSocketFactory SSLSocketFactory )SSLSocketFactory. getDefault();}= . socket createSocket sslSocketFactory(,getHostsocket( ),getPort( ),true) ;if( null !=) ( sslParameters( { SSLSocket)). socketsetSSLParameters();sslParameters}if ( ( null!=) && hostnameVerifier( ! .verifyhostnameVerifier(getHost(),(( SSLSocket)). socketgetSession())))String= { String message . format("The connection to '%s' failed ssl/tls hostname verification.", getHost( ));thrownew JedisConnectionException ( );message}} return ; } socketcatch ( Exception )if ex( { != nullsocket ) .close { socket();}throw ; } ex}DefaultJedisSocketFactory(String host, int port, int connectionTimeout, int soTimeout, boolean ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) <- setSoTimeout() <- BinaryJedis(final String host, final int port, final int connectionTimeout, final int soTimeout) <- Jedis(final String host, final int port, final int connectionTimeout, final int soTimeout) <- JedisConnectionFactory.getActiveSentinel()public
-
-
DefaultJedisSocketFactory创建过程
-
class
-
-
在JedisConnectionFactory.getActiveSentinel方法中找到如下逻辑
-
JedisConnectionFactory implements InitializingBean , DisposableBean, RedisConnectionFactoryprivate final { JedisClientConfiguration ; private clientConfigurationJedis getActiveSentinel ( )Assert. { isTrue(RedisConfiguration.isSentinelConfiguration(),configuration"SentinelConfig must not be null!") ;for( RedisNode :( node ( SentinelConfiguration)). configurationgetSentinels())//创建JedisJedis { = new jedis Jedis ( .getHostnode(),.getPort node(),getConnectTimeout( ),getReadTimeout( ));tryif ( { . pingjedis().equalsIgnoreCase("pong"))potentiallySetClientName( { );jedisreturn; } jedis} catch ( Exception ). exwarn { log(String.format("Ping failed for sentinel host:%s",.getHost node()),); ex}} throw new InvalidDataAccessResourceUsageException ( "No Sentinel found");}private int getReadTimeout ( )returnMath { . toIntExact(.getReadTimeoutclientConfiguration().toMillis());}} package . -
可以看到,readTimeOut最终是获取了JedisClientConfiguration clientConfiguration。接下去还是一样,查询JedisClientConfiguration的初始化赋值过程
-
-
下断点排查是通过public JedisConnectionFactory(RedisStandaloneConfiguration standaloneConfig, JedisClientConfiguration clientConfig) 构造方法初始化的 JedisConnectionFactory。而在此构造方法中传入了 JedisClientConfiguration clientConfig,这个类的具体实现类是 DefaultJedisClientConfiguration,这里可以发现已经是排查到spring-data-redis模块了,接下去可以提前设想下,这个Configuration类 读取的配置 是读取 yml文件或者config文件的配置。
-
. org.springframework.data.redis;connectionclassjedisDefaultJedisClientConfiguration implements JedisClientConfiguration DefaultJedisClientConfiguration ( { boolean,@Nullable useSslSSLSocketFactory , @Nullable sslSocketFactorySSLParameters , @Nullable sslParametersHostnameVerifier , boolean hostnameVerifier, @Nullable usePoolingGenericObjectPoolConfig , @Nullable poolConfigString , Duration clientName, Duration readTimeout) this connectTimeout. { =;useSsl this useSsl. =OptionalsslSocketFactory . ofNullable();sslSocketFactorythis. =OptionalsslParameters . ofNullable();sslParametersthis. =OptionalhostnameVerifier . ofNullable();hostnameVerifierthis. =;usePooling this usePooling. =OptionalpoolConfig . ofNullable();poolConfigthis. =OptionalclientName . ofNullable();clientNamethis. =;readTimeout this readTimeout. =;connectTimeout } connectTimeout} public interface
-
继续追溯org.springframework.data.redis.connection.jedis.DefaultJedisClientConfiguration 初始化过程
-
JedisClientConfiguration private Duration { = Duration readTimeout . ofMillis(Protocol.);DEFAULT_TIMEOUT@Overridepublic JedisClientConfigurationBuilder readTimeout ( Duration)Assert readTimeout. { notNull(,"Duration must not be null!"readTimeout) ;this. =;readTimeout return readTimeoutthis ; }@Override public JedisClientConfiguration build ( )returnnew { DefaultJedisClientConfiguration ( ,,useSsl, sslSocketFactory, sslParameters, hostnameVerifier, usePooling, poolConfig, clientName) readTimeout; connectTimeout}} package .
-
-
最终找到了 spring-data-redis-starter的自动装配的类
-
. org.springframework.boot.autoconfigure;dataimportredis. . javaUnknownHostExceptionnet;import. . javaDurationtime;import. . org.apache.commons.pool2GenericObjectPoolimpl;import. . redis.clientsJedisjedis;import. . redis.clientsJedisPoolConfigjedis;import. . org.springframework.beansObjectProviderfactory;import. . org.springframework.boot.autoconfigureConditionalOnClasscondition;import. . org.springframework.boot.autoconfigureConditionalOnMissingBeancondition;import. . org.springframework.contextBeanannotation;import. . org.springframework.contextConfigurationannotation;import. . org.springframework.data.redisRedisClusterConfigurationconnection;import. . org.springframework.data.redisRedisConnectionFactoryconnection;import. . org.springframework.data.redisRedisSentinelConfigurationconnection;import. . org.springframework.data.redis.connectionJedisClientConfigurationjedis;import. . org.springframework.data.redis.connectionJedisClientConfigurationjedis.JedisClientConfigurationBuilder;import. . org.springframework.data.redis.connectionJedisConnectionjedis;import. . org.springframework.data.redis.connectionJedisConnectionFactoryjedis;import. . org.springframeworkStringUtilsutil;/** * Redis connection configuration using Jedis. * * @author Mark Paluch * @author Stephane Nicoll */@Configuration ( =falseproxyBeanMethods ) @ConditionalOnClass( GenericObjectPool.{ class,JedisConnection. class,Jedis. class}) classJedisConnectionConfiguration extends RedisConnectionConfiguration JedisConnectionConfiguration ( { RedisProperties,ObjectProvider properties< RedisSentinelConfiguration,ObjectProvider> sentinelConfiguration< RedisClusterConfiguration)super> clusterConfiguration( { ,,properties) sentinelConfiguration; clusterConfiguration}@Bean @ConditionalOnMissingBean ( RedisConnectionFactory.class)JedisConnectionFactoryredisConnectionFactory ( ObjectProvider< JedisClientConfigurationBuilderCustomizer)throws> builderCustomizersUnknownHostException return createJedisConnectionFactory { ( );builderCustomizers}private JedisConnectionFactory createJedisConnectionFactory ( ObjectProvider< JedisClientConfigurationBuilderCustomizer)JedisClientConfiguration> builderCustomizers= { getJedisClientConfiguration clientConfiguration ( );builderCustomizersif( getSentinelConfig ()!=null ) returnnew { JedisConnectionFactory ( getSentinelConfig(),); clientConfiguration}if ( getClusterConfiguration ()!=null ) returnnew { JedisConnectionFactory ( getClusterConfiguration(),); clientConfiguration}return new JedisConnectionFactory ( getStandaloneConfig(),); clientConfiguration}private JedisClientConfiguration getJedisClientConfiguration ( ObjectProvider< JedisClientConfigurationBuilderCustomizer)JedisClientConfigurationBuilder> builderCustomizers= { applyProperties builder ( JedisClientConfiguration.builder());.= RedisPropertiesgetPropertiesPool pool ( ).getJedis().getPool();if( != nullpool ) applyPooling( { ,)pool; builder}if ( StringUtils .hasText(getProperties().getUrl()))customizeConfigurationFromUrl( { );builder}. orderedStream builderCustomizers().forEach(().customizercustomize -> customizer())builder;return. build builder();}private JedisClientConfigurationBuilder applyProperties ( JedisClientConfigurationBuilder)if builder( { getProperties ().isSsl()).useSsl { builder();}if ( getProperties ().getTimeout()!=null ) Duration= { getProperties timeout ( ).getTimeout();.readTimeout builder().timeoutconnectTimeout();timeout}if ( StringUtils .hasText(getProperties().getClientName())).clientName { builder(getProperties().getClientName());}return ; } builderprivate void applyPooling ( .,RedisProperties.Pool pool) JedisClientConfiguration.JedisClientConfigurationBuilder builderusePooling { builder().poolConfig(jedisPoolConfig())pool;}private JedisPoolConfig jedisPoolConfig ( .)RedisPropertiesJedisPoolConfigPool pool= { new config JedisPoolConfig ( );.setMaxTotal config(.getMaxActivepool());.setMaxIdle config(.getMaxIdlepool());.setMinIdle config(.getMinIdlepool());if( . getTimeBetweenEvictionRunspool()!=null ) .setTimeBetweenEvictionRunsMillis { config(.getTimeBetweenEvictionRunspool().toMillis());}if ( . getMaxWaitpool()!=null ) .setMaxWaitMillis { config(.getMaxWaitpool().toMillis());}return ; } configprivate void customizeConfigurationFromUrl ( .)JedisClientConfigurationConnectionInfoJedisClientConfigurationBuilder builder= { parseUrl connectionInfo ( getProperties().getUrl());if( . isUseSslconnectionInfo()).useSsl { builder();}} } @ConfigurationProperties( -
="spring.redis"prefix ) publicclass RedisProperties /** * Database index used by the connection factory. */ private { int = 0 database ; /** * Connection URL. Overrides host, port, and password. User is ignored. Example: * redis://user:password@example.com:6379 */private String ; /** * Redis server host. */ urlprivate String = "localhost" host ; /** * Login password of the redis server. */private String ; /** * Redis server port. */ passwordprivate int = 6379 port ; /** * Whether to enable SSL support. */private boolean ; /** * Connection timeout. */ sslprivate Duration ; /** * Client name to be set on connections with CLIENT SETNAME. */ timeoutprivate String ; private clientNameSentinel ; private sentinelCluster ; private clusterfinal Jedis = new jedis Jedis ( );privatefinal Lettuce = new lettuce Lettuce ( );publicint getDatabase ( )returnthis { . ;}databasepublic void setDatabase ( int)this database. { =;database } databasepublic String getUrl ( )returnthis { . ;}urlpublic void setUrl ( String)this url. { =;url } urlpublic String getHost ( )returnthis { . ;}hostpublic void setHost ( String)this host. { =;host } hostpublic String getPassword ( )returnthis { . ;}passwordpublic void setPassword ( String)this password. { =;password } passwordpublic int getPort ( )returnthis { . ;}portpublic void setPort ( int)this port. { =;port } portpublic boolean isSsl ( )returnthis { . ;}sslpublic void setSsl ( boolean)this ssl. { =;ssl } sslpublic void setTimeout ( Duration)this timeout. { =;timeout } timeoutpublic Duration getTimeout ( )returnthis { . ;}timeoutpublic String getClientName ( )returnthis { . ;}clientNamepublic void setClientName ( String)this clientName. { =;clientName } clientNamepublic Sentinel getSentinel ( )returnthis { . ;}sentinelpublic void setSentinel ( Sentinel)this sentinel. { =;sentinel } sentinelpublic Cluster getCluster ( )returnthis { . ;}clusterpublic void setCluster ( Cluster)this cluster. { =;cluster } clusterpublic Jedis getJedis ( )returnthis { . ;}jedispublic Lettuce getLettuce ( )returnthis { . ;}lettuce/** * Pool properties. */ public static class Pool /** * Maximum number of "idle" connections in the pool. Use a negative value to * indicate an unlimited number of idle connections. */ private { int = 8 maxIdle ; /** * Target for the minimum number of idle connections to maintain in the pool. This * setting only has an effect if both it and time between eviction runs are * positive. */private int = 0 minIdle ; /** * Maximum number of connections that can be allocated by the pool at a given * time. Use a negative value for no limit. */private int = 8 maxActive ; /** * Maximum amount of time a connection allocation should block before throwing an * exception when the pool is exhausted. Use a negative value to block * indefinitely. */private Duration = Duration maxWait . ofMillis(-1);/** * Time between runs of the idle object evictor thread. When positive, the idle * object evictor thread starts, otherwise no idle object eviction is performed. */private Duration ; public timeBetweenEvictionRunsint getMaxIdle ( )returnthis { . ;}maxIdlepublic void setMaxIdle ( int)this maxIdle. { =;maxIdle } maxIdlepublic int getMinIdle ( )returnthis { . ;}minIdlepublic void setMinIdle ( int)this minIdle. { =;minIdle } minIdlepublic int getMaxActive ( )returnthis { . ;}maxActivepublic void setMaxActive ( int)this maxActive. { =;maxActive } maxActivepublic Duration getMaxWait ( )returnthis { . ;}maxWaitpublic void setMaxWait ( Duration)this maxWait. { =;maxWait } maxWaitpublic Duration getTimeBetweenEvictionRuns ( )returnthis { . ;}timeBetweenEvictionRunspublic void setTimeBetweenEvictionRuns ( Duration)this timeBetweenEvictionRuns. { =;timeBetweenEvictionRuns } timeBetweenEvictionRuns} /** * Cluster properties. */ public static class Cluster /** * Comma-separated list of "host:port" pairs to bootstrap from. This represents an * "initial" list of cluster nodes and is required to have at least one entry. */ private { List < String;/** * Maximum number of redirects to follow when executing commands across the * cluster. */> nodesprivate Integer ; public maxRedirectsList < StringgetNodes(> )returnthis { . ;}nodespublic void setNodes ( List<String)this> nodes. { =;nodes } nodespublic Integer getMaxRedirects ( )returnthis { . ;}maxRedirectspublic void setMaxRedirects ( Integer)this maxRedirects. { =;maxRedirects } maxRedirects} /** * Redis sentinel properties. */ public static class Sentinel /** * Name of the Redis server. */ private { String ; /** * Comma-separated list of "host:port" pairs. */ masterprivate List < String;/** * Password for authenticating with sentinel(s). */> nodesprivate String ; public passwordString getMaster ( )returnthis { . ;}masterpublic void setMaster ( String)this master. { =;master } masterpublic List < StringgetNodes(> )returnthis { . ;}nodespublic void setNodes ( List<String)this> nodes. { =;nodes } nodespublic String getPassword ( )returnthis { . ;}passwordpublic void setPassword ( String)this password. { =;password } password} /** * Jedis client properties. */ public static class Jedis /** * Jedis pool configuration. */ private { Pool ; public poolPool getPool ( )returnthis { . ;}poolpublic void setPool ( Pool)this pool. { =;pool } pool} /** * Lettuce client properties. */ public static class Lettuce /** * Shutdown timeout. */ private { Duration = Duration shutdownTimeout . ofMillis(100);/** * Lettuce pool configuration. */private Pool ; private poolfinal Cluster = new cluster Cluster ( );publicDuration getShutdownTimeout ( )returnthis { . ;}shutdownTimeoutpublic void setShutdownTimeout ( Duration)this shutdownTimeout. { =;shutdownTimeout } shutdownTimeoutpublic Pool getPool ( )returnthis { . ;}poolpublic void setPool ( Pool)this pool. { =;pool } poolpublic Cluster getCluster ( )returnthis { . ;}clusterpublic static class Cluster private final { Refresh = new refresh Refresh ( );publicRefresh getRefresh ( )returnthis { . ;}refreshpublic static class Refresh /** * Cluster topology refresh period. */ private { Duration ; /** * Whether adaptive topology refreshing using all available refresh * triggers should be used. */ periodprivate boolean ; public adaptiveDuration getPeriod ( )returnthis { . ;}periodpublic void setPeriod ( Duration)this period. { =;period } periodpublic boolean isAdaptive ( )returnthis { . ;}adaptivepublic void setAdaptive ( boolean)this adaptive. { =;adaptive } adaptive} } } } //1.存在类存在属性依赖RedisTemplate,这就开始了Redis相关类bean的初始化 public
-
-
总结最后发现RedisInputStream的readTimeout的值,是从RedisProperties 配置类中获取的,获取的配置项是spring.redis.timeout
-
项目类依赖于RedisTemplate
-
class Test @Autowired private{ RedisTemplate < String,String;}> redisTemplate@Configuration @EnableCaching
-
-
RedisTemplate由项目中配置类创建Bean,此处决定RedisTemplate的初始化创建依赖于RedisConnectionFactory factory
-
//开启注解 public class RedisConfig extends CachingConfigurerSupport @Resource ( { ="customObjectMapper"name ) privateObjectMapper ; /** * redisTemplate相关配置 * @param factory * @return */ om@Bean public RedisTemplate < String,ObjectredisTemplate (> RedisConnectionFactory)RedisTemplate factory< { String,Object= new> template RedisTemplate < ()>;// 配置连接工厂. setConnectionFactory template();factory//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)Jackson2JsonRedisSerializer < Object=new> jacksonSerial Jackson2JsonRedisSerializer < (Object>.class);.setObjectMapper jacksonSerial();om// 值采用json序列化. setValueSerializer template();jacksonSerial//使用StringRedisSerializer来序列化和反序列化redis的key值. setKeySerializer template(newStringRedisSerializer( ));// 设置hash key 和value序列化模式. setHashKeySerializer template(newStringRedisSerializer( ));.setHashValueSerializer template();jacksonSerial.afterPropertiesSet template();return; } template} package .
-
-
RedisConnectionFactory 的创建是由org.springframework.boot.autoconfigure.data.redis.JedisConnectionConfiguration创建的。这里需要记住JedisConnectionConfiguration下的两个属性,因为JedisConnectionConfiguration是继承RedisConnectionConfiguration,在RedisConnectionConfiguration中存在属性 private final RedisProperties properties;后续会用到
-
. org.springframework.boot.autoconfigure;data/** * Redis connection configuration using Jedis. * * @author Mark Paluch * @author Stephane Nicoll */redis@Configuration ( =falseproxyBeanMethods ) @ConditionalOnClass( GenericObjectPool.{ class,JedisConnection. class,Jedis. class}) classJedisConnectionConfiguration extends RedisConnectionConfiguration JedisConnectionConfiguration ( { RedisProperties,ObjectProvider properties< RedisSentinelConfiguration,ObjectProvider> sentinelConfiguration< RedisClusterConfiguration)super> clusterConfiguration( { ,,properties) sentinelConfiguration; clusterConfiguration}//当项目中不存在RedisConnectionFactory,则创建RedisConnectionFactory @Bean @ConditionalOnMissingBean ( RedisConnectionFactory.class)JedisConnectionFactoryredisConnectionFactory ( ObjectProvider< JedisClientConfigurationBuilderCustomizer)throws> builderCustomizersUnknownHostException return createJedisConnectionFactory { //调用私有方法createJedisConnectionFactory(ObjectProviderbuilderCustomizers) ( );builderCustomizers}private JedisConnectionFactory createJedisConnectionFactory ( ObjectProvider< JedisClientConfigurationBuilderCustomizer)JedisClientConfiguration> builderCustomizers= { getJedisClientConfiguration clientConfiguration ( );builderCustomizersif( getSentinelConfig ()!=null ) returnnew { JedisConnectionFactory ( getSentinelConfig(),); clientConfiguration}if ( getClusterConfiguration ()!=null ) returnnew { JedisConnectionFactory ( getClusterConfiguration(),); clientConfiguration}return new JedisConnectionFactory ( getStandaloneConfig(),); clientConfiguration}private JedisClientConfiguration getJedisClientConfiguration ( ObjectProvider< JedisClientConfigurationBuilderCustomizer)JedisClientConfigurationBuilder> builderCustomizers= { applyProperties builder ( JedisClientConfiguration.builder());.= RedisPropertiesgetPropertiesPool pool ( ).getJedis().getPool();if( != nullpool ) applyPooling( { ,)pool; builder}if ( StringUtils .hasText(getProperties().getUrl()))customizeConfigurationFromUrl( { );builder}. orderedStream builderCustomizers().forEach(().customizercustomize -> customizer())builder;return. build builder();}private JedisClientConfigurationBuilder applyProperties ( JedisClientConfigurationBuilder)if builder( { getProperties ().isSsl()).useSsl { builder();}if ( getProperties ().getTimeout()!=null ) Duration= { getProperties timeout ( ).getTimeout();.readTimeout builder().timeoutconnectTimeout();timeout}if ( StringUtils .hasText(getProperties().getClientName())).clientName { builder(getProperties().getClientName());}return ; } builderprivate void applyPooling ( .,RedisProperties.Pool pool) JedisClientConfiguration.JedisClientConfigurationBuilder builderusePooling { builder().poolConfig(jedisPoolConfig())pool;}private JedisPoolConfig jedisPoolConfig ( .)RedisPropertiesJedisPoolConfigPool pool= { new config JedisPoolConfig ( );.setMaxTotal config(.getMaxActivepool());.setMaxIdle config(.getMaxIdlepool());.setMinIdle config(.getMinIdlepool());if( . getTimeBetweenEvictionRunspool()!=null ) .setTimeBetweenEvictionRunsMillis { config(.getTimeBetweenEvictionRunspool().toMillis());}if ( . getMaxWaitpool()!=null ) .setMaxWaitMillis { config(.getMaxWaitpool().toMillis());}return ; } configprivate void customizeConfigurationFromUrl ( .)JedisClientConfigurationConnectionInfoJedisClientConfigurationBuilder builder= { parseUrl connectionInfo ( getProperties().getUrl());if( . isUseSslconnectionInfo()).useSsl { builder();}} } abstract class -
RedisConnectionConfiguration private final { RedisProperties ; } properties@ConfigurationProperties (
-
-
而从JedisConnectionConfiguration(RedisProperties properties,
ObjectProvider sentinelConfiguration,
ObjectProvider clusterConfiguration)可以看到,JedisConnectionConfiguration依赖RedisProperties配置类-
="spring.redis"prefix ) publicclass RedisProperties /** * Database index used by the connection factory. */ private { int = 0 database ; /** * Connection URL. Overrides host, port, and password. User is ignored. Example: * redis://user:password@example.com:6379 */private String ; /** * Redis server host. */ urlprivate String = "localhost" host ; /** * Login password of the redis server. */private String ; /** * Redis server port. */ passwordprivate int = 6379 port ; /** * Whether to enable SSL support. */private boolean ; /** * Connection timeout. */ sslprivate Duration ; /** * Client name to be set on connections with CLIENT SETNAME. */ timeoutprivate String ; private clientNameSentinel ; private sentinelCluster ; private clusterfinal Jedis = new jedis Jedis ( );privatefinal Lettuce = new lettuce Lettuce ( );publicint getDatabase ( )returnthis { . ;}databasepublic void setDatabase ( int)this database. { =;database } databasepublic String getUrl ( )returnthis { . ;}urlpublic void setUrl ( String)this url. { =;url } urlpublic String getHost ( )returnthis { . ;}hostpublic void setHost ( String)this host. { =;host } hostpublic String getPassword ( )returnthis { . ;}passwordpublic void setPassword ( String)this password. { =;password } passwordpublic int getPort ( )returnthis { . ;}portpublic void setPort ( int)this port. { =;port } portpublic boolean isSsl ( )returnthis { . ;}sslpublic void setSsl ( boolean)this ssl. { =;ssl } sslpublic void setTimeout ( Duration)this timeout. { =;timeout } timeoutpublic Duration getTimeout ( )returnthis { . ;}timeoutpublic String getClientName ( )returnthis { . ;}clientNamepublic void setClientName ( String)this clientName. { =;clientName } clientNamepublic Sentinel getSentinel ( )returnthis { . ;}sentinelpublic void setSentinel ( Sentinel)this sentinel. { =;sentinel } sentinelpublic Cluster getCluster ( )returnthis { . ;}clusterpublic void setCluster ( Cluster)this cluster. { =;cluster } clusterpublic Jedis getJedis ( )returnthis { . ;}jedispublic Lettuce getLettuce ( )returnthis { . ;}lettuce/** * Pool properties. */ public static class Pool /** * Maximum number of "idle" connections in the pool. Use a negative value to * indicate an unlimited number of idle connections. */ private { int = 8 maxIdle ; /** * Target for the minimum number of idle connections to maintain in the pool. This * setting only has an effect if both it and time between eviction runs are * positive. */private int = 0 minIdle ; /** * Maximum number of connections that can be allocated by the pool at a given * time. Use a negative value for no limit. */private int = 8 maxActive ; /** * Maximum amount of time a connection allocation should block before throwing an * exception when the pool is exhausted. Use a negative value to block * indefinitely. */private Duration = Duration maxWait . ofMillis(-1);/** * Time between runs of the idle object evictor thread. When positive, the idle * object evictor thread starts, otherwise no idle object eviction is performed. */private Duration ; public timeBetweenEvictionRunsint getMaxIdle ( )returnthis { . ;}maxIdlepublic void setMaxIdle ( int)this maxIdle. { =;maxIdle } maxIdlepublic int getMinIdle ( )returnthis { . ;}minIdlepublic void setMinIdle ( int)this minIdle. { =;minIdle } minIdlepublic int getMaxActive ( )returnthis { . ;}maxActivepublic void setMaxActive ( int)this maxActive. { =;maxActive } maxActivepublic Duration getMaxWait ( )returnthis { . ;}maxWaitpublic void setMaxWait ( Duration)this maxWait. { =;maxWait } maxWaitpublic Duration getTimeBetweenEvictionRuns ( )returnthis { . ;}timeBetweenEvictionRunspublic void setTimeBetweenEvictionRuns ( Duration)this timeBetweenEvictionRuns. { =;timeBetweenEvictionRuns } timeBetweenEvictionRuns} /** * Cluster properties. */ public static class Cluster /** * Comma-separated list of "host:port" pairs to bootstrap from. This represents an * "initial" list of cluster nodes and is required to have at least one entry. */ private { List < String;/** * Maximum number of redirects to follow when executing commands across the * cluster. */> nodesprivate Integer ; public maxRedirectsList < StringgetNodes(> )returnthis { . ;}nodespublic void setNodes ( List<String)this> nodes. { =;nodes } nodespublic Integer getMaxRedirects ( )returnthis { . ;}maxRedirectspublic void setMaxRedirects ( Integer)this maxRedirects. { =;maxRedirects } maxRedirects} /** * Redis sentinel properties. */ public static class Sentinel /** * Name of the Redis server. */ private { String ; /** * Comma-separated list of "host:port" pairs. */ masterprivate List < String;/** * Password for authenticating with sentinel(s). */> nodesprivate String ; public passwordString getMaster ( )returnthis { . ;}masterpublic void setMaster ( String)this master. { =;master } masterpublic List < StringgetNodes(> )returnthis { . ;}nodespublic void setNodes ( List<String)this> nodes. { =;nodes } nodespublic String getPassword ( )returnthis { . ;}passwordpublic void setPassword ( String)this password. { =;password } password} /** * Jedis client properties. */ public static class Jedis /** * Jedis pool configuration. */ private { Pool ; public poolPool getPool ( )returnthis { . ;}poolpublic void setPool ( Pool)this pool. { =;pool } pool} /** * Lettuce client properties. */ public static class Lettuce /** * Shutdown timeout. */ private { Duration = Duration shutdownTimeout . ofMillis(100);/** * Lettuce pool configuration. */private Pool ; private poolfinal Cluster = new cluster Cluster ( );publicDuration getShutdownTimeout ( )returnthis { . ;}shutdownTimeoutpublic void setShutdownTimeout ( Duration)this shutdownTimeout. { =;shutdownTimeout } shutdownTimeoutpublic Pool getPool ( )returnthis { . ;}poolpublic void setPool ( Pool)this pool. { =;pool } poolpublic Cluster getCluster ( )returnthis { . ;}clusterpublic static class Cluster private final { Refresh = new refresh Refresh ( );publicRefresh getRefresh ( )returnthis { . ;}refreshpublic static class Refresh /** * Cluster topology refresh period. */ private { Duration ; /** * Whether adaptive topology refreshing using all available refresh * triggers should be used. */ periodprivate boolean ; public adaptiveDuration getPeriod ( )returnthis { . ;}periodpublic void setPeriod ( Duration)this period. { =;period } periodpublic boolean isAdaptive ( )returnthis { . ;}adaptivepublic void setAdaptive ( boolean)this adaptive. { =;adaptive } adaptive} } } } redis :
-
-
RedisProperties配置类获取的是从配置类中获取spring.redis 下的相关配置项
-
database: 4host : port: 192.168.10.143 6350password : lettuce: pool: max-idle: 8max-active : 8min-idle : 0max-wait : -1timeout : 12@Bean @ConditionalOnMissingBean
-
-
上一步为初始化JedisConnectionConfiguration及其相关的依赖配置类,接下去的步骤是初始化JedisConnectionFactory类 的bean,通过JedisConnectionConfiguration.createJedisConnectionFactory() 方法
-
( RedisConnectionFactory.class)JedisConnectionFactoryredisConnectionFactory ( ObjectProvider< JedisClientConfigurationBuilderCustomizer)throws> builderCustomizersUnknownHostException return createJedisConnectionFactory { ( );builderCustomizers}//创建JedisConnectionFactory private JedisConnectionFactory createJedisConnectionFactory ( ObjectProvider< JedisClientConfigurationBuilderCustomizer)//获取JedisClientConfigurationBuilder> builderCustomizersJedisClientConfiguration { = getJedisClientConfiguration clientConfiguration ( );builderCustomizersif( getSentinelConfig ()!=null ) returnnew { JedisConnectionFactory ( getSentinelConfig(),); clientConfiguration}if ( getClusterConfiguration ()!=null ) returnnew { JedisConnectionFactory ( getClusterConfiguration(),); clientConfiguration}return new JedisConnectionFactory ( getStandaloneConfig(),); clientConfiguration}//获取JedisClientConfigurationBuilder private JedisClientConfiguration getJedisClientConfiguration ( ObjectProvider< JedisClientConfigurationBuilderCustomizer)// org.springframework.data.redis.connection.jedis.JedisClientConfiguration.DefaultJedisClientConfigurationBuilder> builderCustomizers//关键步骤调用applyProperties 将redisProperties的timeout属性值 赋值给builder的readTimeout字段 { JedisClientConfigurationBuilder = applyProperties builder ( JedisClientConfiguration.builder());.= RedisPropertiesgetPropertiesPool pool ( ).getJedis().getPool();if( != nullpool ) applyPooling( { ,)pool; builder}if ( StringUtils .hasText(getProperties().getUrl()))customizeConfigurationFromUrl( { );builder}. orderedStream builderCustomizers().forEach(().customizercustomize -> customizer())builder;//Build the {@link JedisClientConfiguration} with the configuration applied from this builder. 这里要注意的是readTimeout的赋值return . build builder();}private JedisClientConfigurationBuilder applyProperties ( JedisClientConfigurationBuilder)if builder( { getProperties ().isSsl()).useSsl { builder();}//此处设置了redis readTimeout if ( getProperties ().getTimeout()!=null ) //获取的是RedisProperties的Timeout属性Duration { = getProperties timeout ( ).getTimeout();.readTimeout builder().timeoutconnectTimeout();timeout}if ( StringUtils .hasText(getProperties().getClientName())).clientName { builder(getProperties().getClientName());}return ; } builderclass DefaultJedisClientConfigurationBuilder implements JedisClientConfigurationBuilder , JedisPoolingClientConfigurationBuilder, JedisSslClientConfigurationBuilder//初始化默认为Protocol.DEFAULT_TIMEOUT public static final int DEFAULT_TIMEOUT = 2000; private { Duration = Duration readTimeout . ofMillis(Protocol.);DEFAULT_TIMEOUT/* * (non-Javadoc) * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration.JedisClientConfigurationBuilder#build() */@Override public JedisClientConfiguration build ( )returnnew { DefaultJedisClientConfiguration ( ,,useSsl, sslSocketFactory, sslParameters, hostnameVerifier, usePooling, poolConfig, clientName) readTimeout; connectTimeout}/* * (non-Javadoc) * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration.JedisClientConfigurationBuilder#readTimeout(java.time.Duration) */ @Override public JedisClientConfigurationBuilder readTimeout ( Duration)Assert readTimeout. { notNull(,"Duration must not be null!"readTimeout) ;this. =;readTimeout return readTimeoutthis ; }}- 初始化JedisConnectionFactory类 的bean
- 调用getJedisClientConfiguration()方法生成JedisClientConfigurationBuilder对象
-
-
此处可以获得到逻辑
- 生成JedisClientConfigurationBuilder对象后,调用applyProperties(JedisClientConfigurationBuilder builder)方法,将redisProperties的timeout属性值,赋值给JedisClientConfigurationBuilder 的ReadTimeout属性
- 总结:由此框架就定义了redis的readTimeout时间,至此在createJedisConnectionFactory()方法中的getJedisClientConfiguration()逻辑结束了。 privateJedisConnectionFactory
-
将生成的JedisClientConfiguration赋值给JedisConnectionFactory,最后返回JedisConnectionFactory
-
createJedisConnectionFactory ( ObjectProvider< JedisClientConfigurationBuilderCustomizer)JedisClientConfiguration> builderCustomizers= { getJedisClientConfiguration clientConfiguration ( );builderCustomizersif( getSentinelConfig ()!=null ) returnnew { JedisConnectionFactory ( getSentinelConfig(),); clientConfiguration}if ( getClusterConfiguration ()!=null ) returnnew { JedisConnectionFactory ( getClusterConfiguration(),); clientConfiguration}return new JedisConnectionFactory ( getStandaloneConfig(),); clientConfiguration}@Bean public
-
-
创建完JedisConnectionFactory类的Bean对象后,回到redisTemplate类的Bean创建方法中,通过setConnectionFactory() 给redisTemplate赋值redis工厂。最后,完成redisTemplate 类的Bean创建。
-
RedisTemplate < String,ObjectredisTemplate (> RedisConnectionFactory)RedisTemplate factory< { String,Object= new> template RedisTemplate < ()>;// 配置连接工厂. setConnectionFactory template();factory//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)Jackson2JsonRedisSerializer < Object=new> jacksonSerial Jackson2JsonRedisSerializer < (Object>.class);.setObjectMapper jacksonSerial();om// 值采用json序列化. setValueSerializer template();jacksonSerial//使用StringRedisSerializer来序列化和反序列化redis的key值. setKeySerializer template(newStringRedisSerializer( ));// 设置hash key 和value序列化模式. setHashKeySerializer template(newStringRedisSerializer( ));.setHashValueSerializer template();jacksonSerial.afterPropertiesSet template();return; } template. opsForValue
-
-
接下去是调用流程
-
redisTemplate().get();keypublicclass -
RedisTemplate < K,Vextends RedisAccessor> implements RedisOperations < K,V, BeanClassLoaderAware>AbstractOperations ( { RedisTemplate<K,V) this> template. { =;template } templateDefaultValueOperations ( RedisTemplate<K,V) super> template( { );template}private final ValueOperations < K,V= new> valueOps DefaultValueOperations < (this>);/* * (non-Javadoc) * @see org.springframework.data.redis.core.RedisOperations#opsForValue() */@Override public ValueOperations < K,VopsForValue (> )return; { } valueOps@Nullable public < T Texecute> ( RedisCallback<T,boolean> action) return exposeConnectionexecute { ( ,,actionfalse exposeConnection) ;}@Nullable public < T Texecute> ( RedisCallback<T,boolean> action, boolean exposeConnection) Assert pipeline. { isTrue(,"template not initialized; call afterPropertiesSet() before using it"initialized) ;Assert. notNull(,"Callback object must not be null"action) ;RedisConnectionFactory= getRequiredConnectionFactory factory ( );RedisConnection= null conn ; tryif ( { ) // only bind resources in case of potential transaction synchronizationenableTransactionSupport= { RedisConnectionUtils conn . bindConnection(,)factory; enableTransactionSupport}else = RedisConnectionUtils { conn . getConnection();factory}boolean = TransactionSynchronizationManager existingConnection . hasResource();factoryRedisConnection= preProcessConnection connToUse ( ,)conn; existingConnectionboolean= . pipelineStatus isPipelined connToUse();if( && !pipeline ) .pipelineStatusopenPipeline { connToUse();}RedisConnection = ( connToExpose ? :exposeConnection createRedisConnectionProxy connToUse ( ))connToUse;T= . result doInRedis action();connToExpose// close pipelineif ( && !pipeline ) .pipelineStatusclosePipeline { connToUse();}// TODO: any other connection processing? return postProcessResult ( ,,result) connToUse; existingConnection}finally RedisConnectionUtils . { releaseConnection(,,conn) factory; enableTransactionSupport}} } class DefaultValueOperations -
< K,Vextends AbstractOperations> < K,Vimplements ValueOperations> < K,VDefaultValueOperations (> { RedisTemplate<K,V) super> template( { );template}@Nullable < T Texecute> ( RedisCallback<T,boolean> callback) return exposeConnection. { execute template(,)callback; exposeConnection}/* * redis get 命令 */ @Override public V get ( Object)return keyexecute { ( newValueDeserializingRedisCallback( )@Overridekeyprotected { byte [ ]inRedis( byte[],RedisConnection rawKey) return connection. { get connection();rawKey}} , true) ;}} public abstract -
class RedisConnectionUtils public static { RedisConnection getConnection ( RedisConnectionFactory)return factorygetConnection { ( ,falsefactory) ;}public static RedisConnection getConnection ( RedisConnectionFactory,boolean factory) return transactionSupportdoGetConnection { ( ,truefactory, false, ); transactionSupport}public static RedisConnection doGetConnection ( RedisConnectionFactory,boolean factory, boolean allowCreate, boolean bind) Assert transactionSupport. { notNull(,"No RedisConnectionFactory specified"factory) ;RedisConnectionHolder= ( connHolder RedisConnectionHolder )TransactionSynchronizationManager. getResource();factoryif( != nullconnHolder ) if( { ) potentiallyRegisterTransactionSynchronisationtransactionSupport( { ,)connHolder; factory}return . getConnection connHolder();}if ( ! )throwallowCreatenew { IllegalArgumentException ( "No connection found and allowCreate = false");}if ( . isDebugEnabledlog()).debug { log("Opening RedisConnection");}//获取 RedisConnection RedisConnection = . conn getConnection factory();if( ) RedisConnectionbind= { ; connectionToBind if conn( && isActualNonReadonlyTransactionActivetransactionSupport ( ))=createConnectionProxy { connectionToBind ( ,)conn; factory}= new connHolder RedisConnectionHolder ( );connectionToBindTransactionSynchronizationManager. bindResource(,)factory; connHolderif( ) potentiallyRegisterTransactionSynchronisationtransactionSupport( { ,)connHolder; factory}return . getConnection connHolder();}return ; } conn} public class -
JedisConnectionFactory implements InitializingBean , DisposableBean, RedisConnectionFactory/* * (non-Javadoc) * @see org.springframework.data.redis.connection.RedisConnectionFactory#getConnection() */ public { RedisConnection getConnection ( )if( { isRedisClusterAware ())returngetClusterConnection { ( );}//获取redis 连接 Jedis = fetchJedisConnector jedis ( );JedisConnection= ( connection getUsePool ()?new JedisConnection ( ,,jedisgetDatabase pool( ),getClientName( )):new JedisConnection ( ,nulljedis, getDatabase( ),getClientName( )));.setConvertPipelineAndTxResults connection();convertPipelineAndTxResultsreturnpostProcessConnection ( );connection}protected Jedis fetchJedisConnector ( )tryif { ( { getUsePool ()&&!= null pool ) return. { getResource pool();}Jedis = createJedis jedis ( );//强制初始化,这里会获取连接// force initialization (see Jedis issue #82) . connect jedis();potentiallySetClientName( );jedisreturn; } jediscatch ( Exception )throw exnew { RedisConnectionFailureException ( "Cannot get Jedis connection",); ex}} } public class -
BinaryJedis implements BasicCommands , BinaryJedisCommands, MultiKeyBinaryCommands, AdvancedBinaryJedisCommands, BinaryScriptingCommands, Closeablepublic void { connect ( ).connect { client();}public class BinaryClient extends Connection @Override public { void connect ( )if( { ! isConnected())super. { connect();if( != nulluser ) auth( { ,)user; passwordgetStatusCodeReply( );}else if ( != nullpassword ) auth( { );passwordgetStatusCodeReply( );}if ( 0 )db > select( { );dbgetStatusCodeReply( );}} } } } public class -
Connection implements Closeable public String { getStatusCodeReply ( )flush( { );finalbyte [ ]=( resp byte [])readProtocolWithCheckingBroken( );if( null ==) return respnull { ; }else return SafeEncoder { . encode();resp}} protected Object readProtocolWithCheckingBroken ( )if( { ) throwbrokennew { JedisConnectionException ( "Attempting to read from a broken connection");}try return Protocol { . read();inputStream}catch ( JedisConnectionException )= exctrue { broken ; throw; } exc} } public final -
class Protocol public static { Object read ( finalRedisInputStream) return isprocess { ( );is}private static Object process ( finalRedisInputStream) final isbyte { = . b readByte is();switch( ) caseb: { return PLUS_BYTEprocessStatusCodeReply ( );iscase: return DOLLAR_BYTEprocessBulkReply ( );iscase: return ASTERISK_BYTEprocessMultiBulkReply ( );iscase: return COLON_BYTEprocessInteger ( );iscase: processError MINUS_BYTE( );isreturnnull ; default: thrownew JedisConnectionException ( "Unknown reply: "+( char )); b}} } public class RedisInputStream extends FilterInputStream public byte { readByte ( )throwsJedisConnectionException ensureFill ( { );return[ ++ buf]count;}private void ensureFill ( )throwsJedisConnectionException if ( { ) trycount >= limit= { . { limit read in();buf=0 count ; if( == -limit 1 )thrownew { JedisConnectionException ( "Unexpected end of stream.");}} catch ( IOException )throw enew { JedisConnectionException ( );e}} } }
-
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)