티스토리 뷰

SpringBoot에서 통합테스트를 만들 때 kstyrc의 Embedded redis가 실행되지않는 문제가 있었다.

 

Caused by: java.lang.RuntimeException: Can't start redis server. Check logs for details.

 

 

로그를 확인 하라는데 어디서 확인할 수 있는지 알 수가 없다.

그래서 라이브러리 코드를 디버깅 해 찾아보니 아래 부분에서 에러가 발생한다.

private void awaitRedisServerReady() throws IOException {
    BufferedReader reader = new BufferedReader(new InputStreamReader(redisProcess.getInputStream()));
    try {
        String outputLine;
        do {
            outputLine = reader.readLine();
            if (outputLine == null) {
                //Something goes wrong. Stream is ended before server was activated.
                throw new RuntimeException("Can't start redis server. Check logs for details.");
            }
        } while (!outputLine.matches(redisReadyPattern()));
    } finally {
        IOUtils.closeQuietly(reader);
    }
}

 

 

레디스 프로세스를 띄우고 stdout 을 받아서 실행되었는지 확인하는 듯 하다.

디버거로 reader 의 값을 받아보면

=== REDIS BUG REPORT START: Cut & paste starting from here ===
[8366] 14 Jan 18:14:28.233 #     Redis 2.8.19 crashed by signal: 10

...

os:Darwin 20.2.0 x86_64

...

 

 

임베디드 redis 라이브러리에서 mac_arm64 용 바이너리가 준비되지 않은 것이 원인인 것을 알 수 있다.

라이브러리의 소스코드에도 MAC_OS_X_arm64 가 없는 것을 알 수 있다.

라이브러리를 수정해 사용할 수도 있겠지만, 문서에서는 사용자가 바이너리를 지정해 사용하는 방법을 제시하고 있다.

https://github.com/kstyrc/embedded-redis/blob/master/src/main/java/redis/embedded/RedisExecProvider.java
private void initExecutables() {
    executables.put(OsArchitecture.WINDOWS_x86, "redis-server-2.8.19.exe");
    executables.put(OsArchitecture.WINDOWS_x86_64, "redis-server-2.8.19.exe");

    executables.put(OsArchitecture.UNIX_x86, "redis-server-2.8.19-32");
    executables.put(OsArchitecture.UNIX_x86_64, "redis-server-2.8.19");

    executables.put(OsArchitecture.MAC_OS_X_x86, "redis-server-2.8.19.app");
    executables.put(OsArchitecture.MAC_OS_X_x86_64, "redis-server-2.8.19.app");
}

 

 

찾아보니 redis 사이트에서 직접 바이너리를 다운받아 resource를 옮겨 실행시키면 됐었다.

M1 mac sequoia OS에서는 최신버전인 7.4.2 버전이 정상적으로 동작해서 해당 버전을 사용했다.

https://download.redis.io/releases/ 참고

$ wget https://download.redis.io/releases/redis-7.4.2.tar.gz
$ tar -xzf redis-6.0.10.tar.gz
$ cd redis-6.0.10
$ make
$ src/redis-server 

바이너리 실행 시 Embedded Redis가 실행된다.
정상적으로 동작하면 resource로 옮긴다. 

$ cp redis-server /Users/hi/git-project/reservation/src/test/resources/binary/redis

 

 

EmbeddedRedisConfig에서 ARM 아키텍처에서는 옮겨놓은 바이너리가 실행되도록 설정한다.

@Slf4j
@Profile("test")
@Configuration
public class EmbeddedRedisConfig {

    @Value("${spring.data.redis.port}")
    private int redisPort;

    private RedisServer redisServer;

    @PostConstruct
    public void redisServer() throws IOException {
        log.info("Embedded Redis Server start. isArmMac={}",isArmMac());

        if (isArmMac()) {
            redisServer = new RedisServer(getRedisFileForArcMac(), redisPort);
        } else {
            redisServer = RedisServer.builder()
                    .port(redisPort)
                    .build();
        }

        redisServer.start();
    }

    @PreDestroy
    public void stopRedis() {
        if (redisServer != null) {
            redisServer.stop();
        }
    }

    /**
     * 현재 시스템이 ARM 아키텍처를 사용하는 MAC인지 확인
     * System.getProperty("os.arch") : JVM이 실행되는 시스템 아키텍처 반환
     * System.getProperty("os.name") : 시스템 이름 반환
     */
    private boolean isArmMac() {
        String osArch = System.getProperty("os.arch").toLowerCase();
        String osName = System.getProperty("os.name").toLowerCase();
        log.info("osArch={}, osName={}", osArch,osName );
        return (osArch.equals("aarch64") || osArch.equals("arm64"))
                || osName.contains("mac");
    }

    /**
     * ARM 아키텍처를 사용하는 Mac에서 실행할 수 있는 Redis 바이너리 파일을 반환
     */
    private File getRedisFileForArcMac() {
        try {
            return new ClassPathResource("binary/redis/redis-server-7.4.2-mac-arm64").getFile();
        } catch (Exception e) {
            throw new RuntimeException("Redis File Error");
        }
    }
}