java 测试容器的JedisconnectionException:无法从Gitlab管道上的池”“中获取资源

pzfprimi  于 2023-01-29  发布在  Java
关注(0)|答案(1)|浏览(135)

我使用Testcontainers进行Redis集群集成测试;虽然本地的一切工作正常,但在创建了一个远程分支并将代码推送到Gitlab pipeline后,我得到了下面的异常。我有Cassandra和PostgreSQL,它们都工作正常,但对于Redis,我得到了下面的异常。

    • 更新:之前使用fixedExposePort时,测试在本地运行,但现在删除fixedExposePort**后,即使在本地,我也会收到相同的错误。
Caused by: redis.clients.jedis.exceptions.JedisClusterMaxAttemptsException: No more cluster attempts left.
        at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:156)
        at redis.clients.jedis.JedisClusterCommand.runBinary(JedisClusterCommand.java:69)
        at redis.clients.jedis.BinaryJedisCluster.setex(BinaryJedisCluster.java:496)
        at redis.clients.jedis.commands.BinaryJedisClusterCommands.setex(BinaryJedisClusterCommands.java:74)
        at org.springframework.data.redis.connection.jedis.JedisClusterStringCommands.setEx(JedisClusterStringCommands.java:175)
        ... 39 common frames omitted
        Suppressed: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
            at redis.clients.jedis.util.Pool.getResource(Pool.java:84)
            at redis.clients.jedis.JedisPool.getResource(JedisPool.java:366)
            at redis.clients.jedis.JedisSlotBasedConnectionHandler.getConnectionFromSlot(JedisSlotBasedConnectionHandler.java:129)
            at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:118)
            ... 43 common frames omitted
        Caused by: redis.clients.jedis.exceptions.JedisConnectionException: Failed to create socket.
            at redis.clients.jedis.DefaultJedisSocketFactory.createSocket(DefaultJedisSocketFactory.java:110)
            at redis.clients.jedis.Connection.connect(Connection.java:226)
            at redis.clients.jedis.BinaryClient.connect(BinaryClient.java:135)
            at redis.clients.jedis.BinaryJedis.connect(BinaryJedis.java:309)
            at redis.clients.jedis.BinaryJedis.initializeFromClientConfig(BinaryJedis.java:87)
            at redis.clients.jedis.BinaryJedis.<init>(BinaryJedis.java:292)
            at redis.clients.jedis.Jedis.<init>(Jedis.java:167)
            at redis.clients.jedis.JedisFactory.makeObject(JedisFactory.java:177)
            at org.apache.commons.pool2.impl.GenericObjectPool.create(GenericObjectPool.java:889)
            at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:424)
            at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:349)
            at redis.clients.jedis.util.Pool.getResource(Pool.java:75)
            ... 46 common frames omitted
        Caused by: java.net.ConnectException: Connection refused (Connection refused)
            at java.base/java.net.PlainSocketImpl.socketConnect(Native Method)
            at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412)
            at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255)
            at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237)
            at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
            at java.base/java.net.Socket.connect(Socket.java:609)
            at redis.clients.jedis.DefaultJedisSocketFactory.createSocket(DefaultJedisSocketFactory.java:80)
            ... 57 common frames omitted
    • 这是测试容器配置。**
public class RedisClusterContainer extends GenericContainer<RedisClusterContainer> {

    public RedisClusterContainer() {
        super("grokzen/redis-cluster:6.2.8");
        withEnv("IP", "0.0.0.0");
        addExposedPorts(7000, 7001, 7002, 7003, 7004, 7005);
    }

    public String getNodeAddress() {
        return Stream.of(7000, 7001, 7002, 7003, 7004, 7005)
                .map(port -> {
                    Integer mappedPort = getMappedPort(port);
                    return getHost() + ":" + mappedPort;
                })
                .collect(Collectors.joining(","));
    }
}

我现在已经添加了两个测试,它们以不同的方式创建容器,而不使用FixedExposedPort,但是它们都不起作用。
一个一个二个一个一个一个三个一个一个一个一个一个四个一个

    • 这是群集的连接工厂配置。**
@Slf4j
@Configuration
public class JedisConfiguration {
    @Value("${spring.redis.cluster.nodes}")
    private String redisClusterNodes;

    @Value("${spring.redis.client-name:redis}")
    private String clientName;

    @Bean
    @Primary
    RedisConnectionFactory connectionFactory() {
        log.info("Cluster nodes: {}", redisClusterNodes);
        List<String> nodes = Arrays.stream(redisClusterNodes.split(",")).collect(toList());
        RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration(nodes);
        JedisClientConfiguration clientConfig = JedisClientConfiguration.builder().clientName(clientName).usePooling().build();
        return new JedisConnectionFactory(clusterConfig, clientConfig);
    }

    @Bean
    RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        return new StringRedisTemplate(factory);
    }
}
    • 在管道日志中,我可以看到容器已启动。**
2022-12-15 14:14:19.804  INFO 87 --- [    Test worker] i.c.testenv.RedisContainerExtension      : Starting Redis container
    2022-12-15 14:14:19.814  INFO 87 --- [    Test worker] 🐳 [grokzen/redis-cluster:5.0.7]         : Pulling docker image: grokzen/redis-cluster:5.0.7. Please be patient; this may take some time but only needs to be done once.
    2022-12-15 14:14:20.170  INFO 87 --- [ream-2042455873] 🐳 [grokzen/redis-cluster:5.0.7]         : Starting to pull image

................

2022-12-15 14:14:35.997  INFO 87 --- [    Test worker] 🐳 [grokzen/redis-cluster:5.0.7]         : Creating container for image: grokzen/redis-cluster:5.0.7
    2022-12-15 14:14:35.999  INFO 87 --- [ream-2042455873] 🐳 [grokzen/redis-cluster:5.0.7]         : Pull complete. 17 layers, pulled in 15s (downloaded 176 MB at 11 MB/s)
    2022-12-15 14:14:36.335  INFO 87 --- [    Test worker] 🐳 [grokzen/redis-cluster:5.0.7]         : Container grokzen/redis-cluster:5.0.7 is starting: 47534017152ee0a974cf65d2030fbbab592da976a2d258613e5c27ad4b5b71e9
    2022-12-15 14:14:39.206  INFO 87 --- [    Test worker] 🐳 [grokzen/redis-cluster:5.0.7]         : Container grokzen/redis-cluster:5.0.7 started in PT19.39715S

即使启动了容器,并且getHost()返回docker作为主机,但我仍然收到上面的异常,有人知道我做错了什么吗?

yzuktlbb

yzuktlbb1#

下面是基于this github project的示例
本示例是使用www.example.com创建start.spring.io
技巧是在Config类中,spring.data.redis.cluster.nodes属性设置为主机端口和随机端口,但是客户端尝试解析随机端口和原始端口,因此定制器将帮助将原始端口重定向到随机端口。

@Testcontainers
@SpringBootTest
class SpringBootRedisApplicationTests {

    @Container
    private static final RedisClusterContainer redisCluster = new RedisClusterContainer();

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @DynamicPropertySource
    static void properties(DynamicPropertyRegistry registry) {
        registry.add("spring.data.redis.cluster.nodes", redisCluster::getNodeAddress);
    }

    @Test
    void contextLoads() {
        this.redisTemplate.opsForValue().set("redisKey", "redisValue");
        String result = redisTemplate.opsForValue().get("redisKey");
        assertThat(result).isEqualTo("redisValue");
    }

    static class RedisClusterContainer extends GenericContainer<RedisClusterContainer> {

        public RedisClusterContainer() {
            super("grokzen/redis-cluster:6.2.8");
            withEnv("IP", "0.0.0.0");
            addExposedPorts(7000, 7001, 7002, 7003, 7004, 7005);
            waitStrategy = Wait.forLogMessage(".*Cluster state changed: ok*\\n", 6);
        }

        public String getNodeAddress() {
            return Stream.of(7000, 7001, 7002, 7003, 7004, 7005)
                    .map(port -> {
                        Integer mappedPort = getMappedPort(port);
                        return getHost() + ":" + mappedPort;
                    })
                    .collect(Collectors.joining(","));
        }

        public Map<Integer, Integer > ports() {
            return Map.of(7000, getMappedPort(7000),
                    7001, getMappedPort(7001),
                    7002, getMappedPort(7002),
                    7003, getMappedPort(7003),
                    7004, getMappedPort(7004),
                    7005, getMappedPort(7005));
        }

    }

    @TestConfiguration
    static class Config {

        @Bean
        ClientResourcesBuilderCustomizer customizer() {
            return builder -> {
                Function<HostAndPort, HostAndPort> mappingFn = hostAndPort -> {
                    if (redisCluster.ports().containsKey(hostAndPort.getPort())) {
                        Integer mappedPort = redisCluster.ports().get(hostAndPort.getPort());
                        return HostAndPort.of(hostAndPort.getHostText(), mappedPort);
                    }
                    return hostAndPort;
                };
                builder.socketAddressResolver(MappingSocketAddressResolver.create(mappingFn));
            };
        }

    }

}

相关问题