Он такой свой — наш VPS за тридцатку
Мы начитались статей конкурентов и пользователей, которые 3-4 года назад писали о том, почему не нужен недорогой VPS. Ну правильно, тогда VPS «за копейки» был чистой воды маркетингом и не мог предложить нормальные рабочие возможности. Но времена меняются, стоимость виртуальных ресурсов становится всё ниже и за 30 рублей в месяц мы готовы предложить вот что:
- Процессор: Intel Xeon 2 ГГц (1 ядро)
- Система Linux (Debian, Ubuntu, CentOS на выбор)
- 1 выделенный IPv4-адрес
- 10 Гб для хранения данных на быстрых SSD-дисках корпоративного класса
- Оперативная память: 512 Мб
- Посекундная тарификация
- Безлимитный трафик
На тариф действуют дополнительные технические ограничения, подробности на странице нашего классного предложения — VPS за 30 рублей.
Кому подойдёт такой виртуальный сервер? Да почти всем: новичкам, энтузиастам, опытным разработчикам, DIY-фанатам и даже некоторым компаниям.
Для чего подходит такой VPS?
Мы думаем, читатели Хабра точно найдут свой способ применения такой конфигурации, но решили собрать и свою подборку идей — а то вдруг кому-то надо, а мужики и не знают?
- Разместить свой несложный сайт, портфолио, резюме с кодом и проч. Конечно, собственный оформленный сайт производит на работодателя позитивное впечатление. Разместите его на своём VPS и отвечайте за безопасность и стабильность сайта самостоятельно, а не силами сотрудников обычных хостингов.
- Использовать VPS для учебных целей: разместить свой проект, изучить особенности функционирования сервера и серверной операционной системы, поэкспериментировать с DNS, поковырять маленький учебный сайт.
- Для телефонии. Иногда индивидуальному предпринимателю, фрилансеру или очень небольшой компании крайне нужна IP-телефония, а операторы этой самой телефонии весьма жадные. Всё просто: берём свой сервер, покупаем номер у оператора IP-телефонии, настраиваем виртуальную АТС и создаём внутренние номера (при необходимости). Экономия колоссальная.
- Использовать сервер для тестирования своих приложений.
- Использовать сервер для DIY-экспериментов, в том числе для управления и сбора данных с датчиков системы умного дома.
- Необычный способ применения — разместить на сервере виртуального помощника биржевой торговли, торгового робота. Вы будете полностью отвечать за стабильность и безопасность сервера, а значит, получите подконтрольный инструмент для торгов на фондовы рынках. Ну вдруг кто увлекается или планирует 🙂
Есть такому VPS применение и в корпоративной сфере. Кроме уже названного телефонного сервиса, можно реализовать несколько интересных штук. Например:
- Размещать небольшие базы данных и информацию, которые будут доступны командировочным сотрудникам на расстоянии, например, с помощью ftp. Это позволит очень быстро обменяться свежей аналитикой, обновлёнными конфигурациями для продажников, презентацией и т.д.
- Давать временный доступ пользователям или клиентам для демонстрации программного обеспечения или мультимедиа.
Тест-драйв VPS за 30 рублей — сделали за вас
30 рублей это настолько мало, что даже неохота доставать карточку, чтобы оплатить и потестить. Мы иногда тоже такие ленивые, но в этот раз сделали всё за вас. Перед запуском серверов в бой мы провели тест, чтобы проверить все детали и показать, на что способны серверы на данном тарифе. Чтобы было интереснее, мы добавили экстрима и проверили как себя поведёт эта конфигурация, если плотность и нагрузка будут превышать установленные нами значения.
Хост находился под нагрузкой некоторого количества виртуальных машин, которые выполняли различные задачи на процессоре и активно использовали дисковую подсистему. Цель — смоделировать высокую плотность размещения и нагрузку сопоставимую или большую, чем боевая.
Помимо постоянной нагрузки поставили 3 виртуальные машины, собирающие синтетические метрики с помощью sysbench, усредненные результаты которых привели ниже, и 50 виртуальных машин, которые создавали дополнительную нагрузку. Все тестовые виртуальные машины имели одинаковую конфигурацию (1 ядро, RAM 512 Гб, SSD 10Гб), в качестве операционной системы выбран стандартный образ debian 9.6, который предлагается пользователям на RUVDS.
Нагрузку имитировали по характеру и величине сопоставимую с боевой:
- Часть виртуальных машин были запущены с низкой нагрузкой
- Часть машин «крутили» тестовый сценарий, имитирующий нагрузку на процессор (с использованием утилиты stress)
- На оставшейся части виртуалок мы запустили сценарий, использующий dd для копирования данных из заранее заготовленных данных на диск с ограничением, заданным с помощью pv (примеры можно посмотреть здесь и здесь).
Ещё, как вы помните, у нас были три машины, собирающие синтетические метрики.
На каждой машине циклически раз в 15 минут выполнялся скрипт, который запускает стандартные тесты sysbench для процессора, памяти и диска.
#!/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’а, но взяты средние значения за всё время тестирования со всех машин, итог можно посмотреть здесь:
sysbench 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 update
- apt-get upgrade
- apt-get install python-pip
- pip install 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
Тестовая база маленького объема:
| Table | RowsCount | Data size (MB) | Index size (KB) |
|---|---|---|---|
| departments | 9 | 0.02 | 16.00 |
| dept_emp | 331143 | 11.52 | 5648.00 |
| dept_manager | 24 | 0.02 | 16.00 |
| employees | 299379 | 14.52 | 0.00 |
| salaries | 2838426 | 95.63 | 0.00 |
| titles | 442783 | 19.56 | 0.00 |
Примитивный тестовый сервис написан на коленке на питоне, он выполняет четыре операции:
- getState: возвращает статус
- getEmployee: возвращает из базы employee (+salaries, +titles)
- patchEmployee: изменяет поля employee
- insertSalary: выполняет вставку salary
#!/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
Ниже приведены усредненные значения времени ответа на запросы:
| Label | Average | Median | 90% Line | 95% Line | 99% Line | 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 |
| patchEmployee | 161.42 | 83.29 | 308 | 492.57 | 1845.14 | 5 | 6639.4 |
| putSalary | 167.21 | 86.93 | 315.34 | 501.07 | 1927.12 | 7 | 6722.44 |
Возможно вам будет сложно по данным синтетическим результатам судить о том, насколько подходит данный VPS под ваши конкретные задачи и в целом, перечисленные способы ограничиваются теми кейсами, с которыми нам приходилось в том или ином виде сталкиваться.Так что наш список явно не исчерпывающий. Предлагаем вам самим сделать выводы и протестировать сервер за 30 рублей на ваших реальных приложениях и задачах и предложить в комментариях свои варианты для такой конфигурации.
ссылка на оригинал статьи https://habr.com/ru/company/ruvds/blog/464571/

Добавить комментарий