동기/비동기 프로그래밍

Dec 06 2022
이 블로그에서는 동기 및 비동기 프로그래밍이 무엇인지 가장 잘 설명하려고 합니다.
발신자가 수신자에게 메시지를 보내고 응답을 기다리는 경우 다른 작업을 수행할 수 있습니까? 이러한 호출은 모든 곳에서 발생하므로 서버/클라이언트 대신 호출자/수신자를 말하고 있습니다. 설계상 처음 컴퓨팅을 구축했을 때 모든 것이 동기식이었습니다.
동기/비동기

발신자가 수신자에게 메시지를 보내고 응답을 기다리는 경우 다른 작업을 수행할 수 있습니까? 이러한 호출은 모든 곳에서 발생하므로 서버/클라이언트 대신 호출자/수신자를 말하고 있습니다. 설계상 처음 컴퓨팅을 구축했을 때 모든 것이 동기식이었습니다. 이는 발신자와 서버가 동기화되거나 동일한 리듬에 있는 사인파로 볼 수 있습니다. 비동기는 동기화되지 않았음을 의미합니다.

동기 I/O
호출자는 요청을 수신자에게 보낸 다음 차단합니다. 발신자가 차단되어 아무 것도 하지 않는 경우이므로 전체 시간이 낭비됩니다. 예전에는 CPU가 프로세스가 차단된 것으로 생각하여 프로세서에서 프로세스를 제거하고 차단되지 않은 새 프로세스를 추가했습니다(컨텍스트 전환). 따라서 호출자는 그동안 실행할 수 없습니다. 마지막으로 수신자가 응답하면 운영 체제는 프로세스를 다시 프로세서로 보낼 수 있습니다. 따라서 발신자는 차단을 해제합니다. 이는 클라이언트와 서버가 완전히 동기화된 방식을 보여줍니다.

OS 동기화 I/O의 예:
1. 프로그램이 CPU에 디스크에서 파일을 읽도록 요청합니다.
2. 프로그램의 메인 스레드가 CPU에서 분리됩니다.
3. 읽기가 완료되고 프로그램이 다시 실행되기 시작합니다.

// A simple Js example
// Program starts
// Programs uses CPU to execute work.

SampleFunction();
// Program reads from the disk
// Program can't do anything until file loads
readfile("SyncExample.dat")

// Program resumes

구체적으로 NodeJ의 관점에서 이야기하면 Linux에서 epoll을 사용하고 Windows의 경우 완료 스택을 사용합니다. nodeJs가 하는 또 다른 일은 차단 작업을 수행해야 하는 경우 차단하는 새 스레드를 가동하는 것입니다. 기본적으로 Nodejs는 I/O 작업에 사용하는 libuv 라이브러리에 4개의 작업자 스레드가 있지만 구성 가능합니다.

OS 비동기 호출(NodeJS)의 예
a) 프로그램이 보조 스레드를 가동합니다.
b) 보조 스레드가 디스크에서 읽습니다. 분명히 OS는 현재 프로세서에서 제거됩니다.
c) Main 프로그램은 계속 실행되고 실행됩니다.
d) 스레드가 종료되고 메인 스레드를 호출합니다.

// A simple Javascript example
// Program starts
// Programs uses CPU to execute work.

SampleFunction();
// Program reads from the disk
// Program hapilly moves on to the samplefunction2
readfile("SyncExample.dat", onReadFinish(console.log))
//file is not probably read yet

SampleFunction2();
//onReadFinish function called
// executing it

이제 우리는 순전히 클라이언트와 서버(백엔드)의 관점에서 논의할 것입니다.
따라서 동시성은 기다리거나 이동할 수 있는 클라이언트 속성으로도 알려져 있습니다. 요즘에는 동기식 클라이언트가 없으며 대부분의 라이브러리가 비동기식입니다. 대부분 클라이언트는 요청을 보내고 응답을 받고 응답이 실행될 때마다 일부 콜백이 호출됩니다. 따라서 특히 Node.js에는 응답을 확인하는 이벤트 루프 메인 루프가 있습니다.
동기식은 발표자가 응답하면 회의가 진행되는 회의에서 질문을 하는 것과 같다는 이 아름다운 실제 사례를 통해 누군가가 설명했을 때 항상 그랬기 때문에 이것은 혼란스러울 수 있습니다. 비동기식은 수신자가 시간이 있을 때마다 응답할 수 있는 이메일에 질문을 하는 것과 같습니다.

비동기식 백엔드 처리

백엔드 엔지니어로서 백엔드 비동기화에 대해 이야기하지 않으면 불공평합니다. 많은 코드/리포지토리에서 클라이언트는 주로 비동기식이지만 백엔드는 여전히 대기합니다. 따라서 클라이언트가 일부 데이터를 푸시하도록 요청할 때 데이터베이스 호출을 수행한다고 가정해 봅시다. 커밋 후 상태 200 응답을 반환하는 백엔드의 응답을 기다리라는 요청을 여러 번 받습니다. 이제 렌즈를 백엔드로 옮기면 프런트엔드는 비동기식이지만 백엔드는 여전히 동기식입니다. 그렇다면 즉각적인 응답을 어떻게 반환합니까?
해결책 중 하나는 대기열이라는 아름다운 데이터 구조를 사용하는 것입니다. 클라이언트가 요청을 보내면 즉시 실행하겠다고 약속하지는 않지만 대기열에 플러시합니다. 그 이유는 백엔드가 이전 요청을 완료할 수 있고 클라이언트가 더 이상 차단되지 않기 때문입니다. 우리는 요청을 대기열에 넣었다는 응답을 보낼 수 있으며 여기에 약속/JobID가 있습니다. 자세한 내용은 메시지 대기열 에 대해 읽을 수 있습니다 .
사용 사례에 따라 이 외에도 매우 인기 있는 솔루션이 있습니다.

비동기 워크로드의 실제 예: a) Postgres ↗
의 비동기 커밋 . b) Linux의 비동기 I/O(io-uring). c) 비동기 I/O fsync(fs-cache): 어떤 파일에 무언가를 쓸 때마다 디스크에 직접 쓰지 않고 파일 시스템 캐시에 씁니다. 운영 체제에는 캐시가 있으며 쓰기는 페이지로 이동합니다. 그런 다음 운영 체제는 한 번에 모든 페이지를 플러시합니다.

전체 내용을 다음과 같이 요약할 수 있습니다.
a) 동기식 프로그래밍 접근 방식은 작업을 순차적으로 실행합니다. 각 작업은 이전 작업이 완료될 때까지 기다린 후에 수행됩니다.
b) 비동기 프로그래밍 모델에서 작업이 실행되면 이전 작업이 완료될 때까지 기다리지 않고 다른 작업으로 이동할 수 있습니다.

읽어 주셔서 감사합니다; 도움이 되었기를 바랍니다.
더 궁금한 점이 있으면 LinkedIn / Instagram을 통해 자유롭게 연결하십시오 .