업력 9년인지라 레거시 코드가 꽤(?) 있다.

특히 웹서버의 접근 로그를 단일 서버(PostgreSQL)에 모아 분석한 결과를 웹으로 보여 주는 시스템이 있다.

실시간 분석 시스템은 아니고 작게는 분단위 길게는 일, 월단위 분석이다.

준 실시간성은 EFK(Elasticsearch, Fluentd, Kibana)를 이용해 3개월치를 분석하고 있어 서로를 보완한다.

1년전에 시스템이 느려지고, 저장 용량도 부족해 하드웨어를 마이그레이션한 적이 있다.

전체적인 스케일업이였는데 특히 S모사의 SATA SSD 512GB 4개를 묶어서 사용하다가 더 좋은 INTEL® SSD DC P3500 SERIES으로 4대나 묶었다.

하지만 1년만에 생각보다 로그가 많이 쌓여 대략 39억건의 row가 되었다. 다시 한번 마이그레이션을 해야 할 때가 되었다.어째야 할까?

  1. 내가 그 시스템 담당자는 아니니 모른척한다. 에반, 데빈 미안해요?!
  2. 또 다시 스케일업을 한다. 그래 더 좋은 장비를.. 쇼핑을 시작해 볼까!
  3. 이것저것 튜닝을 해본다. 차지하고 있는 index를 좀 줄이면 더 버틸 수 있겠지.
  4. AWS EMR Spark + Zepplin, 음… 나쁘진 않지만…
  5. AWS Athena.. 아 QuickSight까지 해놓고 샘플 보여주고 기존 레거시는? 안되면 JDBC로.. 역시나.. 누가 JDBC랩핑 해놓은 python 패키지도 있다.
  6. 이참에 GCP, Bigquery!

그래 Athena!

5번이 제일 재미있어 보이니 5번.

이유는 얼마든지 만들 수 있지.

  1. 데이터를 S3에 저장. 해봐야겠지만 거의 무한대란 이야기겠지.
  2. 관리형 서비스라 서버 불 필요.
  3. 스캔한 데이터랑 저장한 데이터 기준으로 비용 지불.
  4. Presto 기본 표준 SQL 실행.
  5. Parquet 같은 컬럼 베이스 형식 지원.  비용 감소.
  6. 나름 빠름.
  7. SQL 결과가 저장됨.
  8. JDBC 드라이버 지원, SQL Workbench/J나 Datagrip으로도 연결!

어떻게 만들어 볼까?

제대로 하려면 ORC나 Parquet으로 한번 변환해야겠네.

변환은 Spark으로 많이 하네? 아니 EMR 안올릴려고 Athena를 쓰려고 했던건데!

이럴바엔 IDC에 Spark클러스터를 만들까? 이렇게까지는 하고 싶지 않은데.

뭐 없나?! Apache Arrow. 게다가 파이썬 구현체도 있다.

Pandas로 읽어 arrow table을 만들고 Parquet 포맷으로 저장을 하면 된다.

대략 이런 모양새

import pandas as pd
import pyarrow as pa
from pyarrow import parquet as pq


df = pd.DataFrame(logs)
tb = pa.Table.from_pandas(df)
pq.write_table(tb, 'access.log.parquet')

속도가 더 필요하면 fastparquet을 쓰면 되겠다. 하지만 이건 패스.

기본 압축이 Snappy이지만 GZIP, brotli도 가능하고 압축을 사용하지 않아도된다.

Ahtena는 Snappy, Zlib, LZO, GZIP을 지원하니 조금 더 압축을 원하면 GZIP을 사용하면 되겠다.

시험삼아 21MB 짜리를 변환했더니 47KB가 되었다. 기본 Snappy로 압축했는데도 괜찮아 보인다.

66.55.3.64 - - [30/May/2017:15:47:28 +0900] "DELETE /app/main/posts HTTP/1.0" 200 4993 "http://warner.info/register.asp" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/5331 (KHTML, like Gecko) Chrome/13.0.847.0 Safari/5331"
40.152.29.205 - - [30/May/2017:15:48:38 +0900] "GET /list HTTP/1.0" 404 4982 "http://medina-caldwell.com/" "Mozilla/5.0 (Windows NT 5.01; en-US; rv:1.9.2.20) Gecko/2012-10-30 01:54:53 Firefox/3.6.19"
99.158.57.24 - - [30/May/2017:15:51:07 +0900] "GET /app/main/posts HTTP/1.0" 200 5041 "http://www.west-martinez.com/main/post.html" "Mozilla/5.0 (Macintosh; PPC Mac OS X 10_8_2) AppleWebKit/5361 (KHTML, like Gecko) Chrome/14.0.844.0 Safari/5361"
195.67.221.131 - - [30/May/2017:15:52:27 +0900] "GET /wp-admin HTTP/1.0" 200 4986 "http://lopez-glass.com/search/" "Mozilla/5.0 (Windows; U; Windows 95) AppleWebKit/531.7.6 (KHTML, like Gecko) Version/5.0.3 Safari/531.7.6"
15.46.27.141 - - [30/May/2017:15:56:43 +0900] "GET /apps/cart.jsp?appID=2548 HTTP/1.0" 200 4935 "http://whitaker.org/search.htm" "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_7_9; rv:1.9.4.20) Gecko/2011-10-21 19:57:56 Firefox/8.0"
173.224.181.156 - - [30/May/2017:15:59:36 +0900] "GET /list HTTP/1.0" 200 5032 "http://obrien.info/" "Mozilla/5.0 (X11; Linux x86_64; rv:1.9.5.20) Gecko/2015-02-16 00:50:42 Firefox/11.0"
171.191.97.102 - - [30/May/2017:16:00:17 +0900] "PUT /wp-content HTTP/1.0" 200 5000 "http://www.lucero.biz/app/index/" "Mozilla/5.0 (iPod; U; CPU iPhone OS 3_1 like Mac OS X; en-US) AppleWebKit/533.42.5 (KHTML, like Gecko) Version/3.0.5 Mobile/8B113 Safari/6533.42.5"
18.59.225.171 - - [30/May/2017:16:05:00 +0900] "GET /wp-content HTTP/1.0" 200 5038 "http://williams.org/index/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2; rv:1.9.3.20) Gecko/2015-12-29 10:02:59 Firefox/3.6.16"
251.20.43.250 - - [30/May/2017:16:08:35 +0900] "GET /app/main/posts HTTP/1.0" 200 5023 "http://perez-gillespie.com/" "Mozilla/5.0 (Windows NT 5.01) AppleWebKit/5311 (KHTML, like Gecko) Chrome/14.0.857.0 Safari/5311"
97.112.197.19 - - [30/May/2017:16:09:18 +0900] "PUT /list HTTP/1.0" 200 5022 "http://mendez.net/posts/blog/search/terms.asp" "Mozilla/5.0 (Windows NT 5.01; it-IT; rv:1.9.0.20) Gecko/2010-08-20 16:41:00 Firefox/3.6.19"

위 로그가 아래 처럼 변했다.

00000000: 5041 5231 1504 15d0 1615 c60b 4c15 ea02  PAR1........L...
00000010: 1504 1200 00a8 0b08 7813 0005 0100 840d  ........x.......
00000020: 0800 a70d 0800 c70d 0800 d50d 0800 800d  ................
00000030: 0800 9f0d 0800 710d 0800 850d 0800 d20d  ......q.........
00000040: 0800 8b0d 0800 ab0d 0800 9c0d 0800 160d  ................
00000050: 0800 810d 0800 a60d 0800 650d 0800 b80d  ..........e....
00000060: 0800 af0d 0800 6d0d 0800 3a0d 0800 750d  ......m...:...u.
00000070: 0800 3c0d 0800 bb0d 0800 b00d 0804 1914  ..<.............
00000080: 05c7 0400 c10d 1000 6c0d 0800 510d 0800  ........l...Q...
00000090: 820d 0800 930d 0800 d90d 0800 970d 0800  ................
000000a0: 870d 0800 a10d 0800 ba0d 0800 670d 0800  ............g...
000000b0: 880d 0800 830d 0800 bf0d 0800 5f0d 0800  ............_...
000000c0: 860d 0800 440d 0800 a40d 0800 d10d 0800  ....D...........
000000d0: 250d a000 e60d 1000 620d 0800 b50d 0800  %.......b.......
000000e0: 480d 0800 340d 0800 770d 0800 3f0d 0800  H...4...w...?...
000000f0: 320d 0800 8c0d 0800 7f0d 0800 590d 0800  2...........Y...
00000100: 7c0d 0800 8e0d 0800 c30d 0800 5e0d 0800  |...........^...
...
00000300: 2c15 9e08 1504 1506 1506 1c18 0825 1400  ,............%..
00000310: 0000 0000 0018 0808 1300 0000 0000 0016  ................
00000320: 0000 0000 9a04 f419 0203 0000 009e 0801  ................
00000330: 087f 0001 0203 0405 0607 0809 0a0b 0c0d  ................
00000340: 0e0f 1011 1213 1415 1617 1819 081a 1b06  ................
00000350: 1c1d 1e1f 2021 2200 0723 0808 2425 2627  .... !"..#..$%&'
00000360: 2829 2a0a 0f2b 022c 1d27 2d2e 2f30 261d  ()*..+.,.'-./0&.
00000370: 3132 3334 0535 3637 3839 3a08 2b0c 3b15  1234.56789:.+.;.
00000380: 3c25 3d3e 063f 2129 4041 4236 430a 4405  <%=>.?!)@AB6C.D.
00000390: 4520 1246 4748 4914 4a15 2136 4b4c 4d01  E .FGHI.J.!6KLM.
000003a0: 034e 2b4f 0250 0c23 5105 0829 5253 3106  .N+O.P.#Q..)RS1.
000003b0: 5455 5657 5859 4a5a 0b5b 0042 5c5d 2608  TUVWXYJZ.[.B\]&.
000003c0: 160e 235e 5f0e 0e0f 3060 6162 5363 5f64  ..#^_...0`abSc_d