블로킹은 프로세스가 시스템콜을 하고 난 후(IO 같은거) 결과가 리턴될때까지 기다리고 있는 상태이다. 블록이 되어있는 상태라고 이해하면된다.
논블로킹은 시스템을 호출한 직후 (IO 같은 것을) 기다리지 않고 바로 다음을 처리하는 것이다. 종료가 되면 그때 이벤트를 받아서 처리한다.
다음 예제에서 블로킹, 논블로킹을 살펴볼 수 있다.
왼쪽에 있는 코드는 서버 프로그램이다.
포트먼트를 아규먼트로 지정해서 바인드, 리슨을 한 후 반복문에서 소켓에 대한 연결을 대기하고 있다. 그리고 데이터를 2048바이트만큼 계속 수신한 후 데이터사이즈를 더해서 출력하는 코드이다.
오른쪽은 데이터를 인코드한 후 보낸다. 데이터는 * 300 * 1024*1024 만큼 반복해서 보내서 거의 3기가바이트의 양이 될 것이다. 이 데이터를 이제 전송을 할 때 socket.send() 함수를 호출해서 보낸다. 이때 대량의 데이터를 보낼때는 send() 가 오류가 날 수 있다. 이것은 블로킹, 논블로킹 둘 다 오류가 날 수 있다. 운영체제에 따라 다를 수도 있다. 실험 결과 맥에서는 숫자가 작게 오류가 나고 윈도우에서는 크게 오류가 난다.
작은데이터는 문제없이 전송이 되지만 대용량 데이터는 오류가 난다.
setblocking(0)== (논블로킹) , setblocking(1)==(블로킹)
블로킹모드는 굉장히 오랜시간 대기를 하면 완료까지 시간이 많이 걸린다. 다만 오류 리턴이 금방될 수 도 있어서 실험 환경에 따라 달라질 수 있다.
이런 경우 운영체제에 소켓 버퍼사이즈가 있어서(디폴트 크기 다름) 굉장히 큰 용량 한번에 전송하면 오류가 날 수 있고, 오류가 났을 때
send () 함수를 sendall() 로 바꾸거나 반복문을 써서 해결할 수 있다.
아래 코드는 정상 작동하는 코드이다. 동일하게 굉장히 큰 용량의 데이터를 전송하고 있다. 아래는 3기가 바이트를 두번에 나누어 실행했다.
이런 블러킹 모드에서 굉장히 큰 데이터를 보낼땐 io 가 길어지고 그럴땐 논블로킹 모드를 사용할 수 있다.
위 예시를 통해 소켓 커널 버퍼사이즈에 따른 오류도 살펴봤다.
다음은 동기 비동기에 관한 문제이다.
특정 작업이 끝나면 다음을 처리하는 순차처리방식이 동기이다. 끝나는 걸 기다렸다가 순서대로 처리하는 것이다.
블뢰킹 논블로킹이랑 헷갈릴 수 있는데 동기화, 비동기화라고 하면 두개의 작업이 클럭이 맞춰진다. 즉, 끝나는 걸 정확히 기다렸다가 다음작업을 처리한다고 보면된다. 비동기는 파이프라이닝 방식이다. 여러 작업이 실행되어야하는 상황이다. 그 작업을 순차적으로 처리하지 않고, 끝나지 않은 상태에서 작업 세개를 동시에 실행하도록하는게 비동기 방식이다. 이것 역시 cpu 실행속도가 다르기 때문에 이 시간에 대한 버퍼링을 하기 위해 이런 방식이 도입된 것이다.
아래 예시
'* 예시 *
process_sync() 함수에서 find_users_sync() 함수를 3개 만ㄷ르어서 실행
함수를 호출해서 순서대로 1번째 2번재 3번째 이렇게 순서대로 for 루프로 실행함.
비동기 관점에서 프로그램한 예제를 살펴보자. 비동기 프로그래밍을 파이썬에할 때는 신택스를 공부해야한다.
asyncio 에 대한 함수가 있기 때문이다.
이걸 살펴보는 이유는 여러 개를 동시에 사용할 때는 스레드 사용이 전통적인 방법이었다. 스레드 사용시 일반적으로 프로세스보단 가볍고 프로그램하는 게 조금 더 간단할 수 있지만 스레드 역시 스레드 safe 프로그래밍이 어렵다는 단점이 있다. 여러 관련된 문제를 해결할 필요가 있다. 그리고 성능이 코어 개수에 민감하다. 이런 스레드를 활용하는 동시 프로그래밍을 대체하는 방식으로 비동기 프로그래밍 방식이 많이 개발되고 있다. 자바스크립트 기반, nginx 와 같은 하나의 쓰레드로 동시 처리하는 비동기 프로그래밍이 그 예시이다.
다음은 웹 서치 예제이다.
다음은 구글로 6개의 키워드를 검색해서 시간을 계산하는 예제이다. 루프를 돌면서 6번을 실행을 하는 것이므로 순서대로 4.8초 정도 나왔다. 이건 순차적으로 된 것이다. 동기화 되어있는 작업6개가 실행된 결과이다.
(*코드*)
이것을 비동기로 실행할 때는 asyncio 모듈을 사용한다. 코루틴을 정의를 하고 이벤트 루프를 만들고, 그 결과를 기다려야한다. 그리고 종료하면 닫기, 그다음에 객체가 다 끝난 결과를 대기하는게 await 키워드이다. 그래서 웹페이지를 동기화된 작업을 실행할 때는 순차적으로 된다. 그걸 비동기화하게되면 어떻게 되는지 살펴보자.
아래 코드를 보자
(*코드*)
아까 본것처럼 구글 사이트에서 6개 검색을 해서 시간을 측정하는데 대략 0.9초로 굉장히 성능이 향상된 것을 확인할 수 있다.
따라서 io 가 굉장히 길때(하드디스크 접근, db접근, io 처리)는 순차적으로 처리하는 게 아니라 비동기화 해서 처리하면 속도가 향상 될 수 있다.
(*사진*)
'Network' 카테고리의 다른 글
응용 계층 정리 (0) | 2023.10.21 |
---|---|
[컴퓨터네트워크] tcp 혼잡제어 (0) | 2023.10.16 |
[컴퓨터네트워크] 소켓프로그래밍 (0) | 2023.10.12 |
[컴퓨터 네트워크] TCP 개요 (0) | 2023.10.11 |
[컴퓨터네트워크] FTP, SMTP 프로토콜 (0) | 2023.10.02 |