💻문제점1
잘못된 streamkey를 입력해도 유효하다고 log가 찍힌다.
@NoArgsConstructor
@Getter
@Setter
@Slf4j
public abstract class RtmpServer implements CommandLineRunner {
//생략
@Override
public void run(String... args) {
DisposableServer server = TcpServer.create()
// .host("0.0.0.0")
.port(1935)
.doOnBound(disposableServer ->
log.info("RTMP 서버가 포트 {} 에서 시작됩니다.", disposableServer.port()))
.doOnConnection(connection -> connection
.addHandlerLast(getInboundConnectionLogger())
.addHandlerLast(getHandshakeHandler())
.addHandlerLast(getChunkDecoder())
.addHandlerLast(getChunkEncoder())
.addHandlerLast(getRtmpMessageHandler()))
.option(ChannelOption.SO_BACKLOG, 128) // 클라이언트가 새로운 연결을 요청할 때 대기하는 큐 크기를 128로 설정
.childOption(ChannelOption.SO_KEEPALIVE, true) // 특정 시간동안 클라이언트의 요청이 없어도 서버-클라이언트 연결이 끊기지 않도록 설정
.handle((in, out) -> in
.receiveObject()
.cast(Stream.class)
.flatMap(stream ->
{
webClient
.post()
.uri(authAddress + "/broadcasts/{}/check", stream.getStreamName())
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.body(Mono.just(new User(stream.getStreamKey())), User.class)
.retrieve()
.bodyToMono(Boolean.class).log()
.retryWhen(Retry.fixedDelay(3, Duration.ofMillis(500)))
.doOnError(error -> log.info(error.getMessage()))
.onErrorReturn(Boolean.TRUE)
.flatMap(ans -> {
log.info("스트리머 {} 의 stream key가 유효합니다.", stream.getStreamName());
if (ans) {
//생략
.then())
.bindNow();
server.onDispose().block();
}
}
OBS에서 testNickname이라는 닉네임을 가지는 사용자의 streamKey를 설정하고
방송을 시작하면 다음과 같이 연결할 수 없다고 떴다.
콘솔 창에는 다음과 같은 오류가 떴다.
🔍문제점1 해결
오류에서 POST요청을 한 경로를 보면 이상한 것을 확인할 수 있다. %7B 어쩌구로 깨진 곳에는 OBS에서 설정한 사용자 닉네임, testNickname이 들어가야 한다.
요청 uri가 깨져서 제대로 요청이 안 가는 것일 수도 있겠다는 생각이 들어 이 문제 부터 수정했다.
요청 부분을 다음과 같이 수정했다.
.uri(authAddress + "/broadcasts/" + stream.getStreamName() + "/check")
그랬더니 깨지지 않고 올바른 경로로 요청이 수행된 것을 확인할 수 있었다.
하지만 여전히 연결은 안된다..
그리고 깨달았다..! 이 요청은 POST 요청이고 현재 그 요청을 받는 API는 GET 이다...
그래서 GetMapping이 아니라 PostMapping으로 변경해주었다.
@PostMapping("/{streamer}/check")
public Mono<Boolean> checkStreamer(@PathVariable("streamer") String streamer, @RequestBody StreamerCheckRequestDto streamerCheckRequestDto) {
log.info("channelController: " + streamer);
return channelService.checkBroadcast(streamer, streamerCheckRequestDto);
}
방송 시작을 해보니 무사히 시작되었다.
TranscofingService에서도 정상적으로 testNickname 유저 방송에 대해 파일을 생성하는 것을 확인할 수 있었다.
💻문제점2
방송이 시작되면, DB에서 해당 유저의 방송 상태가 true로 변경되어야 한다. 하지만 변경되지 않았다.
ChannelController에서 로그를 찍어보니 해당 요청인 startBroadcast 메서드에 잘 진입하는 것을 확인할 수 있었다.
Postman으로 확인해보니 true라는 결과는 출력하지만 DB에 변경사항이 적용이 안됐다.
public Mono<Boolean> startBroadcast(String streamer) {
return channelRepository
.findByStreamer(streamer)
.switchIfEmpty(Mono.error(new RuntimeException("존재하지 않는 채널입니다.")))
.map(channel -> {
return channelRepository.save(channel.channelOn());
})
.flatMap(channel -> {
return Mono.just(true);
});
}
코드가 수정되고 아직 해당 부분에 테스트 케이스를 안 짰더니 ㅠㅠ
🔍문제점2 해결
다음과 같이 코드를 변경했다.
public Mono<Boolean> startBroadcast(String streamer) {
return channelRepository
.findByStreamer(streamer)
.switchIfEmpty(Mono.error(new RuntimeException("존재하지 않는 채널입니다.")))
.flatMap(channel -> {
return channelRepository.save(channel.channelOn())
.thenReturn(true);
});
}
이전 코드에서는 save 메서드를 호출하지만, 그에 대한 결과를 처리하지 않았다.
리액티브 프로그래밍은 호출 시점과 실제 작업 수행 시점을 구분하기 때문에 단순히 호출만 하여서 DB에 반영되지 않은 것이다. save를 호출한 후 해당 Mono 객체에 대한 처리를 thenReturn(true)를 통해 해주었다.
방송을 시작하니 DB에 해당 채널의 on_air가 true로 변경되었다.
'TIL' 카테고리의 다른 글
[TIL - 20230615] EC2 + Docker Compose 통한 배포 (0) | 2023.06.16 |
---|---|
[TIL - 20230614] docker compose (0) | 2023.06.15 |
[TIL - 20230608] Webflux + Websocket + Kafka (0) | 2023.06.08 |
[TIL - 20230606] Webflux + Websocket 전체 채팅 (0) | 2023.06.07 |
[TIL - 20230605] RSocketRequester Redis 저장 실패 (0) | 2023.06.05 |