์ข์ ํ๊ณผ ๋ฉ๋ชจ์ฅ, ๋พฐ์กฑํ ์ฐํ, ํธ์ํ ๋ง์ฐ์ค, ์ฌ๋ถ์ ์ ์ ๋ช ๊ฐ ๋ฑ ํ์ํ ์์ ๊ฒ๋ค์ด ๋ชจ๋ ์ค๋น๋์ด ์์ผ๋ฉด ์ ๋ง ์ข์ต๋๋ค. ์ด๋ฌํ ๋์ ๋์ง ์๋ ๊ฒ๋ค์ ๊ด์ฌ์ ๋์ง ๋ชปํ์ง๋ง ์ถ์ ํธ์ํจ์ ๋ํด์ค๋๋ค. ๊ธด ์คํฌ๋ฆฐ์ท, ์ฌ์ง ํฌ๊ธฐ ์ถ์, ๊ฐ์ธ ์ฌ์ ๊ณ์ฐ, ์ฌ์ , ๋ฒ์ญ๊ธฐ, ๋ณํ๊ธฐ ๋ฑ ๋ค์ํ ๋ชจ๋ฐ์ผ ๋ฐ ๋ฐ์คํฌํฑ ์ ํ๋ฆฌ์ผ์ด์
์์๋ ๋ง์ฐฌ๊ฐ์ง์
๋๋ค. ํน์ ๊ฐ๊ณ ๊ณ์๋์?
๊ณต์ฐ์ฃผ์๊ฐ ๋๋ํ์ต๋๋ค, ๋์ง๋ค.
๊ทธ๋ ๊ทธ๋ฐ ์ฌ๋์ ๋๋ค. XNUMX ๋์ฉ VPS
์ฐ๋ฆฌ๋ ์ ๋ ดํ VPS๊ฐ ํ์ํ์ง ์์ ์ด์ ์ ๋ํด 3~4๋ ์ ์ ์ด ๊ฒฝ์์ฌ์ ์ฌ์ฉ์์ ๋ง์ ๊ธฐ์ฌ๋ฅผ ์ฝ์์ต๋๋ค. ๊ทธ๋ ๋ค๋ฉด "30ํ๋์ฉ" VPS๋ ์์ํ ๋ง์ผํ ์ด์๊ณ ์ ์์ ์ธ ์ ๋ฌด ๊ธฐํ๋ฅผ ์ ๊ณตํ ์ ์์์ต๋๋ค. ๊ทธ๋ฌ๋ ์๋๊ฐ ๋ณํ๊ณ ๊ฐ์ ๋ฆฌ์์ค ๋น์ฉ์ด ์ ์ ๋ฎ์์ง๊ณ ์์ผ๋ฉฐ ํ ๋ฌ์ XNUMX๋ฃจ๋ธ์ ๋น์ฉ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ ์๋น์ค๋ฅผ ์ ๊ณตํ ์ค๋น๊ฐ ๋์ด ์์ต๋๋ค.
- ํ๋ก์ธ์: Intel Xeon 2GHz(1์ฝ์ด)
- Linux ์์คํ (Debian, Ubuntu, CentOS ์ค์์ ์ ํ ๊ฐ๋ฅ)
- ์ ์ฉ IPv1 ์ฃผ์ 4๊ฐ
- ๋น ๋ฅธ ์ํฐํ๋ผ์ด์ฆ๊ธ SSD ๋๋ผ์ด๋ธ์ 10GB์ ๋ฐ์ดํฐ ์ ์ฅ ๊ณต๊ฐ ์ ๊ณต
- ๋จ: 512MB
- ์ด๋น ์ฒญ๊ตฌ
- ๋ฌด์ ํ ํธ๋ํฝ
๊ด์ธ์๋ ์ถ๊ฐ ๊ธฐ์ ์ ํ ์ฌํญ์ด ์ ์ฉ๋ฉ๋๋ค.
์ด ๊ฐ์ ์๋ฒ๋ ๋๊ตฌ์๊ฒ ์ ํฉํฉ๋๊น? ์ด๋ณด์, ์ด์ฑ ํฌ, ์๋ จ๋ ๊ฐ๋ฐ์, DIY ํฌ, ์ฌ์ง์ด ์ผ๋ถ ํ์ฌ๊น์ง ๊ฑฐ์ ๋ชจ๋ ์ฌ๋์ด ๊ทธ๋ ์ต๋๋ค.
์ด VPS๋ ์ด๋์ ์ ํฉํฉ๋๊น?
์ฐ๋ฆฌ๋ Habr์ ๋ ์๋ค์ด ์ด ๊ตฌ์ฑ์ ์ฌ์ฉํ๋ ์์ ๋ง์ ๋ฐฉ๋ฒ์ ํ์คํ ์ฐพ์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง๋ง, ์ฐ๋ฆฌ๋ ์ฐ๋ฆฌ๊ฐ ์ ํํ ์์ด๋์ด๋ฅผ ์์งํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค. ๋๊ตฐ๊ฐ๊ฐ ํ์ํ์ง๋ง ๋จ์๋ค์ด ๋ชจ๋ฅธ๋ค๋ฉด ์ด๋ป๊ฒ ๋ ๊น์?
- ๊ฐ๋จํ ์น์ฌ์ดํธ, ํฌํธํด๋ฆฌ์ค, ์ด๋ ฅ์ ๋ฑ์ ์ฝ๋๋ก ๋ฐฐ์นํ์ธ์. ๋ฌผ๋ก ๊ทํ๊ฐ ์ง์ ๋์์ธํ ์น์ฌ์ดํธ๋ ๊ณ ์ฉ์ฃผ์๊ฒ ๊ธ์ ์ ์ธ ์ธ์์ ์ค๋๋ค. VPS์ ๋ฐฐ์นํ๊ณ ์ผ๋ฐ ํธ์คํ ์ ๊ณต์ ์ฒด์ ์ง์์ด ์๋ ์ฌ์ดํธ์ ๋ณด์๊ณผ ์์ ์ฑ์ ์ง์ ์ฑ ์์ ธ์ผ ํฉ๋๋ค.
- ๊ต์ก ๋ชฉ์ ์ผ๋ก VPS๋ฅผ ์ฌ์ฉํ์ญ์์ค. ํ๋ก์ ํธ๋ฅผ ํธ์คํ ํ๊ณ , ์๋ฒ ๋ฐ ์๋ฒ ์ด์ ์ฒด์ ์ ๊ธฐ๋ฅ์ ์ฐ๊ตฌํ๊ณ , DNS๋ฅผ ์คํํ๊ณ , ์๊ท๋ชจ ๊ต์ก ์ฌ์ดํธ๋ฅผ ์์ ํ์ญ์์ค.
- ์ ํ ํต์ ์ฉ. ๋๋ก๋ ๊ฐ์ธ ๊ธฐ์ ๊ฐ, ํ๋ฆฌ๋์ ๋๋ ์์ฃผ ์์ ํ์ฌ๊ฐ IP ํ ๋ ํฌ๋๋ฅผ ์ ์คํ ํ์๋ก ํ๋๋ฐ ๋ฐ๋ก ์ด ํ ๋ ํฌ๋ ์ด์์๋ ๋งค์ฐ ํ์์ค๋ฝ์ต๋๋ค. ๊ฐ๋จํฉ๋๋ค. ์๋ฒ๋ฅผ ๊ฐ์ ธ์ค๊ณ , IP โโ์ ํ ํต์ ์ฌ์ ์๋ก๋ถํฐ ๋ฒํธ๋ฅผ ๊ตฌ๋งคํ๊ณ , ๊ฐ์ PBX๋ฅผ ์ค์ ํ๊ณ (ํ์ํ ๊ฒฝ์ฐ) ๋ด๋ถ ๋ฒํธ๋ฅผ ์์ฑํฉ๋๋ค. ์ ๊ฐ ํจ๊ณผ๋ ์์ฒญ๋ฉ๋๋ค.
- ์๋ฒ๋ฅผ ์ฌ์ฉํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ ํ ์คํธํ์ธ์.
- ์ค๋งํธ ํ ์์คํ ์ผ์์ ๋ฐ์ดํฐ๋ฅผ ์ ์ดํ๊ณ ์์งํ๋ ๋ฑ DIY ์คํ์ ์๋ฒ๋ฅผ ์ฌ์ฉํ์ญ์์ค.
- ์ด๋ฅผ ์ฌ์ฉํ๋ ํน์ดํ ๋ฐฉ๋ฒ์ ๊ฐ์ ๊ฑฐ๋์ ๊ฑฐ๋ ๋ณด์กฐ์์ธ ๊ฑฐ๋ ๋ก๋ด์ ์๋ฒ์ ๋ฐฐ์นํ๋ ๊ฒ์ ๋๋ค. ๊ทํ๋ ์๋ฒ์ ์์ ์ฑ๊ณผ ๋ณด์์ ๋ํด ์ ์ ์ผ๋ก ์ฑ ์์ ์ง๊ฒ ๋๋ฉฐ, ์ด๋ ๊ทํ๊ฐ ์ฃผ์ ์์ฅ ๊ฑฐ๋๋ฅผ ์ํ ํต์ ๋ ๋๊ตฌ๋ฅผ ๋ฐ๊ฒ ๋๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ๊ธ์์, ํน์ ๊ด์ฌ์๊ฑฐ๋ ๊ณํํ๊ณ ๊ณ์๋ค๋ฉด :)
๊ธฐ์ ์์ญ์๋ ์ด๋ฌํ VPS์ ๋ํ ์์ฉ ํ๋ก๊ทธ๋จ์ด ์์ต๋๋ค. ์ด๋ฏธ ์ธ๊ธํ ์ ํ ์๋น์ค ์ธ์๋ ๋ช ๊ฐ์ง ํฅ๋ฏธ๋ก์ด ๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด:
- ์๋ฅผ ๋ค์ด FTP๋ฅผ ์ฌ์ฉํ์ฌ ๋ฉ๋ฆฌ ๋จ์ด์ ธ ์๋ ์ง์์ด ์ก์ธ์คํ ์ ์๋ ์๊ท๋ชจ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๋ณด๋ฅผ ๋ฐฐ์นํฉ๋๋ค. ์ด๋ฅผ ํตํด ์๋ก์ด ๋ถ์, ์์ ์ฌ์์ ์ํ ์ ๋ฐ์ดํธ๋ ๊ตฌ์ฑ, ํ๋ ์ ํ ์ด์ ๋ฑ์ ๋งค์ฐ ๋น ๋ฅด๊ฒ ๊ตํํ ์ ์์ต๋๋ค.
- ์ํํธ์จ์ด๋ ๋ฏธ๋์ด๋ฅผ ์์ฐํ๊ธฐ ์ํด ์ฌ์ฉ์๋ ํด๋ผ์ด์ธํธ์๊ฒ ์์ ์ก์ธ์ค ๊ถํ์ ๋ถ์ฌํฉ๋๋ค.
30๋ฃจ๋ธ์ VPS ํ ์คํธ ๋๋ผ์ด๋ธ - ์๋ฃ๋์์ต๋๋ค
30 ๋ฃจ๋ธ์ ๋๋ฌด ์ ๊ธฐ ๋๋ฌธ์ ์ง๋ถํ๊ณ ํ ์คํธํ๊ธฐ ์ํด ์นด๋๋ฅผ ๊บผ๋ด๊ณ ์ถ์ง๋ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ๋๋ก๋ ๋๋ฌด ๊ฒ์ผ๋ฅด์ง๋ง ์ด๋ฒ์๋ ๋น์ ์ ์ํด ๋ชจ๋ ๊ฒ์ ํด๋์ต๋๋ค. ์๋ฒ๋ฅผ ์ ํฌ์ ํฌ์ ํ๊ธฐ ์ ์ ์ฐ๋ฆฌ๋ ๋ชจ๋ ์ธ๋ถ ์ฌํญ์ ํ์ธํ๊ณ ์ด ๊ฐ๊ฒฉ์ผ๋ก ์๋ฒ๊ฐ ๋ฌด์์ ํ ์ ์๋์ง ์์๋ณด๊ธฐ ์ํด ํ ์คํธ๋ฅผ ์ค์ํ์ต๋๋ค. ๋ ํฅ๋ฏธ๋กญ๊ฒ ๋ง๋ค๊ธฐ ์ํด ๊ทน๋จ์ ์ธ ์์๋ฅผ ์ถ๊ฐํ๊ณ ๋ฐ๋์ ๋ถํ๊ฐ ์ฐ๋ฆฌ๊ฐ ์ค์ ํ ๊ฐ์ ์ด๊ณผํ๋ ๊ฒฝ์ฐ ์ด ๊ตฌ์ฑ์ด ์ด๋ป๊ฒ ์๋ํ๋์ง ํ์ธํ์ต๋๋ค.
ํธ์คํธ๋ ํ๋ก์ธ์์์ ๋ค์ํ ์์ ์ ์ํํ๊ณ ๋์คํฌ ํ์ ์์คํ ์ ์ ๊ทน์ ์ผ๋ก ์ฌ์ฉํ๋ ์ฌ๋ฌ ๊ฐ์ ๋จธ์ ์ ๋ถํ๋ฅผ ๋ฐ๊ณ ์์์ต๋๋ค. ๋ชฉํ๋ ๋์ ๋ฐ๋์ ๋ฐฐ์น์ ์ ํฌ์ ๋น์ทํ๊ฑฐ๋ ๋ ํฐ ๋ถํ๋ฅผ ์๋ฎฌ๋ ์ด์ ํ๋ ๊ฒ์ ๋๋ค.
์ง์์ ์ธ ๋ก๋ ์ธ์๋ sysbench๋ฅผ ์ฌ์ฉํ์ฌ ํฉ์ฑ ๋ฉํธ๋ฆญ์ ์์งํ๋ ๊ฐ์ ๋จธ์ 3๋(ํ๊ท ๊ฒฐ๊ณผ๋ ์๋์ ๋์ ์์)์ ์ถ๊ฐ ๋ก๋๋ฅผ ์์ฑํ๋ ๊ฐ์ ๋จธ์ 50๋๋ฅผ ์ค์นํ์ต๋๋ค. ๋ชจ๋ ํ ์คํธ ๊ฐ์ ๋จธ์ ์ ๋์ผํ ๊ตฌ์ฑ(์ฝ์ด 1๊ฐ, RAM 512GB, SSD 10GB)์ ๊ฐ์ก๊ณ ํ์ค debian 9.6 ์ด๋ฏธ์ง๊ฐ RUVDS ์ฌ์ฉ์์๊ฒ ์ ๊ณต๋๋ ์ด์ ์ฒด์ ๋ก ์ ํ๋์์ต๋๋ค.
ํ์ค์ ์ ํฌ์ ๋น์ทํ ์ฑ๊ฒฉ๊ณผ ๊ท๋ชจ๋ก ์๋ฎฌ๋ ์ด์ ๋์์ต๋๋ค.
- ์ผ๋ถ ๊ฐ์ ๋จธ์ ์ด ๋ฎ์ ๋ก๋๋ก ์์๋์์ต๋๋ค.
- ์ผ๋ถ ์์คํ
์ ํ๋ก์ธ์์ ๋ก๋๋ฅผ ์๋ฎฌ๋ ์ด์
ํ๋ ํ
์คํธ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ์ต๋๋ค(์ ํธ๋ฆฌํฐ ์ฌ์ฉ).
์คํธ๋ ์ค ) - ๊ฐ์ ๋จธ์ ์ ๋๋จธ์ง ๋ถ๋ถ์์๋ pv๋ฅผ ์ฌ์ฉํ์ฌ ๋ฏธ๋ฆฌ ์ค๋น๋ ๋ฐ์ดํฐ์์ ์ ํ์ด ์ค์ ๋ ๋์คํฌ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ณต์ฌํ๊ธฐ ์ํด dd๋ฅผ ์ฌ์ฉํ๋ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ์ต๋๋ค(์์ ๋ ๋ณผ ์ ์์).
์ฌ๊ธฐ์ ะธ์ฌ๊ธฐ์ ).
๋ํ ๊ธฐ์ตํ์๊ฒ ์ง๋ง ์ฐ๋ฆฌ์๊ฒ๋ ์ข ํฉ ์งํ๋ฅผ ์์งํ๋ ์ธ ๋์ ๊ธฐ๊ณ๊ฐ ์์์ต๋๋ค.
๊ฐ ์์คํ ์์ ์คํฌ๋ฆฝํธ๋ 15๋ถ๋ง๋ค ์ฃผ๊ธฐ์ ์ผ๋ก ์คํ๋์ด ํ๋ก์ธ์, ๋ฉ๋ชจ๋ฆฌ ๋ฐ ๋์คํฌ์ ๋ํ ํ์ค sysbench ํ ์คํธ๋ฅผ ์คํํ์ต๋๋ค.
sysbench.sh ์คํฌ๋ฆฝํธ
#!/bin/bash
date +"%Y-%m-%d %H:%M:%S" >> /root/sysbench/results.txt
sysbench --test=cpu run >> /root/sysbench/results.txt
sysbench --test=memory run >> /root/sysbench/results.txt
sysbench --test=fileio --file-test-mode=seqwr run >> /root/sysbench/results.txt
sysbench --test=fileio --file-test-mode=seqrd run >> /root/sysbench/results.txt
sysbench --test=fileio --file-test-mode=rndrw run >> /root/sysbench/results.txt
๊ฒฐ๊ณผ๋ ํธ์๋ฅผ ์ํด sysbench ํ์์ผ๋ก ํ์๋์ง๋ง ์ ์ฒด ํ ์คํธ ๊ธฐ๊ฐ์ ํ๊ท ๊ฐ์ ๋ชจ๋ ์์คํ ์์ ๊ฐ์ ธ์จ ๊ฒ์ด๋ฏ๋ก ๊ฒฐ๊ณผ๋ ์ฌ๊ธฐ์์ ๋ณผ ์ ์์ต๋๋ค.
Sysbanch-avg.txtsysbench 0.4.12: multi-threaded system evaluation benchmark
Running the test with following options:
Number of threads: 1
Doing CPU performance benchmark
Threads started!
Done.
Maximum prime number checked in CPU test: 10000
Test execution summary:
total time: 19.2244s
total number of events: 10000
total time taken by event execution: 19.2104
per-request statistics:
min: 1.43ms
avg: 1.92ms
max: 47.00ms
approx. 95 percentile: 3.02ms
Threads fairness:
events (avg/stddev): 10000.0000/0.00
execution time (avg/stddev): 19.2104/0.00
sysbench 0.4.12: multi-threaded system evaluation benchmark
Running the test with following options:
Number of threads: 1
Doing memory operations speed test
Memory block size: 1K
Memory transfer size: 102400M
Memory operations type: write
Memory scope type: global
Threads started!
Done.
Operations performed: 104857600 (328001.79 ops/sec)
102400.00 MB transferred (320.32 MB/sec)
Test execution summary:
total time: 320.9155s
total number of events: 104857600
total time taken by event execution: 244.8399
per-request statistics:
min: 0.00ms
avg: 0.00ms
max: 139.41ms
approx. 95 percentile: 0.00ms
Threads fairness:
events (avg/stddev): 104857600.0000/0.00
execution time (avg/stddev): 244.8399/0.00
sysbench 0.4.12: multi-threaded system evaluation benchmark
Running the test with following options:
Number of threads: 1
Extra file open flags: 0
128 files, 16Mb each
2Gb total file size
Block size 16Kb
Periodic FSYNC enabled, calling fsync() each 100 requests.
Calling fsync() at the end of test, Enabled.
Using synchronous I/O mode
Doing sequential write (creation) test
Threads started!
Done.
Operations performed: 0 Read, 131072 Write, 128 Other = 131200 Total
Read 0b Written 2Gb Total transferred 2Gb (320.1Mb/sec)
20251.32 Requests/sec executed
Test execution summary:
total time: 6.9972s
total number of events: 131072
total time taken by event execution: 5.2246
per-request statistics:
min: 0.01ms
avg: 0.04ms
max: 96.76ms
approx. 95 percentile: 0.03ms
Threads fairness:
events (avg/stddev): 131072.0000/0.00
execution time (avg/stddev): 5.2246/0.00
sysbench 0.4.12: multi-threaded system evaluation benchmark
Running the test with following options:
Number of threads: 1
Extra file open flags: 0
128 files, 16Mb each
2Gb total file size
Block size 16Kb
Periodic FSYNC enabled, calling fsync() each 100 requests.
Calling fsync() at the end of test, Enabled.
Using synchronous I/O mode
Doing sequential read test
Threads started!
Done.
Operations performed: 131072 Read, 0 Write, 0 Other = 131072 Total
Read 2Gb Written 0b Total transferred 2Gb (91.32Mb/sec)
5844.8 Requests/sec executed
Test execution summary:
total time: 23.1054s
total number of events: 131072
total time taken by event execution: 22.9933
per-request statistics:
min: 0.00ms
avg: 0.18ms
max: 295.75ms
approx. 95 percentile: 0.77ms
Threads fairness:
events (avg/stddev): 131072.0000/0.00
execution time (avg/stddev): 22.9933/0.00
sysbench 0.4.12: multi-threaded system evaluation benchmark
Running the test with following options:
Number of threads: 1
Extra file open flags: 0
128 files, 16Mb each
2Gb total file size
Block size 16Kb
Number of random requests for random IO: 10000
Read/Write ratio for combined random IO test: 1.50
Periodic FSYNC enabled, calling fsync() each 100 requests.
Calling fsync() at the end of test, Enabled.
Using synchronous I/O mode
Doing random r/w test
Threads started!
Done.
Operations performed: 6000 Read, 4000 Write, 12800 Other = 22800 Total
Read 93.75Mb Written 62.5Mb Total transferred 156.25Mb (1341.5Kb/sec)
85.61 Requests/sec executed
Test execution summary:
total time: 152.9786s
total number of events: 10000
total time taken by event execution: 14.1879
per-request statistics:
min: 0.01ms
avg: 1.41ms
max: 210.22ms
approx. 95 percentile: 4.95ms
Threads fairness:
events (avg/stddev): 10000.0000/0.00
execution time (avg/stddev): 14.1879/0.00
๊ฒฐ๊ณผ๋ ์์์ ์ด์ง๋ง ์ฌ์ ํ QoS๋ก ๊ฐ์ฃผ๋์ด์๋ ์ ๋ฉ๋๋ค.
์ถ๊ฐ ๋ถํ๋ฅผ ์์ฑํ๋ ๊ธฐ๊ณ
์ํํธ์จ์ด:
- apt-get์ ์ ๋ฐ์ดํธ
- apt-get ์ ๊ทธ๋ ์ด๋
- apt-get python-pip ์ค์น
- pip๋ mysql-connector-python-rf๋ฅผ ์ค์นํฉ๋๋ค.
MariaDB ์ค์น ๋ฐฉ๋ฒ
apt-get install libmariadbclient-dev
mysql -e "INSTALL PLUGIN blackhole SONAME 'ha_blackhole.so';" -- ะฝัะถะฝะพ ะดะปั test_employees_sha
ํ
์คํธ ๊ธฐ๋ฐ ํ๋ณด
๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์ง์ ๋ ๋๋ก ๋ฐฐํฌ๋ฉ๋๋ค.
mysql -t < employees.sql
mysql -t < test_employees_sha.sql
์๊ท๋ชจ ํ ์คํธ ๊ธฐ๋ฐ:
์์ ๋
ํ ๊ฐ์
๋ฐ์ดํฐ ํฌ๊ธฐ(MB)
์ธ๋ฑ์ค ํฌ๊ธฐ(KB)
๋ถ์
9
0.02
16.00
๋ถ์_emp
331143
11.52
5648.00
๋ถ์_๊ด๋ฆฌ์
24
0.02
16.00
์ง์
299379
14.52
0.00
๊ธ์ฌ
2838426
95.63
0.00
์ ๋ชฉ๋ค
442783
19.56
0.00
๊ธฐ๋ณธ ํ ์คํธ ์๋น์ค๋ Python์ผ๋ก ์ฆ์ ์์ฑ๋๋ฉฐ ๋ค์ ๋ค ๊ฐ์ง ์์ ์ ์ํํฉ๋๋ค.
- getState: ์ํ๋ฅผ ๋ฐํํฉ๋๋ค.
- getEmployee: ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ง์(+๊ธ์ฌ, +์งํจ)์ ๋ฐํํฉ๋๋ค.
- patchEmployee: ์ง์ ํ๋ ๋ณ๊ฒฝ
- insertSalary: ๊ธ์ฌ๋ฅผ ์ฝ์ ํฉ๋๋ค.
์๋น์ค ์์ค(dbtest.py)
#!/usr/bin/python
import mysql.connector as mariadb
from flask import Flask, json, request, abort
from mysql.connector.constants import ClientFlag
app = Flask(__name__)
def getFields(cursor):
results = {}
column = 0
for d in cursor.description:
results[d[0]] = column
column = column + 1
return results
PAGE_SIZE = 30
@app.route("/")
def main():
return "Hello!"
@app.route("/employees/<page>", methods=['GET'])
def getEmployees(page):
offset = (int(page) - 1) * PAGE_SIZE
connection = mariadb.connect(user='admin', password='q5XpRomdSr', database='employees')
cursor = connection.cursor()
cursor.execute("SELECT * FROM employees LIMIT {} OFFSET {}".format(PAGE_SIZE, offset))
return {'employees': [i[0] for i in cursor.fetchall()]}
@app.route("/employee/<id>", methods=['GET'])
def getEmployee(id):
id = int(id)
connection = mariadb.connect(user='admin', password='q5XpRomdSr', database='employees')
cursor = connection.cursor()
cursor.execute("SELECT * FROM employees WHERE emp_no = {}".format(id))
fields = getFields(cursor)
employee = {}
found = False
for row in cursor.fetchall():
found = True
employee = {
"birth_date": row[fields["birth_date"]],
"first_name": row[fields["first_name"]],
"last_name": row[fields["last_name"]],
"gender": row[fields["gender"]],
"hire_date": row[fields["hire_date"]]
}
if not found:
abort(404)
cursor.execute("SELECT * FROM salaries WHERE emp_no = {}".format(id))
fields = getFields(cursor)
salaries = []
for row in cursor.fetchall():
salary = {
"salary": row[fields["salary"]],
"from_date": row[fields["from_date"]],
"to_date": row[fields["to_date"]]
}
salaries.append(salary)
employee["salaries"] = salaries
cursor.execute("SELECT * FROM titles WHERE emp_no = {}".format(id))
fields = getFields(cursor)
titles = []
for row in cursor.fetchall():
title = {
"title": row[fields["title"]],
"from_date": row[fields["from_date"]],
"to_date": row[fields["to_date"]]
}
titles.append(title)
employee["titles"] = titles
return json.dumps({
"status": "success",
"employee": employee
})
def isFieldValid(t, v):
if t == "employee":
return v in ["birdth_date", "first_name", "last_name", "hire_date"]
else:
return false
@app.route("/employee/<id>", methods=['PATCH'])
def setEmployee(id):
id = int(id)
content = request.json
print(content)
setList = ""
data = []
for k, v in content.iteritems():
if not isFieldValid("employee", k):
continue
if setList != "":
setList = setList + ", "
setList = setList + k + "=%s"
data.append(v)
data.append(id)
print(setList)
print(data)
connection = mariadb.connect(user='admin', password='q5XpRomdSr', database='employees', client_flags=[ClientFlag.FOUND_ROWS])
cursor = connection.cursor()
cursor.execute("UPDATE employees SET {} WHERE emp_no = %s".format(setList), data)
connection.commit()
if cursor.rowcount < 1:
abort(404)
return json.dumps({
"status": "success"
})
@app.route("/salary", methods=['PUT'])
def putSalary():
content = request.json
print(content)
connection = mariadb.connect(user='admin', password='q5XpRomdSr', database='employees', client_flags=[ClientFlag.FOUND_ROWS])
cursor = connection.cursor()
data = [content["emp_no"], content["salary"], content["from_date"], content["to_date"]]
cursor.execute("INSERT INTO salaries (emp_no, salary, from_date, to_date) VALUES (%s, %s, %s, %s)", data)
connection.commit()
return json.dumps({
"status": "success"
})
@app.route("/state", methods=['GET'])
def getState():
return json.dumps({
"status": "success",
"state": "working"
})
if __name__ == '__main__':
app.run(host='0.0.0.0',port='5002')
๊ฒฝ๊ณ ! ์ด๋ ํ ๊ฒฝ์ฐ์๋ ์ด ์๋น์ค๋ฅผ ์์๋ ์ง์นจ์ผ๋ก ์ผ์์๋ ์ ๋ฉ๋๋ค!
ํ ์คํธ๋ ์ค๋๋ JMeter๋ฅผ ์ฌ์ฉํ์ฌ ์ํ๋ฉ๋๋ค. 15๋ถ์์ 2์๊ฐ๊น์ง ์ง์๋๋ ์ผ๋ จ์ ํ ์คํธ๊ฐ ์ค๋จ ์์ด ์์๋์์ผ๋ฉฐ ์์ฒญ ๋น์จ์ ๋ค์ํ์ผ๋ฉฐ ์ฒ๋ฆฌ๋์ ๋ถ๋น 300~600๊ฐ ์์ฒญ์ผ๋ก ๋ค์ํ์ต๋๋ค. ์ค๋ ๋ ์๋ 50~500๊ฐ์ ๋๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ๋งค์ฐ ์๊ธฐ ๋๋ฌธ์ ๋ค์ ๋ช ๋ น์ ์คํํฉ๋๋ค.
mysql -e "SHOW ENGINE INNODB STATUS"
๊ฒ์ ๋ณด์ฌ์ค๋๋ค:
Buffer pool hit rate 923 / 1000, young-making rate 29 / 1000 not 32 / 1000
๋ค์์ ์์ฒญ์ ๋ํ ํ๊ท ์๋ต ์๊ฐ์ ๋๋ค.
๋ผ๋ฒจ
ํ๊ท
์ค์๊ฐ
90% ๋ผ์ธ
95% ๋ผ์ธ
99% ๋ผ์ธ
Min
Max
getEmployee
37.64
12.57
62.28
128.5
497.57
5
4151.78
getState
17
7.57
30.14
58.71
193
3
2814.71
ํจ์น์ง์
161.42
83.29
308
492.57
1845.14
5
6639.4
put๊ธ์ฌ
167.21
86.93
315.34
501.07
1927.12
7
6722.44
์ด๋ฌํ ํฉ์ฑ ๊ฒฐ๊ณผ๋ฅผ ํตํด ์ด VPS๊ฐ ๊ทํ์ ํน์ ์์
์ ์ผ๋ง๋ ์ ํฉํ์ง ํ๋จํ๊ธฐ ์ด๋ ค์ธ ์ ์์ผ๋ฉฐ ์ผ๋ฐ์ ์ผ๋ก ๋์ด๋ ๋ฐฉ๋ฒ์ ์ฐ๋ฆฌ๊ฐ ์ด๋ค ํํ๋ก๋ ์ฒ๋ฆฌํด์ผ ํ๋ ์ฌ๋ก๋ก ์ ํ๋ฉ๋๋ค. ๋ฐ๋ผ์ ๋ชฉ๋ก์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. ๋ถ๋ช
ํ ์์ ํ์ง๋ ์์ต๋๋ค. ์ฌ๋ฌ๋ถ์ด ์ง์ ๊ฒฐ๋ก ์ ๋ด๋ฆฌ๊ณ ์ค์ ์์ฉ ํ๋ก๊ทธ๋จ๊ณผ ์์
์ ๋ํด 30๋ฃจ๋ธ์ ๋ํ ์๋ฒ๋ฅผ ํ
์คํธํ๊ณ ์๊ฒฌ์ ์ด ๊ตฌ์ฑ์ ๋ํ ์ต์
์ ์ ์ํด ๋ณด์๊ธฐ ๋ฐ๋๋๋ค.
์ถ์ฒ : habr.com