Sèvo + VPS pou 30 rubles =?

Li tèlman bèl lè tout ti bagay ki nesesè yo nan men: yon bon plim ak notepad, yon kreyon file, yon sourit konfòtab, yon koup fil siplemantè, elatriye. Bagay sa yo évident pa atire atansyon, men ajoute konfò nan lavi. Menm istwa a se ak plizyè aplikasyon mobil ak Desktop: pou ekran long, pou diminye gwosè yon foto, pou kalkile finans pèsonèl, diksyonè, tradiktè, konvètisè, elatriye. Ou gen youn konsa? VPS - ki pa chè, toujou nan men ak pote anpil benefis? Non, pa youn nan ou genyen nan konpayi ou, men pwòp ou a, "pòch" yon sèl. Nou te panse ke san yon ti VPS nan 2019 li te yon jan kanmenm tris, jis tankou san plim abityèl la nan yon konferans. Poukisa ou tris? Se ete. Kòman ete ye? Ete pou yon espesyalis IT: chita lakay ou, travay sou pwojè ou pi renmen san okenn regrèt. An jeneral, nou te panse ak fè li.

Sèvo + VPS pou 30 rubles =?
Kominis la rive, kanmarad.

Li se konsa - VPS nou an pou trant

Nou te li yon anpil nan atik ki soti nan konpetitè ak itilizatè ki te ekri 3-4 ane de sa sou poukisa yon VPS chè pa nesesè. Oke, se dwa, Lè sa a, VPS "pou yon pyès lajan" te maketing pi bon kalite epi yo pa t 'kapab ofri opòtinite nòmal travay. Men, tan yo ap chanje, pri a nan resous vityèl ap vin pi ba ak pi ba, ak pou 30 rubles yon mwa nou pare yo ofri sa a:

  • Processeur: Intel Xeon 2 GHz (1 nwayo)
  • Sistèm Linux (Debian, Ubuntu, CentOS pou chwazi nan)
  • 1 adrès IPv4 dedye
  • 10 GB depo done sou kondui SSD vit nan klas antrepriz
  • RAM: 512 MB
  • Pou chak dezyèm bòdwo
  • Trafik san limit

Tarif yo sijè a restriksyon adisyonèl teknik, detay sou paj òf fre nou an - VPS pou 30 rubles. 

Pou kiyès sèvè vityèl sa a apwopriye? Wi pou prèske tout moun: débutan, amater, devlopè ki gen eksperyans, fanatik brikoleur e menm kèk konpayi.

Pou ki sa VPS sa a apwopriye?

Nou panse ke lektè Habr yo pral definitivman jwenn pwòp fason yo sèvi ak konfigirasyon sa a, men nou deside kolekte pwòp seleksyon nou an nan lide - e si yon moun bezwen li, men mesye yo pa konnen?

  • Mete sit entènèt senp ou, pòtfolyo, rezime w ak kòd, elatriye. Natirèlman, pwòp sit entènèt ou a fè yon enpresyon pozitif sou anplwayè a. Mete li sou VPS ou a epi responsab sekirite ak estabilite sit la tèt ou, epi pa anplwaye founisè hosting regilye yo.
  • Sèvi ak VPS pou rezon edikasyon: òganize pwojè ou a, etidye karakteristik yo nan sèvè a ak sistèm opere sèvè a, fè eksperyans ak dns, tinker ak yon ti sit edikasyonèl.
  • Pou telefòn. Pafwa yon antreprenè endividyèl, endependan oswa yon konpayi ki piti anpil bezwen dezespereman telefòn IP, ak operatè yo nan telefòn sa a trè visye. Li senp: nou pran sèvè nou an, achte yon nimewo nan men yon operatè IP, mete kanpe yon PBX vityèl epi kreye nimewo entèn (si sa nesesè). Ekonomi yo kolosal.
  • Sèvi ak sèvè a pou teste aplikasyon w yo.
  • Sèvi ak sèvè a pou eksperyans brikoleur, ki gen ladan kontwole ak kolekte done ki sòti nan detèktè sistèm lakay entelijan.
  • Yon fason etranj yo sèvi ak li se mete yon asistan komès echanj vityèl, yon robo komès, sou sèvè a. Ou pral konplètman responsab pou estabilite ak sekirite nan sèvè a, ki vle di ou pral resevwa yon enstriman kontwole pou komès sou mache bousye yo. Oke, nan ka nenpòt moun ki enterese oswa planifye :)

Gen aplikasyon pou VPS sa yo nan esfè antrepriz la. Anplis sèvis telefòn deja mansyone, ou ka aplike plizyè bagay enteresan. Pa egzanp:

  • Mete ti baz done ak enfòmasyon ki pral aksesib pou anplwaye vwayaje yo nan yon distans, pou egzanp, lè l sèvi avèk ftp. Sa a pral pèmèt ou trè byen vit echanj analiz fre, konfigirasyon mete ajou pou lavant moun, prezantasyon, elatriye.
  • Bay itilizatè yo oswa kliyan aksè tanporè pou montre lojisyèl oswa medya yo.

VPS tès kondwi pou 30 rubles - fè pou ou

30 rubles tèlman piti ke ou pa menm vle pran yon kat pou peye ak tès. Nou pafwa parese tou, men fwa sa a nou te fè tout bagay pou ou. Anvan yo te lanse serveurs yo nan batay, nou te fè yon tès pou tcheke tout detay yo epi montre kisa serveurs yo kapab nan tarif sa a. Pou fè li pi enteresan, nou ajoute ekstrèm ak tcheke ki jan konfigirasyon sa a ta konpòte si dansite a ak chaj depase valè yo nou mete. 

Lame a te anba chay la nan yon kantite machin vityèl ki fè divès travay sou processeur a ak aktivman itilize subsistèm nan disk. Objektif la se simulation yon gwo dansite nan plasman ak yon chaj ki konparab oswa pi gran pase yon konba.

Anplis chaj la konstan, nou enstale 3 machin vityèl ki kolekte mezi sentetik lè l sèvi avèk sysbench, rezilta mwayèn yo te bay pi ba a, ak 50 machin vityèl ki te kreye chaj adisyonèl. Tout tès machin vityèl yo te gen menm konfigirasyon (1 nwayo, RAM 512 GB, SSD 10 GB), yo te chwazi imaj estanda Debian 9.6 kòm sistèm operasyon an, ki ofri itilizatè yo sou RUVDS.

Chaj la te simulation nan lanati ak grandè konparab ak konba:

  • Gen kèk machin vityèl yo te lanse ak chaj ki ba
  • Gen kèk machin ki te kouri yon script tès similye chaj la sou processeur a (itilize sèvis piblik la estrès)
  • Sou pati ki rete a nan machin vityèl yo, nou te kouri yon script ki itilize dd pou kopye done ki soti nan done ki te prepare davans nan disk ak yon limit mete lè l sèvi avèk pv (egzanp yo ka wè isit la и isit la).

Epitou, jan ou sonje, nou te gen twa machin ki kolekte mezi sentetik.

Sou chak machin, yon script te egzekite siklik chak 15 minit, ki kouri tès sysbench estanda pou processeur a, memwa ak disk.

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

Rezilta yo prezante pou konvenyans nan fòma sysbench, men valè mwayèn pou tout peryòd tès la te pran nan tout machin, rezilta a ka wè isit la:

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

Rezilta yo se indicatif, men yo toujou pa ta dwe pran kòm QoS. 

Machin ki kreye chaj adisyonèl

Mou:

  • nimewo apatman-GET aktyalizasyon
  • Apt-jwenn ajou
  • apt-jwenn enstale piton-pip
  • pip enstale mysql-connector-python-rf

Enstale MariaDB, Ki jan yo isit la:

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

Baz tès yo pran kon sa:

Se baz done a deplwaye jan sa espesifye isit la:

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

Ti baz tès:

Tablo 

RowsCount 

Gwosè done (MB)

Gwosè endèks (KB)

depatman 

9

0.02

16.00

dept_emp 

331143 

11.52

5648.00

dept_manager 

24 

0.02

16.00

anplwaye 

299379 

14.52

0.00

salè 

2838426 

95.63

0.00 

tit 

442783 

19.56

0.00

Yon sèvis tès primitif ekri sou jenou an nan Python; li fè kat operasyon:

  1. getState: retounen estati a
  2. getEmployee: retounen anplwaye yo (+salè, +tit) nan baz done a
  3. patchEmployee: chanje jaden anplwaye yo
  4. insertSalary: foure yon salè

Sous sèvis (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')

Attention! Nan okenn sikonstans sèvis sa a ta dwe pran kòm yon egzanp oswa gid!

Tès yo fèt lè l sèvi avèk bon ansyen JMeter. Yon seri tès ki dire ant 15 minit ak 2 èdtan yo te lanse, san entèripsyon, pousantaj demann varye, ak debi varye soti nan 300 a 600 demann pou chak minit. Kantite fil soti nan 50 a 500.

Akòz lefèt ke baz done a piti anpil, lòd la:

mysql -e "SHOW ENGINE INNODB STATUS"

Montre ke:

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

Anba a se tan an mwayèn repons pou demann:

Mete etikèt sou

mwayèn

Medyàn

90% Liy

95% Liy

99% Liy

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

patchAnplwaye

161.42

83.29

308

492.57

1845.14

5

6639.4

meteSalè

167.21

86.93

315.34

501.07

1927.12

7

6722.44

Li ka difisil pou w jije apati rezilta sentetik sa yo ki jan VPS sa a apwopriye pou travay espesifik ou yo epi, an jeneral, metòd ki nan lis yo limite a sèlman ka sa yo ke nou te oblije fè fas ak yon fòm oswa yon lòt. Se konsa, lis nou an se klèman pa konplè. Nou envite ou tire pwòp konklizyon ou epi teste sèvè a pou 30 rubles sou aplikasyon reyèl ou yo ak travay epi sijere opsyon ou pou konfigirasyon sa a nan kòmantè yo.

Sous: www.habr.com

Add nouvo kòmantè