포스트

[.NET Orleans] Grain 1개당 Client 1개 연결 시도

[.NET Orleans] Grain 1개당 Client 1개 연결 시도

결론부터 말하면, Grain 안에 TcpClient 멤버 구현은 옳지 않습니다.
이번 포스트에서는 Grain 안에 소켓 통신 구현이 필요했던 이유와
구현 이후 발생했던 문제점과 개선 방향에 대해 말하려고 합니다.

Grain을 관리하는 것은 Orleans 프레임워크


Orleans 프레임워크에서 Grain은 이전 포스트에서 언급한 것처럼 1개의 액터를 담당하며
서로 다른 Grain과 통신할 수 있다는 특징이 있었습니다.

저는 Grain의 특징을 기반으로 서버에 접속한 유저 정보 관리와 함께
TcpClient 멤버를 넣어 각 Grain이 담당하는 클라이언트와 소통할 수 있도록 구현하고자 하였습니다.

그러나 이러한 구조에는 치명적인 문제점이 있었습니다.
Grain의 활성화, 비활성화는 Orleans 프레임워크에서 관리하기 때문에
클라이언트가 전송한 데이터를 Grain에서 수신 대기하던 중,
Orleans 프레임워크는 이 Grain을 비활성화 시킬 수 있습니다.
비활성화된 Grain은 클라이언트가 전송한 데이터를 수신하는데 실패해서 유저 정보는 갱신되지 않고
클라이언트는 요청한 정보를 수신받지 못하기 때문에 이는 정상 작동하는 프로그램이라고 할 수 없습니다.


실해예시

위 이미지는 Orleans Dashboard 창, Orleans에 접속한 2개의 클라이언트,
Orleans 서버의 출력 내용을 보여주는 사진입니다.

여기서 만약 모든 클라이언트가 채팅을 입력하지 않으면 Orleans 프레임워크는
각 Grain이 활성화 상태를 유지할 필요가 없다고 판단하여 비활성화 상태로 변경시킬 수 있습니다.
그리고 이후에 클라이언트에서 채팅을 입력하면 수신할 수 있는 소켓이 없기 때문에
클라이언트가 전송한 채팅은 그 누구도 수신받을 수 없습니다.


클라이언트-서버 구조에서 Orleans


위 과정에서 Grain이 직접 소켓 통신을 하는 것은 바람직하지 않다고 언급했습니다.
그러나 클라이언트-서버 구조에서 Orleans를 아예 활용할 수 없는 것은 아닙니다.
클라이언트가 전송하는 데이터는 Orleans가 아닌 프로세스에서 송수신한 뒤 이 내용을 Orleans에 전달하고
Orleans는 전달받은 내용을 기반으로 유저 정보를 저장하거나 특정 로직(길찾기, 유저 정보 정렬 등 게임 로직)을 수행하면 됩니다.

저는 실행 환경이 Ubuntu Linux server 22.04 LTS를 사용하고 있기 때문에
클라이언트들과 네트워크 통신은 EPoll을 사용하고 이 내용을 기존 Orleans 프로세스에 전달함으로서
클라이언트-서버 구조를 구현하고 있습니다.


이 포스트는 .NET Orleans를 배우면서 작성한 내용입니다. 오류나 틀린 부분이 있을 경우 언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다!

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.