Job Queue #1

CJB_ny·2022년 3월 5일
0

Unity_Server

목록 보기
48/55
post-thumbnail

이 잡큐는 컨텐츠 딴에서 만들어도되고

ServerCore == 라이브딴에서 만들어도 노상관이다.

ServerCore -> Job 생성

그다음에 이 Job이라는 개념을 어떻게 만들어 줄 것인가가 고민이다.

만드는 방법은 여러가지인데 오늘 보여줄 것은 크게 두가지

1) C#문법을 사용하여 만드는것

2) 수동적으로 만드는 것


이 Job이라는 개념을 따로 파도되지만

일반적으로 C#에서 "어떤 행위"자체를

Action으로 표현하는 경우가 많다.

delegate를 이용해가지고 나중에 처리할 것들을

이런식으로 Action으로 밀어넣어주는게 일반적인 상황이다.

그래서 결국 잡큐라는것은 내가 해야할 "행동" == "Action"을

그냥 Queue로 들고있는게 잡큐이다.

그래서 상속을 받아주고

밑에 Action을 뱉어주는 Push, Pop을 lock을 걸고 만들어 주도록 하자.


두번째 고민

그러면 누가 Pop을 해서 사용을 하것인가??

(이것은 조금있다가 보도록 하자)


먼저 어떻게 사용을 할지 보자.

일단 > GameRoom rr

현재

이렇게 상속을 받고

지금 GameRoom이 이 밑줄 세가지 기능을 지원하는데

여기에 바로 접근을 해서 일을 하는게 아니라

이 각각의 행동들을 _jobQueue에다가 밀어 넣어가지고

진행을 할 것이다.

이렇게 한다음에

BroadCast, Enter, Leave사용하던데 수정을 ㄱㄱ

그래서 먼저 PacketHandler ㄱㄱ >

지금 이부분을 실행을 할게 아니라

Action으로 넘겨주기를 해야 한다.

그래서 Action으로 넘겨주는 가장 간단한 방법인 람다로 이렇게 해야할 행동을 넘겨주도록 하자.

그래서 이렇게 19번째 줄처럼 바로 해야 할일을 하러가는게아니라

"해야 할 일감"을 던져줘서 이 행동은 "주문서"처럼

Queue에다가 차곡차곡 쌓여가지고

어느시점에 쌓여있는 녀석들을 순차적으로 실행하면 될 것이다.

그런데 지금 문제가 살짝 있는데

Room이 null로 바뀌면 문제가 될 수 있다.

나중에 고치고 놔두자.

그다음 ClientSession ㄱㄱ >

이렇게 "내가 이렇게 할 일을 주문서 작성을 할테니 시간이 될때 이 "행동"을 처리를 해줘!" 라고 Push를 한셈이다.

OnDisConnected부분도 똑같이 해주도록 하자.

나중에 크래쉬가 날 것인데

일단은 이런 인터페이스를 사용을 할 것이다 정도만 알고 있어라!


그래서 다시 GameRoom으로 돌아와보면

여기 일감들이 쌓여있는데

이 "일감"들을 누가 어떻게 처리를 할것인가?? (ㄴㄱ 실행?)

ㄴㄱ? ->

1) 메인쓰레드 or 다른 쓰레드 순차적으로 돌면서 처리

2) 조금더 간단한 ㅂㅂ

Push를 할 때 맨처음으로 일감을 밀어 넣은 애라면은

실제로 "실행"까지 담당

그게 아니라면 그냥 Queue에다가 Push만하고 빠져나오는 방법

이렇게 있는데 비슷한 것을 전에 구현을 했었다.

일단, Session > ㄱㄱ

Session > Send에서

Queue에다가 sendBuff를 집어넣는데

if문 == 실제로 1빠로 와서 넣었다면 RegisterSend()의 실행까지 하고

1빠가 아니라면 Queue에다가 밀어만 넣고 빠져나오는 것임.


우리는 일단 Push를 하면서 Session > Send처럼 판별을 해주자.

Queue에 쌓인것을 실행 할 것인지 말것인지 정하는

_flush

만약

라면 Queue를 처리를 하면될 것이다.

그런데 실행을 할 때

이렇게 lock을 잡고 계속 실행을 하고 있으면

실행하는 동안 다른애들이 접근을 할 수 없으니까

강제적으로

이렇게 받아주도록 할 것이다.

그래서 _flush가 false라면은

"아하! 내가 이제 실행을 해야 겠구나!" 라는것을

flush = _flush = true로 받아주는 것이다.

그래서 true일 경우 "일을 처리 해야됨!"이니까

Flush라는 일을 처리를 할 함수를 만들어 주도록 하자.

그래서 if문으로 Pop()을 한다음에

일감을 뽑아와서 없다면 retrun -> 끝내고

그게 아니라면

Pop을 해서 들고 있는 (Action () => 람다로 넘겨준 일감을)

실행 == action.Invoke를 해주면될 것이다.


그런데 지금 이상한 점이

분명히 Flush는 나혼자하는데

Pop을 할때 왜 lock을 잡는지 이상할 텐데

내가 여기서

이렇게 하나하나씩 꺼내는 와중에도

다른애가

여기다가 일감을 밀어 넣을 수 있다.

그래서 Pop을 할대도 lock을 잡고 해야


  1. A라는 쓰레드가 Push에서 락을 잡는다.(다른애가 Push를 못하는 상황)
    그리고 _jobQueue에다가 일감을 밀어 넣는다.

  2. lock 안에서 flush가 true로 바뀌어서 Flush함수로 간다.

  1. A쓰레드는 Flush함수에 들어와서 while문안에서 Pop을 한다.
  1. Flush에서 Pop을 하는 순간 A는 락을 잡고 "_jobQueue.Count == 0" 이 될때까지
    retrun _jobQueue.Dequeue();를 하면서 Flush의 while문을 돌게된다.
  1. (그러면 A가 잡고있던 lock은 풀린다? == 다른 B라는 쓰레드가 들어 올 수도 있다 -> 맞나요?? 아니면 A라는 쓰레드가 Flush함수를 호출을 하더라도 계속 lock을 잡고있는것인가요? 아니면 Flush를 실행하러 lock을 풀고 가는것인가요?? )

  2. (A는 Flush함수를 실행하러 왓기에 Push의 lock은 풀려있는 상태이다?)




지금까지 코드가 잘못됨

지금 이부분이 lock밖에서 실행되는 애임

그리고 답변글


그래서 나중에 _jobQueue의 일감이 다 끝났다면

이렇게 false로 풀어주어서

다른애가 Flush하고 Pop을 관리하도록 해준다.

그래서 결국 Push에 여러명이 접근을 해서 일감을 밀어넣는것은 락으로 안전하게 넣고있고

Pop을 하는것은 flush덕분에 한명만 일을 처리하게 되어서

한명만 주방에서 일하는 것이다.

그래서 한번에 한명만 Flush를 실행할 수 있어서

GameRoom >

이런식으로 lock을 잡아서 실행했던부분 없어도 된다.

( 다 지우기 ㄱㄱ)

이런식으로 ㄱㄱ

이렇게되면 Enter, Leave, BroadCast이런 일감들이

요안에 쌓이게 되고

경우에따라 Push로 맨처음 일감을 밀어 넣은애가

실행까지 담당을 하는

구조이다.

그래서 테스트 ㄱㄱ

그래서 보면은

서버랑 클라랑 열심히 열심히 잘 돌아간다.

그래서

쓰레드들도 확연히 줄어든것까지 확인 OK

그런데

C_chatHandler > breakPoint잡고

더미 클라쪽 콘솔창을 끄면은

크래쉬가 난다.

지금 Room이 null로 크래쉬가남

요렇게

그래서 이게 왜 이런 사태가 발생하는지 고민을 해보도록 하자.


2. 크래쉬 해결

우리가 이렇게 람다로 clientSession.Room에 접근을 해서 브로드 캐스트를 하는데

지금 커맨트 패턴으로 실행시점이 뒤로 밀린 것이다.

그래서 이것을 예약을 한 상태에서

Room이 null로 바뀌어서 제거가되면은

결국 clientSession.Room부분에서 Room을 찾지를 못해가지고

크래쉬가 난다.

그래서 ClientSession에서 어디서 Room을 null로 밀어넣고 있는지 보면은

이부분이 문제가 되는 것이였다.

그래서 이것을

이렇게 해주면

Room은 날라가더라도 room은 존재를 하게되니까

"참조"는 유지하고 있으니까ㅣ

room을 이용해서 Leave를 해주면

크래쉬 해결된다.

그래서 PacketHandler에서도 비슷하게 수정을 해주면되는데

Room은 계속 바뀔 수 있으니까

room으로 추출을 한다음에

이렇게 해주고

다시 테스트를 해보면

더미 클라 꺼보면

크래쉬 안나고 잘 된다.

profile
https://cjbworld.tistory.com/ <- 이사중

0개의 댓글