
MongoDB 컬렉션을 구성하고, Insert, Select 부하에 대한 성능을 테스트합니다.
테스트VM 의 Shape는 다음과 같습니다.
| VM | 용도 | Shape | Private IP | |
|---|---|---|---|---|
| demo-db | DB 서버 | x86 VM 1 CPU, 16GB Mem | 10.0.1.18 | |
| demo-app | APP 서버 | x86 VM 1 CPU, 16GB Mem | 10.0.0.70 |
MongoDB 를 구성합니다.
MongoDB 6.0을 사용하도록 하겠습니다.
참조 URL : https://www.mongodb.com/docs/manual/tutorial/install-mongodb-on-red-hat/
YUM리파지토리를 생성합니다.
$ sudo vi /etc/yum.repos.d/mongodb-org-6.0.repo
[mongodb-org-6.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/6.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-6.0.asc
YUM으로 MongoDB를 설치합니다.
$ sudo yum install -y mongodb-org
중략..
Complete!
MongoDB 를 서비스로 등록합니다.
$ sudo systemctl start mongod
$ sudo systemctl enable mongod
$ sudo systemctl status mongod
MongoDB 서비스에 접속해 봅니다.
$ mongosh
Current Mongosh Log ID: 643bbc596bcf4e8ced9c9543
Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+1.8.0
Using MongoDB: 6.0.5
Using Mongosh: 1.8.0
For mongosh info see: https://docs.mongodb.com/mongodb-shell/
To help improve our products, anonymous usage data is collected and sent to MongoDB periodically (https://www.mongodb.com/legal/privacy-policy).
You can opt-out by running the disableTelemetry() command.
test>
admin 유저를 추가해 주고, mongo유저로 접속해 봅니다.
test> use admin
switched to db admin
admin> db.createUser({ user: 'mongo', pwd: 'mongo', roles: ['root'] })
{ ok: 1 }
admin> exit
[opc@oci-demo-db ~]$ mongosh -u mongo -p
Enter password: *****
Current Mongosh Log ID: 643bc123d5285727620484b7
Connecting to: mongodb://<credentials>@127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+1.8.0
Using MongoDB: 6.0.5
Using Mongosh: 1.8.0
For mongosh info see: https://docs.mongodb.com/mongodb-shell/
test>
외부 접속을 위한 설정을 해줍니다.
$ sudo vi /etc/mongod.conf
# bindIp: 127.0.0.1 # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting.
bindIp: 0.0.0.0 # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting.
MongoDB 서비스를 재기동합니다.
$ sudo systemctl restart mongod
Linux방화벽에 TCP 27017 포트를 추가합니다.
$ sudo firewall-cmd --zone=public --permanent --add-port=27017/tcp
success
$ sudo firewall-cmd --reload
success
DB 서비스 확인합니다.
$ ps -ef | grep mongo
mongod 39204 1 0 05:52 ? 00:00:05 /usr/bin/mongod -f /etc/mongod.conf
demo-app VM에 파이썬 환경을 구성합니다.
버전은 Python 3을 사용합니다.
$ python -V
Python 3.6.8
파이썬 가상환경을 만들어 줍니다.
$ mkdir venvs
$ cd venvs
$ python -m venv sampleweb
가상환경에 진입합니다.
$ cd sampleweb/bin/
$ source activate
Flask, pymongo설치 및 pip를 업그레이드 합니다.
$ pip install flask
$ pip install pymongo
$ python -m pip install --upgrade pip
Linux 방화벽에도 TCP 5000 포트를 추가해 줍니다.
$ sudo firewall-cmd --zone=public --permanent --add-port=5000/tcp
success
$ sudo firewall-cmd --reload
success
demp-app 서버에 DB 접속용 클라이언트를 셋업해 줍니다.
YUM리파지토리를 생성합니다.
$ sudo vi /etc/yum.repos.d/mongodb-org-6.0.repo
[mongodb-org-6.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/6.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-6.0.asc
YUM으로 MongoDB Client 를 설치합니다.
$ sudo yum install mongodb-mongosh
중략..
Complete!
MongoDB에 접속해 봅니다.
$ mongosh mongodb://10.0.1.18:27017 -u mongo -p
Enter password: *****
Current Mongosh Log ID: 643d166436853fefdbe957b9
Connecting to: mongodb://<credentials>@10.0.1.135:27017/?directConnection=true&appName=mongosh+1.8.0
Using MongoDB: 6.0.5
Using Mongosh: 1.8.0
For mongosh info see: https://docs.mongodb.com/mongodb-shell/
To help improve our products, anonymous usage data is collected and sent to MongoDB periodically (https://www.mongodb.com/legal/privacy-policy).
You can opt-out by running the disableTelemetry() command.
test> exit
간단하게 각 DB에 JSON 다큐먼트 스토어를 만들고, 1건을 Insert하고 2건을 Select 하는 앱을 만듭니다.
Flask앱 sampleapp.py를 만듭니다.
$ vi sampleapp.py
import logging
from datetime import datetime
from pymongo import MongoClient
import json
from flask import Flask
from faker import Faker
app = Flask(__name__)
logger = logging.getLogger()
logger.setLevel(logging.INFO)
fake=Faker()
mongo_db_host_ip = '10.0.1.18'
mongo_db_host_port = 27017
mongo_db_user_name = 'mongo'
mongo_db_passwd = 'mongo'
mongo_client = MongoClient(mongo_db_host_ip, mongo_db_host_port, username=mongo_db_user_name, password=mongo_db_passwd)
@app.route('/mongo/insert')
def mongo_insert():
try:
#mongo_client = MongoClient(mongo_db_host_ip, mongo_db_host_port, username=mongo_db_user_name, password=mongo_db_passwd)
mongo_db = mongo_client.test
mongo_collection = mongo_db.sample
sample = [
{
"user_name": fake.name(),
"job" : fake.job(),
"client_ip" : fake.ipv4_private(),
"last_conn_date": datetime.now()
}
]
mongo_collection.insert_many(sample)
except Exception as e:
logger.error("mongo error : could not fetch data.")
logger.error(e)
logger.info("success : querying data succeeded.")
return "200"
@app.route('/mongo/select')
def mongo_query():
try:
#mongo_client = MongoClient(mongo_db_host_ip, mongo_db_host_port, username=mongo_db_user_name, password=mongo_db_passwd)
mongo_db = mongo_client.test
mongo_collection = mongo_db.sample
mongo_objects = mongo_client.test.sample.find().sort("_id",-1).limit(1)
mongo_result = str(json.dumps({'results': list(mongo_objects)}, default=str, indent=4))
except Exception as e:
logger.error("mongo error : could not fetch data.")
logger.error(e)
logger.info("success : querying data succeeded.")
return str(mongo_result)
App을 실행합니다.
$ export FLASK_APP=sampleapp
$ flask run --host=0.0.0.0
* Serving Flask app 'sampleapp' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on all addresses.
WARNING: This is a development server. Do not use it in a production deployment.
* Running on http://10.0.0.70:5000/ (Press CTRL+C to quit)
웹브라우저에서 접근하면 잘 동작하는 것을 확인할 수 있습니다.

부하테스트를 위해 병렬처리를 지원하는 WSGI인 gunicorn을 설치합니다. flask개발 모드는 기본적으로 싱글 쓰레드로 동작하므로 부하테스트에 적합하지 않습니다.
$ pip install gunicorn
부하테스트 도구인 locust를 설치합니다.
$ pip install locust
부하 테스트용 스크립트를 작성합니다. 테스트할 시나리오만 주석해제 하고 수행합니다.
$ vi locustfile.py
from locust import HttpUser, task
class User(HttpUser):
@task
def index(self):
self.client.get("/mongo/insert")
# self.client.get("/mongo/select")
gunicorn을 백그라운로 수행합니다.
$ gunicorn --workers=2 sampleapp:app -b 0.0.0.0:5000 &
[2023-05-18 08:10:31 +0000] [66773] [INFO] Starting gunicorn 20.1.0
[2023-05-18 08:10:31 +0000] [66773] [INFO] Listening at: http://127.0.0.1:5000 (66773)
[2023-05-18 08:10:31 +0000] [66773] [INFO] Using worker: sync
[2023-05-18 08:10:31 +0000] [66776] [INFO] Booting worker with pid: 66776
[2023-05-18 08:10:31 +0000] [66778] [INFO] Booting worker with pid: 66778
locust로 부하를 수행합니다.
$ sudo ulimit -n 2048
$ locust
demo-app 터미널을 하나 더 열어서, Linux 방화벽에 TCP 8089 포트를 추가해 줍니다.
$ sudo firewall-cmd --zone=public --permanent --add-port=8089/tcp
success
$ sudo firewall-cmd --reload
success
유저 50으로 1초간격으로 부하를 줍니다.

MongoDB Insert 부하결과 입니다.

MongoDB Select 부하입니다.
