Майна + VPS барои 30 рубл =?

Ин хеле хуб аст, вақте ки ҳама чизҳои хурди зарурӣ дар даст ҳастанд: қалам ва блокноти хуб, қалами тез, муши бароҳат, якчанд симҳои иловагӣ ва ғайра. Ин чизҳои ноаён таваҷҷӯҳро ба худ ҷалб намекунанд, балки ба ҳаёт роҳат мебахшанд. Ҳамин ҳикоя бо барномаҳои гуногуни мобилӣ ва мизи корӣ: барои скриншотҳои дароз, барои кам кардани андозаи тасвир, барои ҳисоб кардани маблағҳои шахсӣ, луғатҳо, тарҷумонҳо, конвертерҳо ва ғайра. Шумо якто доред? VPS - кадоме арзон, ҳамеша дар даст аст ва фоидаи зиёд меорад? Не, на он чизе, ки шумо дар ширкати худ доред, балки аз худатон, "кисавӣ". Мо фикр мекардем, ки бидуни VPS-и хурд дар соли 2019 он ба гунае ғамгин аст, ба мисли бидуни қалами муқаррарии лексия. Чаро ғамгин? Тобистон аст. Тобистон чӣ гуна аст? Тобистон барои мутахассиси IT: дар хона нишаста, дар лоиҳаҳои дӯстдоштаи худ бидуни пушаймон кор кардан. Умуман, мо фикр кардем ва кардем.

Майна + VPS барои 30 рубл =?
Коммунизм фаро расид, рафикон.

Вай чунин аст - VPS-и мо барои сӣ

Мо мақолаҳои зиёдеро аз рақибон ва корбарон хондем, ки 3-4 сол пеш дар бораи он ки чаро VPS-и арзон лозим нест, навишта буданд. Хуб, ин дуруст аст, пас VPS "барои як динор" маркетинги холис буд ва имкони кори муқаррариро пешниҳод карда наметавонист. Аммо вақтҳо тағир меёбанд, арзиши захираҳои виртуалӣ пасттар ва пасттар мешаванд ва мо барои 30 рубл дар як моҳ омодаем, ки инро пешниҳод кунем:

  • Протсессор: Intel Xeon 2 ГГц (1 аслӣ)
  • Системаи Linux (Debian, Ubuntu, CentOS барои интихоб)
  • 1 суроғаи махсуси IPv4
  • 10 ГБ нигоҳдории маълумот дар дискҳои SSD-синфи корпоративӣ
  • RAM: 512 MB
  • Ҳисобкунии як сония
  • Трафики бемаҳдуд

Тарофа ба маҳдудиятҳои иловагии техникӣ, тафсилот дар саҳифа пешниҳоди сард мо - 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 пешниҳод карда мешавад.

Сарборӣ аз рӯи табиат ва миқёси муқоисашаванда бо ҷанг тақлид карда шуд:

  • Баъзе мошинҳои виртуалӣ бо бори кам ба кор андохта шуданд
  • Баъзе мошинҳо скрипти санҷиширо иҷро карданд, ки сарбории протсессоро тақлид мекунад (бо истифода аз утилита стресс)
  • Дар қисми боқимондаи мошинҳои виртуалӣ мо скриптро иҷро кардем, ки dd-ро барои нусхабардории маълумот аз маълумоти пешакӣ ба диск бо маҳдудияти муқарраршуда бо истифода аз pv истифода бурд (мисолҳоро дидан мумкин аст). дар ин ҷо и дар ин ҷо).

Инчунин, чунон ки шумо дар хотир доред, мо се мошин доштем, ки метрикаи синтетикиро ҷамъоварӣ мекарданд.

Дар ҳар як мошин скрипт ба таври даврӣ ҳар 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 install 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

Пойгоҳи хурди санҷиш:

Љадвали 

Сатрҳо 

Андозаи маълумот (МБ)

Андозаи индекс (KB)

шӯъбаҳо 

9

0.02

16.00

департаменти_эмп 

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 навишта шудааст; он чор амалро иҷро мекунад:

  1. getState: вазъиятро бармегардонад
  2. getEmploee: кормандонро (+маош, +унвонҳо) аз пойгоҳи додаҳо бармегардонад
  3. patchEmployee: майдонҳои кормандонро тағир медиҳад
  4. insertMaosh: маош дохил мекунад

Манбаи хидмат (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

макс

даст корманд

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

Музди меҳнат

167.21

86.93

315.34

501.07

1927.12

7

6722.44

Шояд барои шумо аз рӯи ин натиҷаҳои синтетикӣ хулоса баровардан душвор бошад, ки ин VPS барои вазифаҳои мушаххаси шумо то чӣ андоза мувофиқ аст ва дар маҷмӯъ, усулҳои номбаршуда танҳо бо он ҳолатҳое маҳдуданд, ки мо бояд бо ин ё он шакл ҳал кунем. равшан нест. Мо шуморо даъват мекунем, ки хулосаҳои худро бароред ва серверро барои 30 рубл дар бораи замимаҳо ва вазифаҳои воқеии худ санҷед ва имконоти худро барои ин конфигуратсия дар шарҳҳо пешниҳод кунед.

Манбаъ: will.com

Илова Эзоҳ