Brain + VPS per 30 rubles =?

Hè cusì bellu quandu tutte e cose necessarie sò in manu: una bona penna è un bloccu note, un lapis affilatu, un mouse còmode, un paru di fili extra, etc. Queste cose inconspicuous ùn attrae micca l'attenzione, ma aghjunghjenu cunfortu à a vita. A listessa storia hè cù parechje applicazioni mobili è desktop: per screenshots longu, per riduce a dimensione di una stampa, per calculà e finanze persunale, dizziunari, traduttori, cunvertitori, etc. Avete unu ? VPS - chì hè prezzu, sempre à manu è porta assai benefici ? Innò, micca quellu chì avete in a vostra cumpagnia, ma u vostru propiu, "pocket". Avemu pensatu chì senza un picculu VPS in 2019 era in qualchì manera triste, cum'è senza a solita penna stilografica in una conferenza. Perchè esse tristi? Hè veranu. Com'è l'estate ? L'estate per un specialista in IT: pusatu in casa, travagliendu nantu à i vostri prughjetti preferiti senza alcunu rimpianti. In generale, avemu pensatu è fattu.

Brain + VPS per 30 rubles =?
U cumunismu hè ghjuntu, camaradi.

Hè cusì - u nostru VPS per trenta

Avemu lettu assai articuli da i cuncurrenti è l'utilizatori chì anu scrittu 3-4 anni fà per quessa chì un VPS di prezzu ùn hè micca necessariu. Ebbè, hè ghjustu, allora VPS "per un centesimu" era marketing pura è ùn pudia micca offre opportunità di travagliu normale. Ma i tempi cambianu, u costu di risorse virtuali hè diventatu più bassu è più bassu, è per 30 rubles à u mese simu pronti à offre questu:

  • Processore: Intel Xeon 2 GHz (1 core)
  • Sistema Linux (Debian, Ubuntu, CentOS da sceglie)
  • 1 indirizzu IPv4 dedicatu
  • 10 GB di almacenamiento di dati nantu à unità SSD veloci di classe impresa
  • RAM: 512 MB
  • Per seconda fattura
  • Traffico illimitatu

A tarifa hè sottumessa à restrizioni tecniche supplementari, dettagli nantu pagina a nostra offerta cool - VPS per 30 rubles. 

À quale hè adattatu stu servitore virtuale? Iè à quasi tutti: principianti, dilettanti, sviluppatori sperimentati, fan di DIY è ancu alcune cumpagnie.

A cosa hè adattatu stu VPS?

Pensemu chì i lettori di Habr anu da truvà u so propiu modu d'utilizà sta cunfigurazione, ma avemu decisu di cullà a nostra propria selezzione di idee - chì si qualchissia hà bisognu, ma l'omi ùn sanu micca?

  • Pone u vostru situ web simplice, cartera, curriculum vitae cù codice, etc. Di sicuru, u vostru propiu situ web cuncepitu face una impressione positiva nantu à u patronu. Pone lu in u vostru VPS è esse rispunsevuli di a sicurità è a stabilità di u situ stessu, è micca da u persunale di i fornituri di hosting regulare.
  • Aduprate VPS per scopi educativi: ospitate u vostru prughjettu, studià e caratteristiche di u servitore è u sistema operatore di u servitore, sperimentate cù DNS, tinker cun un picculu situ educativu.
  • Per a telefonia. Calchì volta un entrepreneur individuale, freelancer o una sucietà assai chjuca hà bisognu disperatamente di telefonia IP, è l'operatori di questa telefonia sò assai avari. Hè simplice: pigliamu u nostru servitore, cumprà un numeru da un operatore di telefonia IP, stallate un PBX virtuale è creanu numeri internu (se necessariu). U risparmiu hè colossali.
  • Aduprate u servitore per pruvà e vostre applicazioni.
  • Aduprate u servitore per esperimenti DIY, cumpresu u cuntrollu è a cullizzioni di dati da i sensori di u sistema di casa intelligente.
  • Un modu inusual di usà hè di mette un assistente di scambiu virtuale, un robot di cummerciale, nantu à u servitore. Serete pienamente rispunsevuli di a stabilità è a sicurità di u servitore, chì significa chì riceverete un strumentu cuntrullatu per u cummerciu in i mercati di borsa. Ebbè, in casu chì qualchissia hè interessatu o pianificà :)

Ci sò applicazioni per tali VPS in l'esfera corporativa. In più di u serviziu telefuninu digià citatu, pudete implementà parechje cose interessanti. Per esempiu:

  • Pone picculi basa di dati è informazioni chì saranu accessibili à l'impiegati chì viaghjanu à distanza, per esempiu, usendu ftp. Questu permetterà di scambià assai rapidamente analitiche fresche, cunfigurazioni aghjurnate per i venditori, presentazioni, etc.
  • Dà un accessu tempurale à l'utilizatori o clienti per dimustrà software o media.

Test drive VPS per 30 rubli - fattu per voi

30 rubles hè cusì pocu chì ùn vulete mancu piglià una carta per pagà è pruvà. A volte simu cusì pigri ancu, ma sta volta avemu fattu tuttu per voi. Prima di lancià i servitori in battaglia, avemu fattu una prova per verificà tutti i dettagli è dimustrà ciò chì i servitori sò capaci di sta tarifa. Per fà più interessante, avemu aghjustatu estremu è verificatu cumu si comporta sta cunfigurazione se a densità è a carica superavanu i valori chì avemu stabilitu. 

L'ospitu era sottu à a carica di una quantità di macchine virtuali chì anu realizatu diversi travaglii nantu à u processatore è attivamente utilizatu u sottosistema di discu. L'obiettivu hè di simulà una alta densità di piazzamentu è una carica paragunabile o più grande di una di cummattimentu.

In più di a carica constante, avemu installatu 3 macchine virtuali chì cullighjanu metriche sintetiche cù sysbench, i risultati mediu di quale sò stati dati quì sottu, è 50 macchine virtuali chì creanu una carica supplementaria. Tutte e macchine virtuali di prova avianu a listessa cunfigurazione (1 core, RAM 512 GB, SSD 10 GB), l'imagine standard di Debian 9.6 hè stata scelta cum'è u sistema operatore, chì hè offertu à l'utilizatori in RUVDS.

A carica hè stata simulata in natura è magnitudine paragunabili à cumbattimentu:

  • Alcune macchine virtuali sò state lanciate cù una carica bassa
  • Alcune macchine eseguiu un script di prova chì simulava a carica nantu à u processatore (usendu l'utilità ddoi)
  • Nant'à a parte restante di e macchine virtuali, avemu eseguitu un script chì usava dd per copià e dati da dati pre-preparati à u discu cù un limitu stabilitu cù pv (esempii ponu vede ccà и ccà).

Inoltre, cum'è vi ricordate, avemu avutu trè macchine chì cullighjanu metriche sintetiche.

In ogni macchina, un script hè statu eseguitu ciclicamente ogni 15 minuti, chì esegue testi standard di sysbench per u processatore, a memoria è u discu.

Script 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

I risultati sò presentati per comodità in u formatu sysbench, ma i valori medii per tuttu u periodu di prova sò stati pigliati da tutte e macchine, u risultatu pò esse vistu quì:

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

I risultati sò indicativi, ma ancu ùn deve esse pigliatu cum'è QoS. 

Macchine chì creanu carica supplementu

Software:

  • Apt-get update
  • apt-get upgrade
  • apt-get install python-pip
  • pip install mysql-connector-python-rf

Installatu MariaDB, Cumu ccà:

apt-get install libmariadbclient-dev
mysql -e "INSTALL PLUGIN blackhole SONAME 'ha_blackhole.so';" -- нужно для test_employees_sha

Basa di prova pigliata da quì:

A basa di dati hè implementata cum'è specificata ccà:

mysql -t < employees.sql
mysql -t < test_employees_sha.sql

Piccola basa di prova:

Table 

RowsCount 

Dimensione di dati (MB)

Taille de l'index (KB)

dipartimenti 

9

0.02

16.00

dipartimentu_emp 

331143 

11.52

5648.00

dept_manager 

24 

0.02

16.00

Dipoi sempre 

299379 

14.52

0.00

stipendi 

2838426 

95.63

0.00 

tituli 

442783 

19.56

0.00

Un serviziu di teste primitivu hè scrittu annantu à u ghjinochju in Python; esegue quattru operazioni:

  1. getState: torna u statutu
  2. getEmployee: torna l'impiegati (+salari, +tituli) da a basa di dati
  3. patchEmployee: cambia i campi di l'impiegati
  4. insertSalary : inserisce un salariu

Fonte di serviziu (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')

Attenzione! In nisun casu, stu serviziu ùn deve esse pigliatu cum'è un esempiu o una guida!

I testi sò realizati cù un bonu vechju JMeter. Una seria di teste chì duranu da 15 minuti à 2 ore sò state lanciate, senza interruzioni, u percentualità di richieste variava, è u throughput variava da 300 à 600 richieste per minutu. Numero di fili da 50 à 500.

A causa di u fattu chì a basa di dati hè assai chjuca, u cumandimu:

mysql -e "SHOW ENGINE INNODB STATUS"

Mostra chì:

Buffer pool hit rate 923 / 1000, young-making rate 29 / 1000 not 32 / 1000

Quì sottu sò i tempi medii di risposta per e dumande:

Etichette

Average

Mediu

90% Linea

95% Linea

99% Linea

Min

Max

get Employee

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

patch Impiegatu

161.42

83.29

308

492.57

1845.14

5

6639.4

mette Salariu

167.21

86.93

315.34

501.07

1927.12

7

6722.44

Pò esse difficiule per voi di ghjudicà da questi risultati sintetici quantu hè adattatu questu VPS per i vostri compiti specifichi è, in generale, i metudi listati sò limitati à quelli casi chì avemu avutu à trattà in una forma o l'altru. chjaramente micca esaustivu. Vi invitemu à piglià e vostre cunclusioni è pruvà u servitore per 30 rubles nantu à e vostre applicazioni è e vostre attività reali è suggerisce e vostre opzioni per questa cunfigurazione in i cumenti.

Source: www.habr.com

Add a comment