로봇드림 재개봉 소식을 듣고 어제 친구와 신촌 메가박스에 호다닥 다녀왔다
결론부터 말하자면 영화 끝에 감정적으로 너무 괴로울 정도로 슬펐고, 지금까지 영화에 대한 생각을 떨칠 수가 없다. 
그럼에도 영화를 보길 정말 잘했다는 생각이 든다.
 
흔히 연인이나 친구를 그만 잊는것을 놓아주는 것이라고 말한다. 추억을 정리하고, 자꾸 떠오르는 마음을 누르는 행위들.
예전에는 내가 사랑하는 모든 것들은 (불가피한 경우를 제외하고) 내가 살아가고 있는 지금에 놓고 싶어 했다. 한때 내가 좋아했던 것들이 어색해지는게 참을 수 없었다. 멀어져가는 친구와 연락을 주고 받기 위해 노력하고, 더이상 같이 살지 않는 부모님께 매일 전화를 했다. 본가에서 자주 가던 빵집에 주말마다 갔으며 항상 가던 곳을 산책 했다. 
그런데 나이를 먹을수록 어느 순간 부터 내가 아무리 모두 끌어안고 있으려고 해도 결국 나의 상황에 따라 많은 것들이 과거로 남는다는 걸 느꼈다. 인간관계도 마찬가지. 어릴때는 에너지가 넘쳐서 부지런히 방법을 찾았지만, 몇번 시도하고 실망한 끝에 빛나는 순간들은 몇번이고 재연할 수 없다는 걸 어렴풋이 알게되었다.
그러므로 놓아준다는건 사랑하는 것을 나의 지금으로 끌고 오려고 애쓰지 않고 그 자리에 남겨두는것. 그렇게 함으로써 끝을 알고있는 그 시간을 더욱 아껴주는 방법이 아닐까 생각해본다.
 
아는 맛이 더 씁쓸했다. 

socket programming 수업 들을 때 공부 좀 열심히 해둘 걸..

지나고 하는 후회는 다 부질없다. 이제라도 부끄러움을 무릅쓰고 정리 해보려 한다.

소켓 인터페이스는 UNIX 계열 시스템에서 함수의 통신을 위해 설계한 함수의 집합이다. 소켓 통신을 이해하려면 먼저 이 소캣 인터페이스가 어떻게 이루어져 있는지 이해해야 한다.

 

1. 소켓 연결 과정

1-1. socket() : 소캣 생성 + 파일 디스크립터 할당

file desciptor

유닉스 계열 시스템에서 모든 것은 파일이다. 소켓, 디렉토리 등등 프로세스의 모든 것은 파일로 관리되고, 이들 프로세스의 open file 을 관리하는 user file descriptor table의 인덱스를 파일의 식별자로 사용한다. 이를 file descriptor 이라고 부르는데, 프로세스가 system call¹ 할 때 이 0이 아닌 정수값 (0 < .. < OPEN_MAX) 인덱스를 보고 구조체 파일 (struct file fd_array) 에 접근하여 파일을 찾을 수 있다.

대학 수업 때 user space 와 kernel space 가 다르다는 것을 배웠다. 그리고 커널은 인터럽트를 통해서 모든 하드웨어 접근이 가능하나 응용 프로그램에서 이를 사용하려면 커널에 접근해야 한다고 배웠다.
시스템 호출이란 프로그래밍 언어에서 지원하지 않는 기능에 대하여 운영 체제의 루틴을 호출하여 이용하는 것을 말한다. 

<기능>
1. 사용자 모드에 있는 응용 프로그램이 커널의 기능을 사용할 수 있도록 한다.
2. 시스템 호출을 하면 사용자 모드에서 커널 모드로 바뀐다.
3. 커널에서 시스템 호출을 처리하면 커널 모드에서 사용자 모드로 돌아가 작업을 계속한다.

※ 시스템 호출의 유형
프로세스 제어(process control)
파일 조작(file manipulation)
장치 관리(device management)
정보 유지(information maintenance)
통신(communication)

소켓도 마찬가지로 socket()을 호출하면 fd 가 할당된다. 그리고 이 fd는 소켓 구조체를 가리키고 있다. 구조체에는 포트 넘버, ip 등 정보가 포함된다. 

 

1-2. server socket -> bind() / listen() / accept()

서버 소켓의 행동은 다음과 같다.

  1. 소켓fd와 소켓 구조체에 나온 정보를 연결하는 bind()
  2. 서버 소켓으로서 연결을 기다리도록 (listening socket) 명시하는 listen()
  3. listening socket의 fd와 대기열에 있던 클라이언트의 주소를 주고 연결을 수락하는 단계인 accept() 
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
#include <sys/socket.h>
int listen(int sockfd, int backlog); // backlog 는 대기열의 크기

1-3. client socket -> connect()

클라이언트 소캣은 connect()로 서버 소캣과의 연결을 요청한다.

#include <sys/socket.h>
int connect(int clientfd, const struct sockaddr *addr,
            socklen_t addrlen);

이제 위 코드를 이해할 수 있게 되었다. 야호!

TCP 소켓이 연결을 맺는 과정은 https://squeak-squeak.tistory.com/35 여기에 정리했다. 이 과정과 관련한 서버 튜닝값에 대해 정리한 글이다.

 

2. 커널 튜닝 시 fd 값의 의미

위의 내용을 바탕으로 생각해보면 서버가 처리할 수 있는 커넥션 수를 늘리고 싶다면,  동시에 연결 맺을 수 있는 max client 값만 튜닝할 것이 아니라 이 fd 수도 따라 늘려줘야 할 것 같다. 

  • 시스템에 할당된 파일 디스크립터 수. (max 값은 65536 라고 한다 참고~) 늘리기
  • 리눅스의 경우 각 사용자 별로 이 값을 설정할 수 있기 때문에 사용자 레벨에서의 df limit 늘려주기

또한, file descriptor 값의 한도를 늘려줌과 동시에 시스템이 사용할 수 있는 최대 워커 스레드 수도 늘려줘야 합당할 것이다.

(thread_max). 실제로 회사에서 부하테스트를 거쳐 튜닝했던 vm 값 중에 fd가 있었다. 사실 이 글은 거기서 출발했다.

 

정리해놓고 보니 학생 때 나는 운영체제, 리눅스 시스템 설계, 네트워크 수업 시간에 도대체 뭘 한 건지.. 내 인생에서 가장 헛살았던 4년이 대학 다니던 시절이 아니었나 싶다. 그래도 포기하지 않고 개발자 하고 있는 걸 보면 신기하기도 하고 대단하기도 하고...운이 좋았던 것 같다. 

 

참고한 글 

https://dev-ahn.tistory.com/96

https://velog.io/@whwogur/파일-디스크립터File-descriptor-소켓-프로그래밍

 

 

'개발 노트' 카테고리의 다른 글

TCP handshake 그리고 커널 튜닝  (0) 2024.02.18
JSON  (0) 2023.07.15
[socket.io] redis 7v과 @socket.io/redis-adapter  (0) 2022.12.31

네트워크 수업 시간에 제일 먼저 배우게 되는 TCP 연결 방식인 3-way handshake 이다. 

고백하자면 나는 대학을 날로 먹어서 학교에서 예전에 배운 지식들이 요즘에서야 업무를 하며 새롭게 다가온다. 아! 이걸 이래서 배웠구나 깨달음을 얻는 재미가 쏠쏠하다.

 

우리 그룹은 몇 천 TPS의 트래픽을 제일 앞에서 받아내는 통신 미들웨어를 담당하는지라, 만들고 나서 서버 튜닝이 중요한 것 같다. 사실 작년에 엄청나게 얻어맞고 트래픽을 견디기 위해 다들 바쁘게 지냈지만 나는 그 아방하게 멀찍이 지켜만 보고 있었다. 이제라도 그 때 어떤걸 하셨는지, 왜 했는지 티켓을 보면서 복기하면서 vm의 커널 튜닝한 부분을 보고 있었는데 SYN backlog 값이 뭔지 찾아보다가 오랜만에 아는 개념이 나왔다. 

 

통신을 맺을 때, 신뢰성을 보장하기 위해 여러 장치가 있다. 서버는 소캣을 생성하고 바인딩 한 뒤에 클라이언트와 다음과 같이 연결을 맺게 된다. 그러나 실전으로 가니 밀리초 단위에서 이 과정은 전혀 매끄럽지 않다.

TCP handshake 과정을 살펴보면 다음과 같다. 

 

이때 네트워크 성능을 향상시키기 위해 튜닝 할 수 있는 부분은 외부로부터 패킷을 받는 용도의 버퍼 수를 튜닝하는 것이다. NIC max_backlog 에서 확인할 수 있다.

 

그렇게 받은 syn 패킷을 서버 소캣은 가지고 있는 두개의 큐로 받게 되는데,

  1. 일단 receive queue에 저장
  2. 프로세스가 이를 꺼내서 처리(syn-ack을 보내기)
  3. ACK 수신시까지 대기 (send queue) 시킨다.

순간적으로 인입되는 요청은 많은데 드랍(drop)되는 연결이 많다면 receive queue를 늘려줄 수 있다.

또한 send queue의 크기를 SYN backlog 값으로 늘려줄 수 있다. 이를 늘려주면 ACK 패킷을 기다릴 수 있는 대기열이 늘어나서 ack 수신이 느려졌을 때 손실되는 패킷을 줄일 수 있다.

 

클라이언트로부터 ACK 패킷을 받으면 accept queue 로 이동하게 되는데 프로세스에서 accept() 를 호출할 때 여기서 꺼낸다. accept queue의 크기가 바로 somaxconn 값이다.

 

+ 덧붙이기

지금가지 회사에서 실험(?)해본 결과 somaxconn, 커넥션 재사용과 관련된 커널 파라미터 튜닝이 성능을 개선하는데 가장 많은 영향을 줬다. 이를 통해 순간적으로 트래픽이 몰리면 서버가 연결을 맺을때 느려지는 것이 주요 원인임을 알게 되었고 이러한 커넥션 과정이 병목을 발생시키는 것이라고 생각했다. (테스트 할 서버가 통신 플랫폼 역할이라 연산량이 많지 않고 자원이 충분한 편이라..)

 

또 테스트 서버 보단 부하기의 커널 튜닝이 중요했는데 그 이유는 충분한 부하를 주는 것이 오히려 어려웠기 때문이다. 시간에 따른 latency를 보니 활성화된 워커스레드 수와 거의 비슷한 형상이었다(ㅠㅡㅠ). 부하를 거는게 이렇게 어려울 줄이야... jmeter 서버 6개로는 안된 것 같다.. 

 

-계속!-

 

참고한 글

https://recipes4dev.tistory.com/153

 

소켓 프로그래밍. (Socket Programming)

1. 소켓(Socket) 만약 네트워크와 관련된 프로젝트를 진행하면서, 사용자(User)의 관점이 아닌, 개발자(Developer)의 관점에서 네트워크를 다뤄본 경험이 있다면, "소켓(Socket)"이라는 용어가 아주 낯설

recipes4dev.tistory.com

https://brunch.co.kr/@growthminder/23

 

네트워크 커널 튜닝

할 수 있을 듯 하기 어려운 리눅스 커널 튜닝 | 대량의 트래픽이 발생할 때를 대비해야 한다면..? 신상품 공개, 콘서트 티켓 세일 등과 같은 이벤트가 있는 경우, 웹사이트에 순간적으로 엄청난

brunch.co.kr

 

'개발 노트' 카테고리의 다른 글

Socket : file descriptor, backlog  (0) 2024.02.18
JSON  (0) 2023.07.15
[socket.io] redis 7v과 @socket.io/redis-adapter  (0) 2022.12.31

0. 직장 선배 추천으로 가입한 독서 모임 첫 날

아 이제까지 내가 살았던 세계와 다른 곳에서 사는 사람들을 만난 기분이었다. 정말 지적인 유희를 즐기려면 저 정도까지의 교양이 있어야 하는구나, 나는 아직 교양의 기억도 모르고 있구나 생각이 들었다. 

인생에서 또 다른 길이 펼쳐진 느낌이었다. 내가 할 일은 길의 풍경과 향기를 즐기며 그 길을 달려가는 것. 설레이기도 하고 이상하기도 하다. 다만 그들이 진짜 똑똑한건지, 삶이 여유로워서 잠깐 멋지게 느껴진 것인지 아직은 혼란스럽다. 좀 더 오랜 시간을 보내보고 판단해도 늦지 않겠지.

1. PT 선생님이 가르쳐 준 것

피티 첫날에 선생님이 운동에 재능이 있다고 말했다. 26년 평생 운동을 좋아해 본 적 없는 나는 당연히 그냥 번지르르한 칭찬인 줄 알았는데, 그분이 정말 진지하게 말씀하시길 운동신경이 좋은 사람보다 그렇게 고통을 잘 참는 사람들이 나중에는 운동을 더 잘 한다고 한다. 한계가 와도 끝까지 하는 의지를 가진건 재능이라고. 운동하면서 그 사람이 어떤 삶을 사는지 알 수 있다고 했다.  나는 순간 머리를 한 대 얻어 맞은 듯, 그것이 삶을 관통하는 원리라는 생각이 들었다.

참고 하는 사람만이 결국 그 상태가 된다. 남들보다 효율이 좋아도 끝까지 하지 않으면.. 안된다. 

그 말이 너무 기억에 남아서 집에 와서 생각해보니, 정말 그게 내 재능인 것 같았다. 이렇다 특별한 것도, 탁월한 것도 아닌 나의 재능

난 미래를 상상하며 눈앞의 고통을 참아내는 걸 잘한다. 이제서야 나라는 사람의 장점을 하나 꼽을 수 있게 됐다. 조금 행복했다. 나 자신을 알아갈수록 나라는 사람의 속이 꽉 채워지는 기분이었다. 

2. 자기만의 장점이 있어야 안짤려

덕메 언니와 석촌에서 점심을 먹고 카페를 갔다. 오랜만에 봤는데 서로 자연스레 고민도 이야기하고 편했다.

회사 이야기를 하다보니 내 마음이 뾰족해져서, 회사 동료들에 대한 불평과 속앓이 했던 것을 털어놓게 됐다. 그런데 언니가 되게 당연했지만 내가 받아들이지 못하고 있었던 사실을 알려줬다. 모두 자기만의 장점이 있어야 직장에서 안짤리고(?) 살 수 있다고. 그건 꼭 일을 잘하는 능력을 의미하는게 아니고, 때론 내가 이해하지 못하는 행동을 할 수는 있지만 그건 그 사람 나름의 전략이기 때문에 (그리고 나와 다를 수 있기 때문에) 이해해야 한다는 말이었다. 대화를 하면서 지금 나의 상황을 멀리서 내려다본 입장을 듣는 느낌이었고, 그래서 마음이 누그러졌다.

맞아. 쟤네들도 만들고 싶은 거였다. 자신들이 이 자리를 차지하고 있어야 하는 이유를 말이다. 

그럼 나는 그런게 무엇이 있을까 생각했다. 나도 이렇다 할 확실한 이유는 아직 모르겠다. 이 지루하고 불쾌한 회사 생활에 어떤 목표가 생기는 기분이었다. 어느 집단에 있든, 내 존재의 이유를 확실히 만들어 놓는것이 좋을 것이다. 회사원으로서 개발자로서 그 답을 찾는 것이 내 커리어 하이의 출발점이 아닐까 싶다.

원래

JSON : object . 객체. 자바스크립트에서 사용하도록 만들어진 표준.

let a = {bar:"foo"}

JSON.stringify : 다른 언어에서도 사용할 수 있도록 데이터 교환 목적으로 바꾼 형태 --> json encoded 

{"bar":"foo"}

let tmp = '{"bar":"foo"}' --> JSON.parse()로 바꿀 수 있음

이때 두번째 인수로 [reviver] 의 함수로 특정 키에 대해 어떻게 처리해줄 것인지 정할 수 있음.

JSON.parse(tmp, (key,value)=>{
	if(key==Date){
    	return new Date(value)
    }
    return value;
})

socket.io 에서는 그냥 보내면 알아서 처리해준다.

Redis json

어떤 exception 상황에서 int 값을 string으로 변환해버린다. 

자세한 케이스는 확인 후 업데이트 예정!

'개발 노트' 카테고리의 다른 글

Socket : file descriptor, backlog  (0) 2024.02.18
TCP handshake 그리고 커널 튜닝  (0) 2024.02.18
[socket.io] redis 7v과 @socket.io/redis-adapter  (0) 2022.12.31

 
적당한 관심과 적당한 보상

나는 그냥 걔를 따뜻하게 해주고, 물을 주고, 햇빛을 쬐어주었을 뿐인데
들여다보지 않는 사이에 쑥 자란다.
 
물을 주면 화분의 자갈들 틈새로 맑은 소리가 나고,
썩은 곳을 잘라주면 어느샌가 아물어 초록빛을 띄고있다.
내가 지치든 힘들든, 슬프든 기쁘든 그냥 그 자리에서 조용히 자라난다.
 
영양이 부족하면 잎을 떨궈서 살아있고
물이 부족하면 잎을 말아서 살아있다.
 
나도 살면서 가끔 내 일부가 죽어도 다른 줄기를 계속 키워내면서 살아야지
 
식물을 기르는 일은 잎을 다 떨구는 것은 슬픈게 아니라 뿌리를 살리려 비상체제에 들어가는 것이라는 걸 깨닫게 되는 것이다. 그렇게 깨닫고는 혼자 위로를 받는다
그로인해 내 인생은 더 초록초록하고 풍성해지는 것이다.

 
 

redis 7v 에서 pub/sub 기능에 대한 클러스터 부하 분산을 지원하는 shared pub/sub 이 10월에 따끈따끈하게 릴리즈 되었다.

기존에는 클러스터를 구성하는 레디스 서버 어디에서나 sub, pub이 가능하게 하기 위해, publish 해서 메시를 전송할 경우 모든 노드에서 구독 여부를 확인해야 했다. 그래서 사실상 scalable 하지 않았는데 이제 샤드 채널이 슬롯 방식으로 정해진 메시지만 처리하게 개선했다고 한다.

Redis 7.0 and later features sharded pub/sub, in which shard channels are assigned to slots by the same algorithm used to assign keys to slots. A shard message must be sent to a node that owns the slot the shard channel is hashed to. The cluster makes sure the published shard messages are forwarded to all nodes in the shard, so clients can subscribe to a shard channel by connecting to either the master responsible for the slot, or to any of its replicas.

https://redis.io/docs/reference/cluster-spec/

 

Redis cluster specification

Detailed specification for Redis cluster

redis.io

추가적으로, socket.io 에서 인메모리 대신 레디스를 사용할 것인데 이 문서를 참고하면 좋을 듯.

https://socket.io/docs/v4/redis-adapter/

 

Redis adapter | Socket.IO

How it works

socket.io

참고한 자료 

 

'개발 노트' 카테고리의 다른 글

Socket : file descriptor, backlog  (0) 2024.02.18
TCP handshake 그리고 커널 튜닝  (0) 2024.02.18
JSON  (0) 2023.07.15

새 일기장이다. 그동안 네이버 블로그, 브런치, 벨로그를 전전하다 결국 티스토리로 넘어왔다. 사람이 한번 익숙해지면 잘 바꾸려고 하지 않게 되는 것 같다. 브런치와 벨로그는 정말귀엽고 세련됐지만 난 역시 이런 네이버 블로그스러운(?) UI가 편하다. 

사실 네이버 블로그 쓰고 싶었는데 정리하기 어려운 옛 유물이 너무 많아서 그냥 박물관으로 냅두고 여기로 왔다.

 

각설하고.. 2022년은 한 해가 거의 5년 같을 정도로 밋밋했던 내 삶에 순식간에 다양한 변화들이 일어났던 해였다.

2021년 회고에서는 내가 개발을 하면서 먹고 살 정도로 이 일을 좋아하는지 확신이 없고 불안하다고 적었었는데..

얼레벌레 계속 달리다보니 서비스도 하나 배포하고, 취업도 했다. 

그리고 그 서비스가 가입자 팔천명이 되어가며.. 날 도와줄 친구와 함께 다음 업데이트를 준비중이다.

주위 개발자에 비해 난 한없이 모자라고 게으른데(이제 좀 부지런해져라 제발!) 그걸 나도 안다. 그냥 나의 잔머리가 빛을 발한 것이라고 생각하고 있다.

이것도 능력이라면 능력이지만 솔직히 운이 많이 따르기도 했다. 그래서 매달 나가는 서버비에도 그냥 즐겁고 감사하기만 하다.

 

내년의 목표는 스페이스쉽을 안정적으로 운영해보기. 

일단 계획은 이렇다.

올해 상반기까지 음성 전송 기능을 추가하는 방향으로 기획을 했다. 근데 그 기능을 넣으려면 돈이 필요해서.. 서버비 모금이 먼저 돼야 한다.

그리고 앱은 안정적으로 트래픽을 견뎌야 하고, UI가 세련되게 나와야 한다. 

그것에 대해서 상현이(이번에 도와줄 프론트엔드 친구)와 긴급 회동을 가졌는데

결과물이 어떻게 될진 모르지만 일단 계획은 순조롭게 됐다.

부디 제발 기한 안에 끝낼 수 있기를...ㅜㅜ

 

그리고 직장에서는, 좀 건실한 신입사원1 정도의 몫을 해내는것이 목표다. 

하.. 왜 회사 얘기만 하면 기분이 안좋을까.

 

너무 해야 할 일 위주로 쓴 것 같은데 사실 진짜 내가 나에게 바라는 것은 인격적으로 더 나은 사람이 되는 것이다. 

긍정적으로 생각하고, 부정적인 생각은 적당히 끊고, 타인에게 너무 예민하게 굴지 않고, 감정을 잘 포장할 수 있는 민첩함이 있는 사람이 되고 싶다. 같이 있으면 편하고 즐거운 사람이 되고 싶다. 

+ Recent posts