OpenTSDB를 사용하고 있는 모니터링 장비를 개발하고 있다.


모니터링하는 전체 장비 이름(hostname) 목록을 얻어 API에서 suggest할 때 바로 장비 이름이 나오고


"서비스 이름-장비 이름" 매핑에 대한 값을 아주 신속하게 처리할 수 있도록 해야 하는 일이 있었다.


15분짜리 배치 잡을 1초의 배치 잡으로 바꾼 practice를 소개하고자 한다.




OpenTSDB의 아키텍처는 Hbase 기반이고 TSD라는 데몬을 사용하고 있다. 

(특히 downsampling이라는 훌륭한 개념을 탑재하고 있다는 장점을 갖고 있다.  )




1. 문제 해결 #1

15분짜리 배치에서는 OpenTSDB의 suggest API를 통째로 읽어오는 일을 하는 데 10분의 시간이 소요되었다.


http://opentsdb.net/docs/build/html/api_http/suggest.html api는 오래전에 만들어진 플랫폼이라.. pagination이 없다.


이 부분을 OpenTSDB가 아니라 HBase Client Libarary를 사용해 직접 읽고 ES에 저장했다. 


http://opentsdb.net/docs/build/html/user_guide/backends/hbase.html#uid-table-schema


  • metrics for mapping metric names to UIDs
  • tagk for mapping tag names to UIDs
  • tagv for mapping tag values to UIDs.

Within the id column family is a row with a single byte key of \x00



그리고 매번 모두 읽지 않도록 zookeeper에 읽고 난 뒤의 정보를 zk에 저장했다.



2. 문제 해결 #2

opentsdb에 서비스 이름-호스트 이름 매핑 구조를 알 수 있지만, 모든 정보를 다 읽을 수는 없다.


"서비스이름-호스트 이름" 매핑 DB 정보를 따로 읽는 부분이 있었고 소요시간은 2분 30초였다.


이를 모두 DB 커넥션에 매번 읽는 구조가 아닌 Connection Pool을 사용했고 역시 테이블을 사용할 때 읽고 난 뒤의 index를 zookeeper에 저장했다. 


그랬더니. 2분 30초 배치가 0.3초로 줄어들었다.



증분 배치의 개념은 "증분 백업" 개념과 동일하다.





<결론>

문제 해결 #1,#2 보면 Divide & Conquor, 증분(increment) 방식을 사용했다.

(모든 데이터를 읽는 게 최대한 회피한다!!)



그리고 zk에 저장된 데이터에 실제 처리 시간을 작성해 시간이 밀리거나 동작이 안되면 jenkins에서 모니터링 잡에서 노티가 오도록 했다.



chronos를 이용해 30초마다 배치 잡을 돌리는데. 1초만에 배치 잡 동작이 완료되었다.. 







Posted by 김용환 '김용환'


7-8년 전 쯤인가... configuration server를 개발한 적이 있다.


DB 아이디와 패스워드를 암호화하여 소스 리파지토리 서버, 노트북, 물리 장비가 해킹되더라도 아이디/패스워드가 노출되지 않도록.. configuration server를 개발했다.


빌드 툴, 빌드/배포 서버에서 ant/maven 플러그인으로 configuration server에 접속해 암호화된 정보를 읽도록 하고 파일을 교체하도록 했다.  또한 개인정보보호법에 따라 3개월마다 무조건 DBA가 id와 패스워드를 변경하게 하고 DBA가 책임을 지도록 했다.





요즘은 어떨까?



https://12factor.net/ko/config 도 이런 문맥에서 얘기하고 있다. 


애플리케이션의 설정 배포 (스테이징, 프로덕션, 개발 환경 등) 마다 달라질 수 있는 모든 것들입니다. 설정에는 다음이 포함됩니다.

  • 데이터베이스, memcached 등 백엔드 서비스들의 리소스 핸들
  • Amazon S3 이나 트위터 등의 외부 서비스 인증 정보
  • 배포된 호스트의 정규화된 호스트 이름(canonical hostname)처럼 각 배포마다 달라지는 값

애플리케이션은 종종 설정을 상수로 코드에 저장합니다. 이것은 Twelve-Factor를 위반하며, Twelve-Factor는 설정을 코드에서 엄격하게 분리하는 것을 요구합니다. 설정은 배치마다 크게 다르지만, 코드는 그렇지 않습니다.

애플리케이션의 모든 설정이 정상적으로 코드 바깥으로 분리되어 있는지 확인할 수 있는 간단한 테스트는 어떠한 인증정보도 유출시키지 않고 코드베이스가 지금 당장 오픈 소스가 될 수 있는지 확인하는 것입니다.


ansible(https://docs.ansible.com/ansible/2.4/vault.html)의 경우는 암호 파일을 두어 배포를 가능하게 해두었다. 

Posted by 김용환 '김용환'

 

수십 대의 mysql DB를 MMM 솔루션을 이용해서 데이터를 저장한 사례. 단순한 정보이지만 양이 많은 구조이다.

 

Spring의  AbstractRoutingDataSource 클래스와 ThreadLocal를 이용한 코드를 사용한다.

http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/

 

connection을 모두 맺는 것이 아니라 필요할 때마다 맺는 구조라서, 속도 이슈가 문제가 될 수 있다면, Spring의 AbstractRoutingDataSource 클래스 사용 대신 Mybatis에서 처음부터 connection을 모두 맺는 방식을 사용할 수 있다.

 

Spring AOP와 Mybatis의 SessionFactory와 SqlSession을 이용해서 구현해서 Mybatis mapper 를 그대로 쓰도록 해서 개발 환경과 릴리즈 환경시 코드 변화가 최소화되도록 했다. datasource를 DBCP 로 설정해서 connection을 maxActive 설정을 크게 잡았다. 이렇게 해서 SessionFactory, SqlSession 을 datasource (DBCP)를 꺼내 bottleneck이 없게, mapper를 쉽게 쓰는 구조로 사용했다. 

 

Spring AOP와 AbstractRoutingDataSource 구현 예제

http://sidnancy.kr/archives/216#codesyntax_5

 

음.. 이렇게 구현하니 NOSQL 도 안 부럽다. 계속 확장성있는 구조라면 NOSQL이 낫지만, 어느 정도 정해진 스케일이라면, mysql 과 MMM-solution, java 로 multi db를 접근할 수 있을 것 같다.

실제 구현해보니. 생각보다 쓸만하다는 생각이 들었다.

 

AbstractRouting 설명 잘 나온 글.

http://dev.anyframejava.org/docs/anyframe/plugin/optional/routingdatasource/1.0.0/reference/htmlsingle/routingdatasource.html

https://groups.google.com/group/ksug/browse_thread/thread/f527ac148023ac3d

http://forum.springsource.org/showthread.php?104767-MyBatis-AbstractRoutingDataSource

Posted by 김용환 '김용환'

Evernote logo


에버노트는 스마트폰, PC를 상관하지 않고 어디서든 노트를 쓰고, 읽고, 쓴 글을 검색할 수 있는 노트 어플리케이션 서비스를 제공하고 있습니다. 또한 로컬에도 저장을 할 수도 있습니다.



에버노트는 컴퓨터 공학의 선구자였던 "베네바 부시"의 memex를 생각하면 만든 것은 아니었을 까요?



사용자 삽입 이d미지



 베네바 부시는 인간이 가지고 있는 정보를 간편히 저장하고 빠르게 검색할 수 있는 소형의 시스템이 필요하다고 했습니다. 그래서 많은 사람들은 웹은 베네바 부시가 생각했던 부산물이었다고 부산물이라고 생각했습니다.

인간이라는 것이 나라고 생각한다면, 내가 가지고 있는 (노트)정보를 간편히 저장하고 빠르게 검새할 수 있는 소형의 시스템은 에버노트가 될 수도 있겠죠?


ㅎ이 생각은 제가 아니라 이미 있는 얘기입니다.  ㅎ

(http://blog.jonudell.net/2008/04/07/a-conversation-with-phil-libin-about-evernotes-new-memex/)



이제 본론으로 들어가도록 하겠습니다.


이 에버노트에 대한 아키텍처를 지난 5월에 자신의 기업 블로그(http://blog.evernote.com/tech/2011/05/17/architectural-digest/#)를 공유하였습니다.






큰 그림으로 보이는 이 한장의 그림이 아키텍쳐입니다.

서버와 통신하기위해서는 방화벽 - LB(로드 밸런스) 스위치 - 웹 서버 를 거쳐야 합니다.


방화벽은 Vyatta 제품을 쓰고 있습니다. 트래픽과 보안을 위해서 올해 1월에 추가했습니다. 이 제품은 외부와 통신하기 위해서 BGP(외부 게이트웨이와 통신할 수 있는 프로토콜)/Level3/NTT 을 지원하고 있습니다. AX2500 이라는 장비를 써서 failover에 대응하고 있습니다. 추후, N+1 redudancy(시스템 가용성을 위한 내용, 여러 장비가 동시에 사용할 수 있도록 하는 것을 의미, master/slave와 대비하는 용어)를 적용할 예정입니다.


A10 스위치 장비의 SSL 가속화 기능을 이용하여 비싼 SSL 소요 비용을 최소화하여 성능을 높였습니다. 즉 SSL 통신 때문에 앞단 어플리케이션 서버가 부하를 최대한 줄였습니다. 


웹 서버는 Thrift 기반의 Service API를 이용하여 하루에 최고 약 250 mbps로 들어오는 트래픽의 150만 Https 요청을 처리하고 있습니다. 계산해보니 초당 17 tps 정도를 카버할 수 있는 용량입니다. 정확하지는 않지만, A10  스위치 장비에 thrift를 올린 것 같기도 하구요. SSL 가속기가 달린 스위치로부터 필터받은 요청을 thrift에서 처리한 것으로 생각하고 있습니다.


VM 을 이용해서 서버를 운영하고 있습니다. 

server farm을 shads라 불리우는데, 한 개의 shard는 십만명의 user를 처리할 수 있습니다. 다.따라서, 9백만 사용자의 90개의 shards로 운영할 수 있습니다. 2개의 쿼드코어 칩을 가진 슈퍼마이크로 (http://www.supermicro.com/index.cfm)에 Segate RAID 장비 사용, 여기에 2개의 Xen VM을 설치하여 운영하고 있습니다.


서버 이중화를 설명드리겠습니다. 한대의 VM(primary)에 WAS를 구성하고, 다른 한대의 VM(secondary) 은 앞에 설치된 WAS를 DBRD 솔루션을 이용해서 replication하도록 하고, Heartbeat를 이용해서 failover처리가 되도록 하였습니다. 


DBRD가 생소한 내용일텐데, 아래 그림을 보시면 이해가 좀 편합니다. 일종의 Replication 솔루션이라고 보시면 됩니다.

  



NoteStore에 사용하는 WAS와 DB 구성방식은 다음과 같습니다. 

Debian + Java 6 + Tomcat + Hibernate + Ehcache +  Stripes + GWT + MySQL (for metadata) + hierarchical local file systems (for file data).


현재의 90개 이상의 shard가 있습니다.  하나의 shard 에 특정 사용자가 바인딩됩니다. 그리고, 사용자 정보가 하나의 shard에 저장되면, 다른 shard와는 통신하지는 않습니다. 따라서, load balancer의 thrift에서는 사용자 정보를 판별하는 로직이 들어가 있습니다. 


사용자 정보와 데이터를 mysql(UserStore라 불리움) 에 저장됩니다. mysql은 백업을 위해서 RAID 미러링과 DBRM 솔루션을 이용합니다. 

mysql은 in-memory 기반이며,  id, md5 passwod, shard id로 데이터필드를 구성하였습니다. 


에버노트는 AIR(Advanced Imaging and Recognition)라고 하는 이미지에서 검색하는 pool 서버가 있습니다. 이 서버는 자체 개발한 솔루션이며, 핸드라이팅같은 거 검색하는데 사용하고 있습니다. 

총 8코어짜리 28대의 서버가 있고, 윈도우와 데비안 OS를 사용중이며, 올해 말까지 윈도우 서버를 빼서 모두 데비안 OS로 바꿀 예정입니다. 


기타 서버를 말씀드리겠습니다. 

SMTP 서버는 Debian 위에  sendmail 어플인 postfix(http://www.postfix.org/)와 Dwarf 네트웍 AS 서버(http://www.gnome.sk/Dwarf/dwarf.html)를 기반으로 Java mailer 이용해서 사용하고 있습니다. 

트위터 게이트웨이는 twitter4j기반으로 in-house용으로 개발된 것을 쓰고 있습니다.

모니터링 솔루션은 Zabbix, Opsview, AlertSite을 이용하고 있으며,  환경설정파일 배포는 puppet(http://www.puppetlabs.com/puppet/introduction/)을 이용하고 있습니다.


Reference

http://highscalability.com/blog/2011/5/23/evernote-architecture-9-million-users-and-150-million-reques.html

http://blog.evernote.com/tech/2011/05/17/architectural-digest/#


Posted by 김용환 '김용환'

Open API 공부

Architecture 2010.10.27 15:49



Open api 보안 강화를 위해서 사용하는 방법

1. ip 또는 계정 인증
2. HMAC
3. Oauth


Open API 싸이트

네이버 - http://dev.naver.com/openapi/

네이트 -http://devsquare.nate.com/openApi/index 
           http://devsquare.nate.com/nateConnect/nateAuthAPIDevGuide

다음 - http://dna.daum.net/DNALatte/openapi/about

스프링노트 - http://api.springnote.com/


<HMAC 정보>
URL정보에 hmac을 이용하여 client lib를 전달함. 여러 언어별 지원 필요.

hmac이란
http://en.wikipedia.org/wiki/HMAC
http://sybil.tistory.com/tag/hmac
http://www.alicerock.com/??page=230


<Oauth 정보>
인증 id가 아닌 token으로 인증하는 방식. REST 방식으로 지원. 내부적으로 HMAC 이용

http://en.wikipedia.org/wiki/OAuth
http://dev.springnote.com/pages/1083108
http://www.ibm.com/developerworks/kr/library/wa-oauth1/

Posted by 김용환 '김용환'

신규 웹 서비스를 런치할 때 웹 서버 갯수를 산출할 때,
보통은 기존의 웹 서비스를 근거로 파악합니다.

PV, UV, 게임포털이면 게임동접수를 근거로 합니다.
PV(UV, 게임동접수)가 이정도되니, 웹 서버는 이정도면 되겠다고 합니다.
이는 빠른 의사결정을 할 수는 있으나, SE 에게 논리적인 설득을 주기가 어렵습니다.

그래서, 저는 항상 주장하는 것이 있습니다. 아직까지 회사에서
성능 테스트입니다.

-       Real DB를 바라보고, 실제 호출될 서버의 70% 요청량을 차지할 수 있는 Action을 테스트한 결과 (TPS)를 가지고 확인해야 합니다.




서버 산출에 영향을 주는 Factors는 다음과 같습니다.
1) URL (Action)
2) DB Query 개수 및 소요시간
(DB Query와 연관 있는 DB 개수)

서버 산출의 근거가 되는 Factor는 다음과 같습니다.
1) CPU
2) Load Average
3) Response Time

Cpu처리량은 항상 20%미만으로 처리될 수 있도록 가이드합니다. Restart를 할때, 부하를 받더라도 다른 서버가 이어줄 수 있고, 점검 또는 게임서버의 문제에 대해서 웹서버를 보호줄 수 있는 수준이라 생각됩니다.

장점은 논리적인 이해가 바탕이 되므로, SE가 수긍하고 진행이 됩니다.
단점은 시간이 많이 소요됩니다..

아직 회사에서 이렇게 적용하지 못하고 있지만, 조만간에 이것을 할 수 있는 분위기, 프로세스, 툴을 제공한다면 충분히 가능할 것이라 생각한다.

'Architecture' 카테고리의 다른 글

Evernote 서비스 아키텍처 공유  (0) 2011.05.31
Open API 공부  (0) 2010.10.27
웹 서버 갯수 산출 근거  (0) 2010.02.17
모니터링 솔루션 개발 완료  (0) 2009.08.06
티스토리 시스템 장애 관련  (0) 2009.04.17
Map Reduce  (2) 2008.05.14
Posted by 김용환 '김용환'


모니터링 솔루션 개발이 완료가 되었다.
Multi-thread pattern을 사용하여 한번에 수백개의 쓰레드가 동시에 사용되어 데이터 수집 및 경고를 할 수 있는 시스템을 만들었다.
시스템쪽에서 바라보는 시스템 모니터링을 넘어서서, 웹 어플리케이션 개념에서 접근한 모니터링 솔루션이라 할 수 있겠다. 

1. 요구사항
(1) 수집할 모든 프로젝트의 정보를 한 번에 볼 수 있도록 한다.
웹 어플리케이션의 상태를 One Page Monitoring 이라 하는 상황판에서 볼 수 있도록 하는 것이다. 이것만 있으면, Restart, Warning, Error에 대해서 상황 파악이 가능하다

(2) 수집 정보
시스템, Apache, Tomcat, DB, 정보 이렇게 나눌 수 있다.
-- 시스템 정보는 아주 세부적이지는 않다. 예를 들어 cpu의 경우는 io나 nice 값은 보여주지 않는다. idle 값을 100에서 뺀 값으로 보여준다. 간단한 수치만 보여준다. 그래야 사용자들이 판단할 수 있었다.
 loadavg, cpu, io, network, 파일 정보등을 보여준다. 이 떄 모든 명령어는 /proc 데이터를 활용한다.
-- Tomcat
메모리, 쓰레드 정보, 톰캣내 부하 정보를 보여준다. 참조용이라 할 수 있겠다. Outofmemory 정보를 위한 것이다. 사실 JMX 를 통해서 보다 높은 수준의 메모리 쓰레드 정보를 볼 수 있지만, 장애 때를 제외하고는 특별히 수집해도 의미가 없다. 어차피 장애나 튜닝은 특별한 시점에 하기 떄문에 General하게 쓰일 모니터링 솔루션에서는 쓰이지 않을 것이다.
-- Apache 정보
Apche의 server-status 정보를 보고, 정보를 저장하도록 한다.
쓰레드 개수, 초당 요청량을 보면서 deadlock 이나 부하 측정이 가능하다. 하지만 역시 참조용..
-- DB
원했던 방향은 SQL Query가 얼마나 속도가 걸리는지 지금 어떤 SQL을 날리는지 보는 것이었으나, 부하 및 개발 시간이 있어서 간단하게 사용.
웹 서버가 리스타트해서 얼마나 많은 SQL query를 날렸는지 count와 시간만을 group by 해서 보여준다.


2. 동작
(1) 수집이 가능한 서버에 대해서 빠르고 정확하게 정보를 수집한다. RMI 기반인 JMX의 Event-Listener 개념을 사용했다. 부하를 최대한 쓰지 않는 구조이다. Connection은 한번만 그리고, 그 Connection은 오직 리스타트나 종료일 때만 끊어진다. 그리고, 데이터 수집 정보는 Policy에 따라서 알려주도록 한다.
모니터링 솔루션은 웹 서버에 몇분마다 이런 정보를 원한다라는 Policy(정책)을 알려주고 웹 서버는 그 정보를 모니터링 솔루션으로 그 정보를 보내주도록 한다.

(2) 동작여부를 확인한다.
L7 체크를 하고 있는 터라 이 부분은 시스템 담당자와 대화할 수 있는 먼가가 필요했다.
그리고, 톰캣은 현재 물리적인 서버에 cpu갯수만큼 띄워져 있다. cpu가 2개이면 2개의 톰캣 인스턴스가..
cpu가 8개이면 8개의 톰캣 인스터를 띄워서 잘 동작시키고 있어서 단순한 설정으로 할 수 없었기에 Customizing이 되도록 하였다.
그리고, 많은 서버, 약2000대 정보의 상태 모니터링을 체크를 할 수 있도록 개발되었다.

(3) 경고 시스템 개발
정보를 통해서 장애가 생기기전 약 5~10분 정도 그 예후를 판별할 수 있고, 사람이 장애라 확인할 때까지 15분정도 소요되는 것에 비해서 빠르게 알아낼 수 있음을 발견했고, 그 부분을 추가했다.
실제, 웹서버가 장애가 나기 전에 어떤 특정 값을 넘어서면, 경고를 알려줄 수 있도록 했다.
이 부분은 아차피, 톰캣, 시스템, DB 수집 정보를 기간으로 판단할 수 있다.

(4) Customized UI 및 One Page Monitoring
웹 개발자는 자신이 원하는 정보를 얻고 싶어하지 자신과 관계없는 프로젝트는 보지 않는다. 따라서 사용자가 미리 수집중인 웹 서버들을 선택해서 그 정보만 볼 수 있게 했다. 그 때 uptime 정보, Restart 여부 정보를 여러 세부 지표와 함께 보여줌으로서 본인위주의 UI를 넣도록 했다.
또한, 시스템 담당자및 관리자는 현재 서비스의 장애상황을 신속히 볼 수 있기 때문에 적절한 판단을 내릴 수 UI가 필요했다. 바로 한페이지 모니터링 UI이다. 한 화면에 모든 웹 서버들을 볼 수 있고, 상황을 표시해 주도록 되어 있다. 그 정보를 선택하면, 수집해 놓은 수집정보를 Refresh 없이 볼 수 있도록 처리했다.

3. 좀더 해야할 일
더 해야할 일은 가용성, 쓰루풋부분이었다.
가용성은 간단하게 말하면, 얼마나 서비스가 잘 response를 보내주었는지 백분율로 나타내준 것으로서, 어떤 서비스가 1월 1일부터 지금까지 한번도 장애가 안났으면 100%로 해서 성과로 보여줄 수 있도록 하는 것이다.
이 가용성을 근거로 서비스의 안정성을 수치로 나타낼 수 있는데, 이는 개발이 되어 있지만, UI로 만들지 않았다. 기존 개발자들이 힘들것 같다..

성능 부분으로는 java instrument를 이용하여 실시간 정보를 바탕으로 성능 저하 및 병목 부분을 발견하도록 하는 부분이었다. 이를 통해서 어느 코드나 어느 쿼리에서 병목인지 확인하고 보려고 했었다.
하지만, 시간상... 이 부분은 나중에 개발할 예정이다. 바빠서... 이유도 있지만.
그리고, JDk7 이 나오면, 훨씬 잘 디자인된 JVM Tool interface와 instrument로 개발이 용이해지기 때문이다.
사라질 api로 개발하는 것은 무리일 것이라 생각된다.


4. 서버
웹 서버 1대, DB 2대 이렇게 구성한 상태이다. DB는 replication 때문에 한 거구.
웹 서버는 부하를 테스트 해보고 싶었다. 현재 약 500대 돌리고 있는데, cpu 5%정도이다. 아직 한참 돌려도 된다. 멀티 쓰레드는 정말 활용할 만한 가치가 있었다..

'Architecture' 카테고리의 다른 글

Open API 공부  (0) 2010.10.27
웹 서버 갯수 산출 근거  (0) 2010.02.17
모니터링 솔루션 개발 완료  (0) 2009.08.06
티스토리 시스템 장애 관련  (0) 2009.04.17
Map Reduce  (2) 2008.05.14
네트워크 프로그래밍시 유의사항  (0) 2006.07.20
Posted by 김용환 '김용환'
출처  : http://notice.tistory.com/
  • 4월 11일 토요일 새벽 장애 발생 (41분간) : 갑작스러운 'Forbidden' 이라는 페이지가 발생한 것은 블로거 분께서도 지적해 주신바 있지만 새벽 DB 점검 작업을 마치고 서비스를 정상화하기 위한 최종 작업을 하는 과정에서 실수가 발생하였기 때문입니다. 서비스 장애가 발생하고 난 후, 마지막 작업 과정에서 실수가 있었다는 것을 확인하였으며 장애 발생 후 42분 후 정상화되었습니다. 다시 한번 실수로 인하여 피해를 드리게 된 점 진심으로 사과의 말씀드립니다. 개발팀에서 최종 배포 작업 시에 더 꼼꼼하게 확인 목록을 작성하여 실수가 일어나지 않도록 프로세스 및 모니터링 시스템을 강화해 나갈 예정입니다.
  • 4월 12일 일요일 오후 및 자정 장애 발생 (10분간) : 갑작스럽게 DB 부하가 발생하면서 일시적으로 페이지 로딩을 하는 과정에서 실패가 발생한 것으로 파악되었습니다. 다만 11일 정상화 작업을 진행하는 도중 안내 페이지를 기존 버전으로 돌려놓지 않아 10일 점검 작업 메시지가 노출되었는데, 잘못된 안내 메시지로 인하여 혼란을 겪으셨을 여러분들께 사과의 말씀드립니다.
  • 4월 13일 월요일 오전 장애 발생 (10분간) : 일요일에 발생하였던 유형과 유사한 패턴의 DB 부하로 인하여 일시적으로 페이지 로딩 실패하는 건 수가 갑자기 증가하여 공지 블로그를 비롯하여 많은 개별 블로그 접속이 원활하지 않은 문제가 발생하였습니다. 이에 따라 DB 부하를 초래하는 모든 요소들을 모두 모니터링하였으며, 일부 직접적인 문제가 될 수 있는 부분들을 제거함에 따라 정상화 되었습니다.
  • 4월 16일 오후 DNS 서버 장애 (약 50분간): 일부 블로그 이용자의 지역 환경에 따른 접속 문제로 인하여 DNS 서버를 확장하는 과정에서 일부 블로거분들께서 DNS 서버에 접근이 어려워 블로그에 따라 접속이 되었다가 되지 않았다가 하는 모습을 보였습니다. DNS 서버 복구를 통하여 해결하였습니다.
  • 4월 17일 새벽 권한 설정 장애 (약 1시간) : 팀블로그 및 몇 가지 권한설정과 관련하여 정책을 정리하고 배포하는 과정에서 일부 오류가 발생함에 따라 공지블로그 및 일부 블로그의 비밀댓글이 로그인을 한 상태인 다른 티스토리 이용자들에게 보였습니다. 고객센터 및 공지의 신고에 따라 오류 처리가 되었사오나, 이 오류로 인하여 피해를 입으신 분들이 없도록 더욱 주의를 기울이도록 하겠습니다.



이렇게 공지가 올라왔다. 이렇게 투명하게 공지를 올려준 티스토리 담당자 여러분께 깊은 감동을 우선 보내고 싶다. 이렇게 투명하게 쓰는 것이 쉽지는 않았으리라.
과거 내 경험을 가지고 이런 문제를 어떻게 해결해보았나.. 생각해 본다.



1. Forbidden 문제
이 문제는 apache 설정과 밀접한 연관이 있다. 보통 403 apache error를 의미하는데, 바로 Forbidden이 나왔다는 것은 아파치 설정에 문제가 있음을 의미한다. 보통 Alias를 주어서 아파치 디폴트 페이지 (Forbidden)이 나오지 않도록 하고, 일반적인 접근 에러 페이지를 나오게 하도록 하는 것이 좋다.
개발자가 아파치단을 막으면서 배포단계에서 문제가 있지 않나 싶다. 또한 40분 넘게 넘게 나왔다는 것은 개발자가 테스트를 안했다는 뜻이 된다. 이건 결국 모니터링과 밀접한 연관이 있다.
이 문제를 해결하기 위해서는 아파치 설정에 대해서 Source Repository를 두어서 따로 관리하고, 소스-배포-실배포될 서버의 설정이 모두 같이 되도록 하는 것이 좋다. 그래야 일반적으로 실수가 적게 할 수 있다.

실수를 하더라도 모니터링이 된다면, 바로 수정을 하고, 40분을 시간을 짧게 할 수 있다.
* 모니터링
모니터링 서버의 중요성은 바로 이럴 때 드러난다. 먼저 문제를 빨리 발견하게 한다. 일반적으로 토파즈나 내부 모니터링 서비스가 각 서브 도메인별로 모니터링을 하도록 한다. 또는 내부 개발용으로 만든 웹 어플리케이션 모니터링 서버가 있으면 참 좋다.
apache, tomcat, 기대값 충족 필터링 이렇게 단계별로 테스트하는 것이 좋다.
한편 네트웍단에서 L7 체크을 이용하면, 충분히 이런 문제를 해결할 수도 있다.


2. DB 부하
서비스가 인기를 끌면서 데이터량은 많아지면서 많은 웹 서버들이 DB에 붙게 된다. 과거에는 한두개 DB로는 붙을 수 있었지만, 집중화되면서 DB의 성능을 저하시킨다.
 특히 blob과 같은 데이터들은  DB속도를 느리게 한다. 이때 너무 많은 DB connection을 한두개의 DB와 붙지 않도록 한다. oracle 10g의 경우는 한 connection당 9~10mb를 차지하기 때문에 connection 비용을 비싸게 지불해야 한다.
또한 DB의 특정 파라미터는 문제를 또한 야기시킬 수 있다. DB를 업그레이드 하거나 특정 IDC로 이전하면서 OS 버젼업을 하면서 DB 설정 파라미터에 따라서 (아주 사소하더라도) 크게 영향을 미칠 수 있다.
그리고, 제일 중요한 것은 배치성 쿼리이다. 이 배치성 쿼리가 사실 제일 큰 문제를 야기시킬 수 있다. 특히 티스토리의 경우는 어드민에서 유입 경로등 다양한 정보를 보여주는 부분이 있어서 이런 배치성이 문제가 없도록 해야 한다.
만약 특정 시간마다 DB cpu 증가나 장애가 나타나면, 거의 90%다.
쓸 때없이 full indexing하는 쿼리나 indexing이 없는 테이블들.. 그리고 쓸 때없이 돌아가는 배치들을 다 정리해야 한다..
배치 한녀석 킬했더니. DB가 정상화된 적이 있다. ㅡ.ㅡ;


3. DNS 관리
시스템 이나 인프라 관련 담당자들이 자주 실수하는 부분이기도 하다.
DNS 설정시 간단하게 리눅스 데몬형태로 설정파일을 가지고 돌리는데. 이 도메인을 제대로 syntax checking이 되지 않는다. 처음엔 잘 돌아가나 싶더니. 갑자기 서비스 장애가 되서 보았더니. 도메인을 제대로 못적었다는.. DNS 서버에 도메인 추가할 때는 pair로 하는 게 가장 좋다..
결정적인 버그인데. 요즘은 이걸 어떻게 하나 모르겠다.이런 문제를 쉽게 해결하기 위해서는 서비스쪽 도메인과 개별 서버의 도메인은 분류를 해야한다. 서버 증설시 분류된 DNS 서버를 사용해서 서비스와 개별 도메인 서비스 도메인을 분류해서 문제가 없도록 해야 한다.
또한 DNS 알고리즘도 영향을 미칠 수 있으니. 최대한 L4(vip)로 돌리는 것이 좋다. 역시 문제가 생기면 l4체크 및 l7체크를 통해서 잘못된 서버를 빨리 찾아낼 수 있고, 복구가 가능하다.


4. 서비스 배포하기 전
반드시 beta 테스트를 진행하도록 한다. 아무리 좋은 서비스라도 반드시 QA를 통해서 서비스가 진행되도록 해야한다. 능력없는 개발자의 무모한 자신감은 결국은 신뢰를 깨게 된다. 근거없는 자신감은 망신의 지름길이다.
반드시 QA와의 협력, 어떤 서비스를 오픈하는지를 QA와 알려주고, 리얼 서비스가 닫히더라도 사용자가 볼 수 없는 beta나 개별 서비스 도메인으로 접근하여 꼼꼼히 테스트하는 것이 좋다.
잘못하면?? 다음 메일 꼴 난다.







Posted by 김용환 '김용환'

Map Reduce

Architecture 2008.05.14 21:25

구글의 검색 엔진의 기본 핵심이다.

 

functional langaue인 lisp에 영향을 받은것으로 보이며, 간단 명료하게 병렬 배취기능형태로 제공된 것으로 보인다.

 

홈페이지 및 출처는 다음과 같다.

 

http://labs.google.com/papers/mapreduce.html

 

 MapReduce: Simplified Data Processing on Large Clusters
Jeffrey Dean and Sanjay Ghemawat

 

 

아주 간단한 input/output 프로그래밍 api를 가지고 있다.

 

 map (in_key, in_value) -> list(out_key, intermediate_value)

reduce (out_key, list(intermediate_value)) -> list(out_value)

 

이런식으로 구글 소스 트리에 사용되는데. 계속 사용되고 있다..

 

 

 

실행에 대한 개념이다.  중간값이 만들어지고, 그룹된 Key에 의해서 그룹되어서 결과를 나오게 한다.

 

 

 

 

 

 

이를 이용해서 병렬처리는 다음과 하게 되어 있다.

 

 

좀더 쉽게 설명되면 다음과 같다. (출처 : http://www.joinc.co.kr/modules/moniwiki/wiki.php/JCvs/Search/Document/ManReduce?action=download&value=mapreduce.png)


 

 

자연스럽게 시간에 대한 pipe개념도 추가되어 있다.

 

또한 재실행하는 문제에 대한 문제까지도 고려하고 있다.

 

기본 데이터가 없어서 성능쪽은 비교대상이 없기 때문에 쉽게 말하기는 어려운 것 같다.

 

관련한 논문은 다음과 같다.

  • Programming model inspired by functional language primitives
  • Partitioning/shuffling similar to many large-scale sorting systems
    • NOW-Sort ['97]
  • Re-execution for fault tolerance
    • BAD-FS ['04] and TACC ['97]
  • Locality optimization has parallels with Active Disks/Diamond work
    • Active Disks ['01], Diamond ['04]
  • Backup tasks similar to Eager Scheduling in Charlotte system
    • Charlotte ['96]
  • Dynamic load balancing solves similar problem as River's distributed queues
    • River ['99]

 

결론은 다음과 같이 내었는데..

 

 . MapReduce has proven to be a useful abstraction
  • Greatly simplifies large-scale computations at Google
  • Fun to use: focus on problem, let library deal w/ messy details
  •  

     

    추상적인 모델로서 증명되었고, 구글에서 큰 스케일의 계산을 심플화했고, 문제에 포커스를 가지도록 하고, 복잡한 것은 그냥 라이브러리에서 실행할 수 있도록 하였습니다.

     

     

    참조자료.

    http://ypshin.com/2690309

    http://www.joinc.co.kr/modules/moniwiki/wiki.php/man/12/MapReduce

     

     

    개인적으로 병렬처리를 하는 백엔드 worker, batch 작업에 써먹을 수 있는 형태로 보인다. 간략함으로서 사용자에게 편의를 제공하는 것으로 보인다.

     

     

    Hadoop 은 바로 이 MapReduce를 구현하였다. http://hadoop.apache.org/core/

    분산 파일 시스템 Hadoop가 MapReduce 를 구현했다고 보니. 많이 놀랬다.

     

     

     

     

    자세한 것은 다음에.. ㅋ

     

    참조 자료

    http://hadoop.apache.org/core/docs/current/ Hadoop 위키 페이지

    http://freesearch.pe.kr/893 속도 테스트

     

     

    Posted by 김용환 '김용환'

    네트웍 프로그램시 주의할 사항 (buggy 코드를 없애자!!)

    1. 기반 프레임웍 개발시 유의할 점
    +-----+
    |  A  |
    +-----+
    |  B  |
    +-----+
    |  C  |
    +-----+

    C라고 하는 모듈(또는 클래스)를 B라는 모듈로 Wrapping하고, B라는 모듈을 A모듈로 Wrapping하는 아키텍쳐가 있다고 가정하자.

    이 때 유의사항은 A가 C의 기능을 사용하지 않아도 될 정도로 B의 API가 General해야 한다.

    하지만, B의 API가 General하게 디자인이 되지 않았을 경우 (일명 찜찜하게 설계된 경우 문제가 생길 소지가 있다.)
    예를 들자면, C는 Telnet통신을 위한 모듈이다. Telnet은 read,write가 sync가 되지 않기 까닭에 쓰레드를 이용하여 write와 read를 따로 쓰이도록 한다.

    이때 B는 이런 Telnet 통신에 대한 연결과 read, write에 대해서 general하게 디자인을 해놨다. A는 C를 생각하지 않아도 B의 API만을 가지고, Telnet 통신을 할 수 있도록 디자인이 되는 걸 전제로 B의 API를 이용하여 코딩을 하게 된다
    문제는 바로 B의 API의 기능이 잘못될 경우이다.

    먼저 예로 들었던 Telnet인 경우에 B모듈에 close(), connect(), connect(String ip, int port) 라는 Telnet 통신 프로토콜이 있다고 가정하자.
    이때, close()는 read,write에 대한 thread를 종료하는 것이며, 두 connect는 read, write에 대한 thread를 생성하고 read,write를 받아들일 수 있도록 준비가 되는 코드가 만들어져야 한다.

    즉, B의 일부 API인 connect()와 connect(String ip, int port)는 기본적인 기능은 같아야 불구하고도 같지않을때, buggy한 코드를 생성할 수 있다.



    2. 노드간 통신

    네트웍 프로그램에서 가장 중요한 것은 노드와 노드간의 연결성이다.

    때에 따라서 항상 지속적으로 연결이 보장되어야 하는 경우도 있을 수 있고, 필요할 때마가 연결을 하는 경우가 있다.
    필요할 때마다 연결을 하는 경우는 보통 문제가 명확한 반면, 항상 연결이 보장되어야 하는 경우의 통신 프로그래밍을 하는 경우는 상당히(개인적인 체험에서 나온 말이다.) 힘들 수도 있다.

    low-level 통신인 경우에는 sync코드 와 crc외 각종 FEC등을 사용하여 Qos를 보장해야 하는 반면, high-level인 경우는 Qos를 보장한다고 가정하고, 여러 상황에 대한 대비책(?)을 강구해야 한다.

    예를 들어, 계속 연결을 보장해야 하는 통신 노드간의 에러 상황에 대해서 처리하는 방법은 다음이 좋을 수도 있다.
    더 좋은 방법이 있는지는 모르겠다.
              <--------
       A                      B
    (client)    -------->    (server)


    A노드의 클라이언트 프로세스가 B노드의 서버 프로세스가 제대로 동작되는지 확인하는 api를 잘 생각해 보자.

    1. A노드에 B의 API인 ping 명령를 요청하여 B가 현재 제대로 동작 중인지를 확인한다.
      좀 더 확실하기 위해서 ping 명령어를 통해서 네트웍의 상황을 체크할 수도 있다.

    2. 만약 B의 운영체제가 문제가 있어서 응답을 못할 수도 있고, B노드에서 동작중인 프로세스가 종료되는 경우가 있다.
      이 경우는 1번에서 요청한 ping명령에 대해서 무응답이 되기 까닭에 A와 B의 연결이 끊어졌으면 내버려 두고, A와 B의 연결이 되어 있는 경우는 socket 연결을 끊고, 다시 연결하도록 한다.

    3. A노드는 B노드와 통신에 대한 effect를 고려해 플래그를 설정하여 A노드를 통해서 B노드에 요청해야 하는 상황에 대비하여 불필요한 경우에 대해서 접속을 시도 하지 않음으로서, 처리 속도를 높이고 리소스를 낭비하는 일이 없도록 한다.

    4. 2번 마지막에서 A노드에서 B노드로 다시 연결을 요청하고 성공할 경우에 대해서 1번에서처럼 A노드의 클라이언트 프로세스가 B노드의 서버프로세스가 동작이 제대로 될 수 있는지 확인하는 ping 요청을 하도록 한다



    3. 기반 운영체제

    항상 endian를 조심하자. 운영체제마다 big-endian, middle-endian, little-endian을 사용한다.
    Posted by 김용환 '김용환'