안녕하세요? @asbear입니다. 스팀잇팀이 발표한내용을 엔지니어가 아닌 분들도 이해할 수 있도록 풀어 써보자 합니다. 최대한 쉽게 적어보려고하는데, 그게 항상 쉽지않더라구요. 질문은 항상 환영합니다.
스팀잇 성능개선 관련 공지는 이래 링크에서 보실 수 있습니다.
https://steemkr.com/kr/@asbear/performance-and-scalability-updates
여러분이 스팀잇을 사용할때, 웹 브라우저는 먼저 스팀잇 웹서버에 접속합니다. 스팀잇 웹서버는 인증 및 아주 중요한 기본 데이터와더불어 "틀" 만 제공합니다. 글이나 댓글 등의 실제 사용자가 필요로하는 정보는 웹서버가 보내주지 않습니다. 단지, 여러분에게 "어디가면 그 데이터가 있다"고 알려줍니다.
따라서, 스팀잇 웹사이트에 접속하고 기본적인것이 로딩되면, 여러분의 브라우저는 블록체인 내용을 읽을수있는 서버로 다시 접속합니다. 이를 steemd 라고 부릅니다. 실제로 글을 적고 송금을 하고 보팅을 하는 등의 이벤트는 모두 steemd 로 보내지며, 웹서버는 크게 관여하지 않습니다. 웹서버도 steemd에서 일부 정보를 읽어올테지만, 사용자와는 크게 상관 없지요.
즉, 사용자에 의해 발생되는 거의 모든 하중은 steemd가 견뎌야 합니다. 그런데 한대의 서버가 무제한의 하중을 견딜 수 있을까요? 답은 항상 "아니오" 입니다. 사용자가 늘어나면 대책이 필요합니다. 대책을 제대로 세우지 않으면 심각한 랙과 전송실패가 발생 하는것은 당연합니다. 스팀의 지금 문제는 웹서버의 문제가 아닙니다. steemd의 문제입니다. 웹서버는 항상 잘 동작하고 있습니다.
잘 알려진 기본적인 확장(scale out) 방법들이 있습니다. 스팀잇 팀은 이중 일부는 이미 적용 했고 일부는 반만 적용했고 나머지는 적용 예정인것 같습니다. 어떤 대책들이 있는지 한번 알아보겠습니다.
버티컬 스케일링이라고 불리는 방법인데, 서버의 사양을 늘리는것입니다. 메모리를 추가하고, 디스크를 빠른것으로 교체하고, CPU를 여러개 다는 등의 방법이지요. 당연히 성능은 향상 됩니다. 물론 초기에는 가장 확실한 방법이지만, 서버 사양을 업그레이드 하는것은 한계가 있습니다. 수퍼컴퓨터는 엄청나게 비싸며, 그렇다고 무제한 처리할수있는것도 아닙니다. 사실상 이 방법에 의존하는것은 불가능합니다.
가장 원초적인 방법은, 서버 여러대를 클러스터로 묶어서 돌아가면서 하중을 나눠갖는것입니다. 로드밸런싱이라고 합니다. 위의 그림에서 보시면 router에 서버 여러대를 붙여서 처리량을 향상 시킬수 있습니다. 브라우저에게 어떤 steemd에 접속하라고 이야기할수도 있고, 랜덤하게 접속하라고 할수도있고 아니면 라우터가 중간에서 결정해 줄수도있지요.
스팀잇은 이미 이 방법을 사용하고 있습니다. 아마도 여러대의 steemd를 설치하여 다양한 방법으로 로드를 분산 시키고 있을것입니다. 하지만 그게 지금 한계에 도달 한 것이지요. 원인은 여러가지가 있겠지요.
일반적으로 이 방법은 확장성을 이야기할때 잘 언급되지 않습니다. 왜냐하면 이는 개발하는 시점에서 이미 고민이 끝나있어야 하기 때문입니다. 다중처리 디자인을 처음부터 확장성 있게 했어야 하는것이지, 이부분을 확장성 없게 만들고 나서 나중에 개선하는것은 상식에서 상당이 벗어나는 일입니다. 아주 오래된 프로그램도 아니고 신기술이라고 불리는 프로그램에선 특히나 이례적인 일입니다.
이번에 공개된 개선안에서 언급된 AppBase가 이중 하나입니다. steemd가 매우 비효율적으로 처리를 하고 있기 때문에 이를 개선하겠다는 말입니다.어찌 되었든 이제라도 개선한다고 하니 다행입니다.
불필요하게 너무 많은 데이터를 주고받는다던지, 불필요한 절차로인해 딜레익 생긴다던지 하면 사용자가 느끼는 체감 성능은 떨어집니다. 그렇다면 이것을 개선하는것도 즉각적인 효과를 줄 수 있지요. 스팀잇 노드들은 서로 같은 데이터를 가지고 있어야 합니다. 그런데 위에 그림에서 보셨듯이, 여러대의 steemd가 있으면, 사용자가 접속한 노드에만 댓글이 남게 되겠죠. 이 댓글은 빠르게 다른 steemd 노드로 전파되어야 합니다.
위에 그림은 가장 단순한 동기화알고리즘을 사용할 경우 발생하는 통신 경우수를 보여줍니다. 4대인경우 4대 모두가 같은 데이터를 갖기 위해서는 최소 6번의 통신이 이뤄져야 하죠. (실제로는 이보다 훨씬 효율적이겠지만 최악의 경우를 설명드리는 것입니다.)
만일 모든 steemd가 같은지역 같은 서버실에 있다면 이정도 통신은 아무것도 아닐것입니다. 하지만 전세계에 퍼져있는 steemd를 놓고 보면 어떨까요?
거미줄처럼 엮인 목잡한 전송이, 대륙을 건너며 이뤄지면서 감당할수없을만큼 동기화에 지연이 발생할것입니다. 이를 해결하는 한가지 방법은, 계층구조로 묶는것이지요. tree 라던지 graph 등으로 묶어서, 대표 노드를 스스로 선정하고, 그놈들을 통해서 동기화 기준을 맞추는것입니다. 아마도 이번에 p2p 프로토콜을 개선한다는게 이 알고리듬을 개선하는 것으로 보입니다. 추측이긴합니다만..
여러분의 브라우저는 steemd와 1:1 연결을 맺고 명령을 계속 주고 받습니다. 당연히 steemd 가 매우 바빠질수 밖에없습니다. 그리고 만약 여러분이 새로고침을 끊임없이 한다고 칩시다. 브라우저는 steemd에 접속해서 계속 "거의" 같은 데이터를 가져옵니다. steemd는 똑같은일을 반복할 수 밖에 없습니다. 이런 문제를 개선하기 위해서 사용되는기술이 백엔드 캐쉬입니다. 기술에따라 다르지만 memcache라고 많이 부릅니다.
그래서 어떻게 개선하느냐, 단순한 절차를 예로 들어 봅시다.
여기서 (3)번은 정말 매번 해야하는것일까요? 블록체인 스캔하여 담는 것들이 엄청나게 헤비한 작업이라면, 매번 하는것은 큰 부담이지요. 그러면 이걸 매번 안해도 되는 방법이 있을까요? 그게 바로 캐싱입니다.
"asbear가 최근글을 요구한다" 라는 액션에 대해 결과를 힘겹게 준비했으면, 그걸 재사용 하면 되는겁니다. 다서 블록체인을 스캔할 필요 없이 그냥 전에 스캔해서 만들어놓은 데이터를 보내주면 어마어마하게 효율성이 증가하지요.
asbear가 아니라 그냥 "최근글을 가져온다"라면 어떨까요? 예를들면 kr-new를 읽는 경우라던지 말이지요. 그러면 모든사용자의 요청에 똑같이 대답할수 있지요. 실제 블록체인 스캐닝은 딱 한번만 하고 말이죠.
이번에 스팀잇 팀에서 발표한 Jussi 라는것이 이 역할을 하는것입니다. 아래와 같이 말이죠.
브라우저든 뭐든 steemd에 직접 붙어서 데이터를 가져오는것이 아니라 Jussi에 붙어서 가져오는겁니다. Jussi는 이전에 오고간 요청들과 결과값을 기억해 뒀다가, 사용자가 비슷한 요청을 할 때 steemd를 건들지 않고 바로 돌려주면 되지요. 이로인해 많은 성능 향상을 꾀할 수 있습니다.
또 한가지는, 사용자 각자가 steemd에 접속하지 않고 Jussi가 혼자 접속하기때문에 steemd가 훨씬 한가해 집니다. 동시에 쏟아져들어오는 접속 요청이나 데이터 요청에 시달릴 일이 적어지고, Jussi 만 상대하면 되거든요.
아마 이런 질문이 있을텐데요,
"데이터를 새로 가져오지 않으면, 내가 방금 새로 단 댓글은 남들이 못보는것인가요?"
그렇기때문에 캐쉬는 짧게는 몇초 길게는 몇십초정도만 유지되고 새로 갱신되어야 합니다. 그러나 여전히 초당 100건의 요청이 들어오는 서버라고만 생각해도 엄청난 연산을 줄일 수 있는 것이죠. 어느정도의 데이터 일관성 (consistancy라는용어인데 한글로는 잘..) 을 필요로하느냐에 따라 이 캐쉬 유지시간이 달라지는데, SNS같은경우 댓글을 1초안에 보든 10초후에 보든 별 상관 없기떄문에 길어도 됩니다. 그리고 덕분에 성능 향상 효과는 더 확실하죠.
스팀잇팀의 업데이트를 더 자세히 알고싶은 분이 계신것 같아서 정리해보았습니다. 확실한것은, 스팀잇팀의 업데이트는 확장성 및 성능 향상의 기본을 따라가고 있다는 것입니다. 아직 서버에 적용하지 않은것 같은데, 실제로 적용되면 지금보다 많이 빨라질것이라고 생각합니다. 다만 말씀드렸드시, consistency가 낮아지므로 정보 갱신이 늦어지는 현상이 예상됩니다. 혹시 더 궁금하신 부분이 있으시면 답글 주세요.
감사합니다.