Cooperative multi-tasking
with Node.js
Node.js로 협력적 멀티태스킹 처리하기
play.node();2017withIBM
play.node();2017withIBM
Speaker
Irho Park (박일호)
aka. iMaZiNe @ Kakao corp.
Daum자동차 서비스 개발
고백
거창하게 제목을 정해 놓았지만…
하려고 하는 이야기는
적다고 할 수 없는 숫자의 데이터 마이그레이션 경험담
play.node();2017withIBM
사건의 시작
2016년 카카오 입사
play.node();2017withIBM
11개월 만에 꿈에 그리던 제주생활
출근 20분, 퇴근 15분
월정리 20분, 함덕서우봉해변 15분
그렇게 2016년 11월
Daum자동차 서비스를 담당하게 됩니다.
play.node();2017withIBM
여기까지는 Happy함
play.node();2017withIBM
첫번째 임무
Legacy article migration
play.node();2017withIBM
대부분 먼저 하는 생각
1min = 60s
1hour = 3,600sec
1day = 86,400sec
초당 100개씩만 처리하면…
play.node();2017withIBM
여기까지도 Happy함
play.node();2017withIBM
요구사항 분석
구문서 파싱 및 가공
이 모든것을 안전하게 처리
어뷰징 제거
연결된 정보들 처리 (ex. 댓글)
play.node();2017withIBM
어떻게
DB를 읽고, 쓰고
파일을 읽고, 쓰고
API를 호출하고
play.node();2017withIBM
결국
비동기 요청들(Asynchronous Requests)을
순차적(Sequentially)으로
안전하게(Transactionally) 처리
play.node();2017withIBM
정해진 시간 안에
play.node();2017withIBM
Why use Node.JS
Because, I love it!
play.node();2017withIBM
Simulation
1개의 article을 처리하기 위해 필요한 비동기요청 수는
최소 8개 + 댓글 수 * 2
댓글이 없다고 가정하고 비동기 요청 1개당 20ms 로 잡아도
최소 160ms 필요 (6.25/sec)
86400 * 6.25 = 540,000
play.node();2017withIBM
실제 효율은 절반 이하…
느려도 너무 느리다!
play.node();2017withIBM
Solution
병렬처리로 속도를 높이거나
프로세스의 효율을 높이거나
play.node();2017withIBM
마음을 비우고 순차적으로…
play.node();2017withIBM
결국 동시성(Concurrency) 문제를
해결해야 하는 상황!
Message Queue 를 사용해 스케쥴링 하고
병렬처리 하기로…
play.node();2017withIBM
아직까지도 Happy함
play.node();2017withIBM
구현해 봅시다
비동기를 처리하는 대표적인 방법
play.node();2017withIBM
Callback!
Callback DEMO
play.node();2017withIBM
Callback Image?
play.node();2017withIBM
조금 더 나은 방법
play.node();2017withIBM
Promise
Promise DEMO
play.node();2017withIBM
How to solve memory issue
play.node();2017withIBM
협력적 멀티태스킹
play.node();2017withIBM
Cooperative Multi-tasking
일종의 시분할(Time-sharing)방식
운영체제의 개입 없이 task가 독점적으로 CPU를 사용
미사용시 자발적 CPU 자원 반환
Critical section 보호를 위한 Lock이나 Semaphore 불필요
서광열의 코딩스쿨(https://gamecodingschool.org) 참조
구현방법의 선택
play.node();2017withIBM
Coroutine
ES7 스펙 async, await
Node.js 7.6 부터 공식적으로 지원
Node.js 6.x —harmony 옵션과 함께 사용
Coroutine
코루틴은 우리가 잘 알고 있는 서브루틴(Subroutine)과 달리 진입점(Entry Point)이 여러 개일 수 있습니다.
쉽게 이야기하면 실행을 멈췄다가(Suspend) 재개(Resume)할 수 있다는 점인데요.
이 특성을 살리면 우리가 익히 아는 스레드(Thread)처럼 쓸 수 있게 됩니다.
다만 스레드와 달리 코루틴은 비선점적(Non-Preemptive)이기때문에
코드의 흐름을 전적으로 사용자가 제어할 수 있습니다.
play.node();2017withIBM
spoqa 기술블로그 - Concurrency and eventlet(문성원님) 참조
Coroutine
play.node();2017withIBM
Coroutine DEMO
코드 가독성이 좋아짐
play.node();2017withIBM
대규모 처리시 안전함
비동기 다중 중첩시 유의해야 함
결과적으로 Happy함
play.node();2017withIBM
TIPs
play.node();2017withIBM
Coroutine 예외 처리 방법
UV_THREADPOOL_SIZE
Coroutine = Generator + promise + dispatcher(trampoline)
References
play.node();2017withIBM
TOAST ES6의 제너레이터를 사용한 비동기 프로그래밍(김동우님)
spoqa 기술블로그 - Concurrency and eventlet(문성원님)
서광열의 코딩스쿨 - 코루틴(Coroutine) 이해하기(서광열님)
Wikiedia Coroutine 한글 번역(dogfeet님)
play.node();2017withIBM
One more thing…
We want you!
https://careers.kakao.com/jobs/P-10465
play.node();2017withIBM
Thank you
개발자라면 지금 방문하세요! developer.ibm.com/kr
https://github.com/imazine/playnode2017_sample

Nodejs cooperative-multi-tasking

Editor's Notes

  • #5 퇴근 15분 (내리막길) 서울 -> 판교 때 편도 1시간40분 제주에서는 마라도 갈 수 있는 시간 제주 좋은거 다들 아실거고… 효리네 민박? 삶의 질이 달라졌다!!
  • #6 우여곡절 끝에
  • #7 The king of the hill
  • #9 8,640,000 개의 문서를 처리할 수 있을 것이라는 긍정적인 생각을 하게 됨
  • #10 자 이제 먼저… 요구사항을 분석해 봅시다
  • #12 비동기 IO
  • #15 가장 손에 익숙한 도구, 문제를 인식했을 때 가장 먼저 떠오른 도구
  • #16 최대한 긍정적으로 생각했을 때 하루 540,000개
  • #17 - 모든 IO가 20ms에서 끝나지 않음 - H사 관련 댓글만 수백개 이상
  • #19 처리할 수 있다면 좋겠지만…
  • #20 대부분의 병렬 마이그레이션 상황에 선택하는 가장 쉬운 방법을 선택 많은 분들이 이야기 하셨던 부분이라 MQ 사용은 넘어감
  • #21 별 문제 없을 것이라 생각함
  • #22 질문한다. 비동기를 처리하는 대표적인 방법 Node.js 의 Continuous Passing Style
  • #23 코드를 보시고 이런 생각 하신분들 있을겁니다.
  • #24 - 다중 순차적 비동기 처리가 상당히 까다롭다. - transaction및 failover까지 처리하면 더 복잡한 코드가 됩니다.
  • #25 질문한다. 콜백헬의 솔루션이라 알려지기도 한.. (사실은 아님) Lazy evaluation 이 가능
  • #26 1,000,000개 메모리 펑터짐
  • #27 어떻게 메모리 이슈를 해결 하는가…
  • #28 어디선가 놀고있는 자원을 빡시게 사용할 수 있다 들었던… - 협력적 멀티태스킹은 일종의 시분할(time-sharing) 방식으로 여러 task가 하나의 CPU를 나눠쓰는 방식, 선점형 멀티태스킹(preemptive multitasking)과 달리 운영체제의 개입 없이 각 task가 독점적으로 CPU를 사용, 사용이 끝나면 CPU 자원을 자발적으로 양보 장점은 리소스를 사용하는 도중에 강제로 CPU를 뺏기는 일이 없으므로, 크리티컬 섹션(critical section)을 보호하기 위한 락(lock)이나 세마포어(semaphore) 등 동기화 수단이 필요 없다는 점 from 서광열의 코딩 스쿨(https://gamecodingschool.org/tag/%ED%98%91%EB%A0%A5%ED%98%95-%EB%A9%80%ED%8B%B0%ED%83%9C%EC%8A%A4%ED%82%B9/) 비동기 방식은 아님
  • #29 Cooperative multitasking 을 구현하는 방법 중 하나인 Coroutine을 써봅시다.
  • #30 코루틴은 우리가 잘 알고 있는 서브루틴(Subroutine)과 달리 진입점(Entry Point)이 여러 개일 수 있습니다. 쉽게 이야기하면 실행을 멈췄다가(Suspend) 재개(Resume)할 수 있다는 점인데요. 이 특성을 살리면 우리가 익히 아는 스레드(Thread)처럼 쓸 수 있게 됩니다. 다만 스레드와 달리 코루틴은 비선점적(Non-Preemptive)이기때문에 코드의 흐름을 전적으로 사용자가 제어할 수 있습니다. - from spoqa 기술블로그 - 코루틴과 greenlet(문성원님)(https://spoqa.github.io/2012/02/13/concurrency-and-eventlet.html#코루틴과-greenlet)
  • #32  코루틴은  1. 특정일을 단계적으로 발생하게 할때 2. 시간의 흐름에 따라 발생하는 루틴을 작성할때 3. 다른 연상이 완료될때까지 기다리는 루틴이 필요할때 사용하면 굉장히 편리하게 사용할수 있다.
  • #33 무사히 마이그레이션을 마칠 수 있었음. 하지만 아직 끝이 아니다… 마이그레이션 할 다른 녀석들은 지금도 생산되고 있습니다.
  • #34 Coroutine은 Generator + promise + dispatcher(trampoline) 조합으로도 구현할 수 있습니다. (시간상 제외된 이야기) TOAST (김동우님) 글(http://meetup.toast.com/posts/73) Node.js의 libuv 의 IO는 멀티스레드로 구현, UV_THREADPOOL_SIZE 를 늘리면 Connection 수를 늘릴 수 있음 promise.all 은 microTask(promise) limit를 모두 소진할 수 있음 —max_old_space_size로 힙을 늘리면 늘어남
  • #35 코루틴을 이해하는데 큰 도움이 된 글을 써주신 감사한 분들께 다시한번 감사를
  • #36 한가지 더 있습니다. 다음 미디어 개발팀에서 이런 것들을 함께할 동료를 구해요! 변태적으로 신규 스펙 사용을 즐기거나… 대규모 서비스를 경험해 보고 싶다거나… 제주근무를 해보고 싶다거나… 기술 공유를 즐기는 분 ! 환영 합니다!! 아까 말씀드린 남아있는 과제를 비롯 기상천외한 일들이 기다리고 있습니다.