首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Spring生菜连接问题

Spring生菜连接问题
EN

Stack Overflow用户
提问于 2020-05-21 18:32:34
回答 1查看 4.4K关注 0票数 4

我使用MYSQL DB进行了spring引导应用程序,我正在使用@Cacheable注释在服务器层中缓存Redis中的数据。

代码语言:javascript
运行
复制
@Cacheable(value= "employeeCache", key= "#customerId")
@Override
public Customer getEmployee(String customerId) {
    Optional<Customer> cust = customerRepository.findById(Long.parseLong(customerId));
    if(cust.isPresent()) {
        return cust.get();
    }
    return null;
}

我使用的是1个主2从节点和2个哨兵节点,我已经将应用程序部署在码头容器中,在AWS ec2 ubuntu实例中。

应用程序和Redis主/从设置工作很好。

当Redis主容器崩溃时,其中一个奴隶变成主人,这也很好。

但是,一旦其中一个从机成为主从,那么Spring引导就无法连接到Redis,我将获得连接超时,只有重新启动容器才能工作。

请检查配置中是否有错误。

Java日志

代码语言:javascript
运行
复制
2020-05-21 18:04:50.016 ERROR 1 --- [io-8080-exec-10] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.QueryTimeoutException: Redis command timed out; nested exception is io.lettuce.core.RedisCommandTimeoutException: io.lettuce.core.RedisCommandTimeoutException: Command timed out after 1 minute(s)] with root cause

io.lettuce.core.RedisCommandTimeoutException: Command timed out after 1 minute(s)
        at io.lettuce.core.ExceptionFactory.createTimeoutException(ExceptionFactory.java:51) ~[lettuce-core-5.3.0.RELEASE.jar!/:5.3.0.RELEASE]
        at io.lettuce.core.protocol.CommandExpiryWriter.lambda$potentiallyExpire$0(CommandExpiryWriter.java:167) ~[lettuce-core-5.3.0.RELEASE.jar!/:5.3.0.RELEASE]
        at io.netty.util.concurrent.PromiseTask.runTask(PromiseTask.java:98) ~[netty-common-4.1.49.Final.jar!/:4.1.49.Final]
        at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:170) ~[netty-common-4.1.49.Final.jar!/:4.1.49.Final]
        at io.netty.util.concurrent.DefaultEventExecutor.run(DefaultEventExecutor.java:66) ~[netty-common-4.1.49.Final.jar!/:4.1.49.Final]
        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.49.Final.jar!/:4.1.49.Final]
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.49.Final.jar!/:4.1.49.Final]
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.49.Final.jar!/:4.1.49.Final]
        at java.lang.Thread.run(Thread.java:745) [na:1.8.0_111]

春季启动文件

application.yaml

代码语言:javascript
运行
复制
spring:
  datasource:
    url: jdbc:mysql://docker-mysql:3306/customerdb
    username: root
    password: root

  jpa:
    show-sql: true

    hibernate:
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl


  cache:
    type: redis  

  redis:
    sentinel:
      master: mymaster
      nodes:
        - redis-sentinel:26379
        - redis-sentinel-1:26380

management:
  endpoints:
    web: 
      exposure:
        include:
        - "*"
server:
  port: 8080

logging:
  file:
    name: customer.log
    path: ../logs

用于Redis和Spring部署的文件

Docker-compose.yaml

代码语言:javascript
运行
复制
version: '3.5'

services:

  redis-master:
    container_name: redis-master
    image: redis
    volumes:
      - "./data/redis-master:/data"
    networks:
      - backend

  redis-slave:
    container_name: redis-slave
    image: redis
    command: redis-server --slaveof redis-master 6379
    volumes:
      - "./data/redis-slave:/data"
    depends_on:
      - redis-master
    networks:
      - backend

  redis-slave-1:
    container_name: redis-slave-1
    image: redis
    command: redis-server --slaveof redis-master 6379
    volumes:
      - "./data/redis-slave:/data"
    depends_on:
      - redis-master
    networks:
      - backend    

  redis-sentinel:
    container_name: redis-sentinel
    ports:
      - "26379:26379"
    build: redis-sentinel
    depends_on:
      - redis-master
      - redis-slave
    networks:
      - backend

  redis-sentinel-1:
    container_name: redis-sentinel-1
    build: redis-sentinel
    ports:
      - "26380:26379"
    depends_on:
      - redis-master
      - redis-slave
    networks:
      - backend

  docker-mysql:
    restart: always
    container_name: docker-mysql
    image: mysql:5.7
    environment:
      MYSQL_DATABASE: customerdb
      MYSQL_ROOT_PASSWORD: root
      MYSQL_ROOT_HOST: "%"
    volumes:
      - db-data-new:/var/lib/mysql
    ports:
      - "3306:3306"
    networks:
      - backend

  customer-app:
    container_name: java-sentinel
    restart: on-failure
    image: kuldeep99/customer-sentinel:v10
    expose:
      - "8080"
    volumes:
      - /tmp:/logs
    ports:
      - 8080:8080
    depends_on:
      - docker-mysql
      - redis-master
      - redis-slave
      - redis-sentinel
    networks:
      - backend

volumes:
  db-data-new:

networks:
  backend:

Dockerfile

代码语言:javascript
运行
复制
FROM redis

EXPOSE 26379
ENV SENTINEL_QUORUM 2
ENV SENTINEL_DOWN_AFTER 3000
ENV SENTINEL_FAILOVER 3000
ADD sentinel.conf /etc/redis/sentinel.conf
RUN chown redis:redis /etc/redis/sentinel.conf
ADD sentinel-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/sentinel-entrypoint.sh
ENTRYPOINT ["sentinel-entrypoint.sh"]

sentinel-entrypoint.sh

代码语言:javascript
运行
复制
#!/bin/sh

sed -i "s/\$SENTINEL_QUORUM/$SENTINEL_QUORUM/g" /etc/redis/sentinel.conf
sed -i "s/\$SENTINEL_DOWN_AFTER/$SENTINEL_DOWN_AFTER/g" /etc/redis/sentinel.conf
sed -i "s/\$SENTINEL_FAILOVER/$SENTINEL_FAILOVER/g" /etc/redis/sentinel.conf

redis-server /etc/redis/sentinel.conf --sentinel

sentinel.conf

代码语言:javascript
运行
复制
port 26379
protected-mode no
dir /tmp
sentinel monitor mymaster redis-master 6379 $SENTINEL_QUORUM
sentinel down-after-milliseconds mymaster $SENTINEL_DOWN_AFTER
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster $SENTINEL_FAILOVER
EN

回答 1

Stack Overflow用户

发布于 2022-03-23 08:58:53

我认为您没有设置拓扑刷新配置。你可以让他们像这样-

解决方案1

升级到SpringBoot 2.3.0或更高版本。并添加以下配置项

代码语言:javascript
运行
复制
spring.redis.timeout=60s
spring.redis.lettuce.cluster.refresh.period=60s
spring.redis.lettuce.cluster.refresh.adaptive=true

解决方案2

配置LettuceConnectionFactory并设置拓扑刷新策略。

代码语言:javascript
运行
复制
@Bean
public DefaultClientResources lettuceClientResources() {
    
    
    return DefaultClientResources.create();
}

@Bean
public LettuceConnectionFactory lettuceConnectionFactory(RedisProperties redisProperties, ClientResources clientResources) {
    
    

    ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
            .enablePeriodicRefresh(Duration.ofSeconds(30)) //按照周期刷新拓扑
            .enableAllAdaptiveRefreshTriggers() //根据事件刷新拓扑
            .build();

    ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder()
            //redis命令超时时间,超时后才会使用新的拓扑信息重新建立连接
            .timeoutOptions(TimeoutOptions.enabled(Duration.ofSeconds(10)))
            .topologyRefreshOptions(topologyRefreshOptions)
            .build();

    LettuceClientConfiguration clientConfiguration = LettuceClientConfiguration.builder()
            .clientResources(clientResources)
            .clientOptions(clusterClientOptions)
            .build();

    RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration(redisProperties.getCluster().getNodes());
    clusterConfig.setMaxRedirects(redisProperties.getCluster().getMaxRedirects());
    clusterConfig.setPassword(RedisPassword.of(redisProperties.getPassword()));

    LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(clusterConfig, clientConfiguration);

    return lettuceConnectionFactory;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61941396

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档