NHN NEXT 게임 서버 프로그래밍 강의 자료입니다. 최소한의 필요한 이론 내용은 질문 위주로 구성되어 있고 (답은 학생들 개별로 고민해와서 피드백 받는 방식) 해당 내용에 맞는 실습(구현) 과제가 포함되어 있습니다.
참고로, 서버 아키텍처에 관한 과목은 따로 있어서 본 강의에는 포함되어 있지 않습니다.
NHN NEXT 게임 서버 프로그래밍 강의 자료입니다. 최소한의 필요한 이론 내용은 질문 위주로 구성되어 있고 (답은 학생들 개별로 고민해와서 피드백 받는 방식) 해당 내용에 맞는 실습(구현) 과제가 포함되어 있습니다.
참고로, 서버 아키텍처에 관한 과목은 따로 있어서 본 강의에는 포함되어 있지 않습니다.
NHN NEXT 게임 서버 프로그래밍 강의 자료입니다. 최소한의 필요한 이론 내용은 질문 위주로 구성되어 있고 (답은 학생들 개별로 고민해와서 피드백 받는 방식) 해당 내용에 맞는 실습(구현) 과제가 포함되어 있습니다.
참고로, 서버 아키텍처에 관한 과목은 따로 있어서 본 강의에는 포함되어 있지 않습니다.
NHN NEXT 게임 서버 프로그래밍 강의 자료입니다. 최소한의 필요한 이론 내용은 질문 위주로 구성되어 있고 (답은 학생들 개별로 고민해와서 피드백 받는 방식) 해당 내용에 맞는 실습(구현) 과제가 포함되어 있습니다.
참고로, 서버 아키텍처에 관한 과목은 따로 있어서 본 강의에는 포함되어 있지 않습니다.
NHN NEXT 게임 서버 프로그래밍 강의 자료입니다. 최소한의 필요한 이론 내용은 질문 위주로 구성되어 있고 (답은 학생들 개별로 고민해와서 피드백 받는 방식) 해당 내용에 맞는 실습(구현) 과제가 포함되어 있습니다.
참고로, 서버 아키텍처에 관한 과목은 따로 있어서 본 강의에는 포함되어 있지 않습니다.
NHN NEXT 게임 서버 프로그래밍 강의 자료입니다. 최소한의 필요한 이론 내용은 질문 위주로 구성되어 있고 (답은 학생들 개별로 고민해와서 피드백 받는 방식) 해당 내용에 맞는 실습(구현) 과제가 포함되어 있습니다.
참고로, 서버 아키텍처에 관한 과목은 따로 있어서 본 강의에는 포함되어 있지 않습니다.
NHN NEXT 게임 서버 프로그래밍 강의 자료입니다. 최소한의 필요한 이론 내용은 질문 위주로 구성되어 있고 (답은 학생들 개별로 고민해와서 피드백 받는 방식) 해당 내용에 맞는 실습(구현) 과제가 포함되어 있습니다.
참고로, 서버 아키텍처에 관한 과목은 따로 있어서 본 강의에는 포함되어 있지 않습니다.
NHN NEXT 게임 서버 프로그래밍 강의 자료입니다. 최소한의 필요한 이론 내용은 질문 위주로 구성되어 있고 (답은 학생들 개별로 고민해와서 피드백 받는 방식) 해당 내용에 맞는 실습(구현) 과제가 포함되어 있습니다.
참고로, 서버 아키텍처에 관한 과목은 따로 있어서 본 강의에는 포함되어 있지 않습니다.
NHN NEXT 게임 서버 프로그래밍 강의 자료입니다. 최소한의 필요한 이론 내용은 질문 위주로 구성되어 있고 (답은 학생들 개별로 고민해와서 피드백 받는 방식) 해당 내용에 맞는 실습(구현) 과제가 포함되어 있습니다.
참고로, 서버 아키텍처에 관한 과목은 따로 있어서 본 강의에는 포함되어 있지 않습니다.
NHN NEXT 게임 서버 프로그래밍 강의 자료입니다. 최소한의 필요한 이론 내용은 질문 위주로 구성되어 있고 (답은 학생들 개별로 고민해와서 피드백 받는 방식) 해당 내용에 맞는 실습(구현) 과제가 포함되어 있습니다.
참고로, 서버 아키텍처에 관한 과목은 따로 있어서 본 강의에는 포함되어 있지 않습니다.
Auto Scalable 한 Deep Learning Production 을 위한 AI Serving Infra 구성 및 AI DevOps...hoondong kim
[Tensorflow-KR Offline 세미나 발표자료]
Auto Scalable 한 Deep Learning Production 을 위한 AI Serving Infra 구성 및 AI DevOps Cycle 구성 방법론. (Azure Docker PaaS 위에서 1만 TPS Tensorflow Inference Serving 방법론 공유)
(GameTech2015) Live Operation by Adbrix의 Node.js와 MongoDB를 이용한 멀티테넌트 인프라 구축사례Jeongsang Baek
대부분의 중소 모바일 게임 업체는 앱을 잘 만들기에도 시간이 모자라 출시일을 잘 맞추기 급급한 상황이다. 그러다 보니 운영을 위한 툴은 소홀히 개발하는 경우가 대부분이고 운영 캠페인은 날림으로 개발하거나 그때 그때 개발자가 필요한 부분만 개발하기 일쑤다. 그러다보니 마케터는 결국 늘 개발자 눈치만 살피게 된다. 필자는 블루윈드에서 이러한 문제를 절감했고 '모바일 게임 개발사가 앱 개발에만 집중할 수 있게 해주고 싶다'는 IGAworks의 철학에 공감하여 라이브 오퍼레이션 프로젝트를 시작하게 되었다.
라이브 오퍼레이션의 개발 중점과제는 5가지였다. 첫번째, 다수의 개발사가 하나의 큰 클라우드 시스템을 사용하도록 multi-tenant 인프라를 구축해야 한다. 두번째, TCO(Total cost of ownership)를 최소화해야 한다. 세번째, 앱의 핵심유저를 실시간으로 그룹화하여 타게팅 캠페인을 할 수 있어야 한다. 네번째, 캠페인의 성과를 마케터에게 실시간으로 피드백해야 한다. 다섯째, 3개월 안에 정식 서비스가 되어야 한다는 점이었다. (왜 우리에게 주어지는 시간은 늘 3개월인가) 그리고 당연하지만 이 서비스를 혼자 개발해야 했다.
이 다섯가지 이슈를 해결하기 위하여 AWS 클라우드 상에 생산성과 성능이 검증된 node.js 와 mongodb를 이용하여 서비스 백엔드를 구성하였고, multi-tenant를 구성하기 위한 여러가지 고민과 그 해결책을 직접 구현하였다. 필자는 node.js와 mongodb를 사용해 본 경험이 충분하다 생각했지만 대규모 정식 서비스를 진행하며 많은 함정에 빠졌고 결국 해결했다.
이 발표를 통해 청강자는 node.js와 mongodb를 이용하여 multi-tenant 인프라를 구축해야 할 때 고려해야 할 설계 방식과 기술적인 고민, 그것에 대한 현실적인 해법을 얻을 수 있다.
이 발표는 [야생의 땅: 듀랑고]의 지형 배포 시스템과 생태계 시뮬레이션 자동화 시스템에 대한 이야기를 다룹니다. 듀랑고의 각 섬은 크기와 지형, 기후 조건이 다양하고 섬의 개수가 많아서 수동으로 관리하는 것은 사실상 불가능합니다. 몇번의 사내 테스트와 베타 테스트를 거치면서 이러한 문제를 해결해주는 자동화된 도구의 필요성이 절실해졌고, 작년에 NDC에서 발표했던 생태계 시뮬레이터와 Docker, 그리고 아마존 웹서비스(AWS)를 이용하여 수많은 섬들을 자동으로 생성하고 관리하는 자동화 시스템을 구축하게 되었습니다. 그 과정에서 했던 고민들, 기존의 애플리케이션을 "Dockerizing" 했던 경험, AWS의 각 서비스들을 적절히 활용했던 이야기, AWS의 각 지역별 요금이 상이하다는 점을 이용해서 비용을 절감한 사례, 그리고 자동화 시스템의 문제점과 앞으로의 방향에 대해서 이야기 할 계획입니다.
2. 비동기 방식의 필요성.
• 멀티 스레드 프로그래밍은 기본(코어가 여러 개니까.)
• 하나의 프로그램이 이제 네트워크로 연결된 별도의 프로세서에
서 동작하는 경우도 너무 많다(쓸 만한 서비스는 거의 대부분).
• 락을 이용한 동기화 방식으로 멀티 스레드 프로그램을 만든다
는 건, 결국 어느 시점에서는 다른 스레드를 기다리기 위해 블럭
상태에 있어야 한다는 거다.
• 결국 성능향상을 위해서 멀티 스레드 프로그램을 만들었는데
그 노력이 허사가 돼 버린다.
• 결국 비동기 방식의 멀티 스레드 프로그램을 만들어야 한다.
4. Appendix : std::future,std::promise(2)
• std::promis<dataType> promis1; //promis객체를 생성하고
• auto future1 = promis1.get_future();//promis1에 해당하는 future객체를 받고.
• std::thread th1(
[&promis1, inFile](){ promis1.set_value(readFile(inFile));}
);// 값을 생산하는 스레드에 promis1을 전달하고 값을 promis1에 저장한다
• size_t result = fut2.get();
//원래 스레드에서는 다른 작업을 하다가. 값이 필요할 때 future1객체를 이용해서 값을 받을 수 있다. 이때 블럭이 된다.
5. Appendix : std::async
• 하지만 위의 std::future와 std::promis는 사용하기 불편하다.
• 코드도 복잡하고.
• 그때 사용할 수 있는 것이 std::async
• 처음인자로 함수자나 람다를 넣고 그 다음 그 함수자나 람다의
인자를 순서대로 매개 변수에 넣어 주면 그 리턴 값의
std::future 객체를 반환한다.
• 스레드도 알아서 만들어 준다(많이 추상화 되어있음.)
6. Appendix : std::async(2)
auto fut1 = async(readFile, inFile); //함수자 와 매개변수
auto fut2 = async(
[&future1](const string& path){ return writeFile(future1.get(),
path);},//람다
outFile); //매개변수
7. 예제 코드: 소수 구하기
• 소수를 구하는 함수들.
https://gist.github.com/LethalSun/d74cfe458196eb23518242c33
2fc6597
• 정수 범위가 주어 졌을 때 스레드 마다 범위를 나눠주는 함수.
https://gist.github.com/LethalSun/2131d3601f7431a4810b8defd
d3efb1e
• 실제 스레드를 만들어서 테스트 하는 코드.
https://gist.github.com/LethalSun/3b6452d4dd0514f9e8b4e7e0
e4d4c2e3
8. 비동기 방식에서의 std::vector
• 멀티 스레드 간에 공유를 하는 경우
->이상하게 동작한다.
• 동기화 객체를 이용해서 락을 거는 경우
-> 잘 동작하지만 여러 개의 스레드를 사용한 것에 비해서 싱글
스레드로 하는 것과 차이가 없다…
• PPL 병렬 컨테이너를 사용했을 때.
->잘 동작한다. 동기화같은걸 고민하지 않았는데…
9. 비동기 방식에서의 std::vector(2)
• 동기화 객체를 이용하지 않았을 때 문제가 발생한 이유.
• 각각의 스레드가 이터레이터를 이용해서 공유 컨테이너의 값을 읽고
있을 때 다른 스레드에서 컨테이너의 값을 삭제 하거나 이동하면 이터
레이터는 무효가 된다.
• 또 값을 추가 할 때 현재 컨테이너가 수용할 수 있는 개수를 초과 하면
새로운 공간에 가지고 있는 요소를 전부 복사하게 되는데 이때 그냥 동
일한 공간다음의 위치를 추가적으로 확보하는게 아니라 새로운 공간에
새로운 크기만큼 할당하게 된다(아마 물리적 공간에서의 연속성을 가
져야 하기 때문이 아닐까?)
• 즉 삭제 뿐만 아니라, 삽입도 문제가 된다…
10. Microsoft PPL(Parallel Patterns Library)
• 이러한 컨테이너의 문제점을 해결하기위해서 마이크로 소프트
에서 만든 PPL컨테이너가 존재함.
• concurrent_vector
• concurrent_que
• concurrent_unordered_map
• concurrent_unordered_multimap
• concurrent_unordered_set
• concurrent_unordered_multiset
• Linux 에서는 Intel TBB:Threading Building Blocks이 존재한다.
• 추가로concurrent_bounded_queue/concurrent_priority_queue도 지원
12. 예)concurrency::concurrent_vector (cont.)
• 당연히 락을 사용하지 않고 동시에 접근해서 조작 가능하다.
• 끝에 요소를 넣는 push_back으로만 요소를 넣어야 한다.
• Push_back에 move시멘틱을 지원하지 않는다.
• erase, pop_back이 없고 전체를 지우는 clear는 동시실행을 지
원하지 않는다->요소의 삭제는 동시 실행이 불가능 하다.
• 각 요소는 메모리 상에 연속적으로 존재하지 않는다.
• 하지만 배열처럼 임의 접근은 가능하다.
• 요소를 추가하거나 벡터를 확장할 때 요소를 재배치 하지 않는
다.
15. 예)concurrency::concurrent_queue (cont.)
• push(Enqueue) 와 try_pop(Dequeue)은 동시 실행 가능하다.
• front 와 pop메소드는 없다.
• 이터레이터를 사용할 수 있지만 동시 실행 가능하지 않다.
• Back메소드는 존재하지 않고 끝 값을 참조할 수도 없다.
• size메소드 대신 동시 실행 가능하지 않은 unsafe_size메소드를
제공한다.
• clear와 empty로 concurrent_que를 비울 수 있지만 empty만 동
시실행 가능하다.