mongodb 부하테스트

technomad·2024년 8월 23일

개요

MongoDB 컬렉션을 구성하고, Insert, Select 부하에 대한 성능을 테스트합니다.

테스트VM 의 Shape는 다음과 같습니다.

VM용도ShapePrivate IP
demo-dbDB 서버x86 VM 1 CPU, 16GB Mem10.0.1.18
demo-appAPP 서버x86 VM 1 CPU, 16GB Mem10.0.0.70

DB 구성

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

테스트APP 환경 구성

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

테스트 APP 작성

간단하게 각 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 부하입니다.

profile
tech life

0개의 댓글