Truri + VPS për 30 rubla =?

Është shumë bukur kur të gjitha gjërat e vogla të nevojshme janë pranë: një stilolaps dhe bllok shënimesh të mirë, një laps i mprehur, një mi i rehatshëm, disa tela shtesë, etj. Këto gjëra që nuk bien në sy nuk tërheqin vëmendjen, por i shtojnë rehati jetës. E njëjta histori është me aplikacione të ndryshme celulare dhe desktop: për pamje të gjata të ekranit, për zvogëlimin e madhësisë së një fotografie, për llogaritjen e financave personale, fjalorë, përkthyes, konvertues etj. A keni një të tillë? VPS - cila është e lirë, gjithmonë pranë dhe sjell shumë përfitime? Jo, jo atë që keni në kompaninë tuaj, por tuajin, "xhepin". Ne menduam se pa një VPS të vogël në 2019 ishte disi e trishtuar, ashtu si pa stilolapsin e zakonshëm në një leksion. Pse të jetë i trishtuar? Eshte vere. si është vera? Verë për një specialist IT: ulur në shtëpi, duke punuar në projektet tuaja të preferuara pa asnjë keqardhje. Në përgjithësi, ne menduam dhe e bëmë atë.

Truri + VPS për 30 rubla =?
Komunizmi ka ardhur, shokë.

Ai është i tillë - VPS-ja jonë për tridhjetë

Ne kemi lexuar shumë artikuj nga konkurrentët dhe përdoruesit që shkruan 3-4 vjet më parë se pse nuk nevojitet një VPS i lirë. Epo, ashtu është, atëherë VPS "për një qindarkë" ishte marketing i pastër dhe nuk mund të ofronte mundësi normale pune. Por kohët po ndryshojnë, kostoja e burimeve virtuale po bëhet gjithnjë e më e ulët, dhe për 30 rubla në muaj ne jemi të gatshëm ta ofrojmë këtë:

  • Procesori: Intel Xeon 2 GHz (1 bërthamë)
  • Sistemi Linux (Debian, Ubuntu, CentOS për të zgjedhur)
  • 1 adresë e dedikuar IPv4
  • 10 GB ruajtje të të dhënave në disqet e shpejtë SSD të klasit të ndërmarrjes
  • RAM: 512 MB
  • Faturimi për sekondë
  • Trafik i pakufizuar

Tarifa i nënshtrohet kufizimeve teknike shtesë, detaje mbi faqe oferta jonë e lezetshme - VPS për 30 rubla. 

Për kë është i përshtatshëm ky server virtual? Po pothuajse për të gjithë: fillestarët, entuziastët, zhvilluesit me përvojë, fansat DIY dhe madje edhe disa kompani.

Për çfarë është i përshtatshëm ky VPS?

Ne mendojmë se lexuesit e Habr do të gjejnë patjetër mënyrën e tyre për të përdorur këtë konfigurim, por vendosëm të mbledhim përzgjedhjen tonë të ideve - po sikur dikujt t'i duhet, por burrat nuk e dinë?

  • Vendosni uebsajtin tuaj të thjeshtë, portofolin, rezymenë me kod, etj. Natyrisht, uebfaqja juaj e dizajnuar bën një përshtypje pozitive te punëdhënësi. Vendoseni atë në VPS-në tuaj dhe jini vetë përgjegjës për sigurinë dhe stabilitetin e faqes, dhe jo nga stafi i ofruesve të rregullt të pritjes.
  • Përdorni VPS për qëllime edukative: organizoni projektin tuaj, studioni veçoritë e sistemit operativ të serverit dhe serverit, eksperimentoni me DNS, ndërroni me një sit të vogël arsimor.
  • Për telefoni. Ndonjëherë një sipërmarrës individual, profesionist i pavarur ose një kompani shumë e vogël ka nevojë të dëshpëruar për telefoni IP, dhe operatorët e kësaj telefonie janë shumë të pangopur. Është e thjeshtë: marrim serverin tonë, blejmë një numër nga një operator i telefonisë IP, vendosim një PBX virtual dhe krijojmë numra të brendshëm (nëse është e nevojshme). Kursimet janë kolosale.
  • Përdorni serverin për të testuar aplikacionet tuaja.
  • Përdorni serverin për eksperimente DIY, duke përfshirë kontrollin dhe mbledhjen e të dhënave nga sensorët e sistemit inteligjent të shtëpisë.
  • Një mënyrë e pazakontë për ta përdorur atë është vendosja e një asistenti tregtar të shkëmbimit virtual, një robot tregtar, në server. Ju do të jeni plotësisht përgjegjës për stabilitetin dhe sigurinë e serverit, që do të thotë se do të merrni një instrument të kontrolluar për tregtimin në bursa. Epo, në rast se dikush është i interesuar ose planifikon :)

Ka aplikacione për VPS të tilla në sferën e korporatës. Përveç shërbimit telefonik të përmendur tashmë, mund të zbatoni disa gjëra interesante. Për shembull:

  • Vendosni baza të të dhënave të vogla dhe informacione që do të jenë të arritshme për punonjësit që udhëtojnë në distancë, për shembull, duke përdorur ftp. Kjo do t'ju lejojë të shkëmbeni shumë shpejt analiza të reja, konfigurime të përditësuara për shitësit, prezantime, etj.
  • Jepni akses të përkohshëm përdoruesve ose klientëve për të demonstruar softuer ose media.

VPS test drive për 30 rubla - bërë për ju

30 rubla janë aq pak sa nuk dëshiron të marrësh as një kartë për të paguar dhe testuar. Edhe ne ndonjëherë jemi kaq dembelë, por këtë herë bëmë gjithçka për ju. Përpara se të nisnim serverët në betejë, ne kryem një test për të kontrolluar të gjitha detajet dhe për të treguar se çfarë janë të aftë serverët në këtë tarifë. Për ta bërë më interesante, shtuam ekstremin dhe kontrolluam se si do të sillej ky konfigurim nëse dendësia dhe ngarkesa i kalonin vlerat që vendosëm. 

Pritësi ishte nën ngarkesën e një numri makinash virtuale që kryenin detyra të ndryshme në procesor dhe përdornin në mënyrë aktive nënsistemin e diskut. Qëllimi është të simulojë një densitet të lartë vendosjeje dhe një ngarkesë të krahasueshme ose më të madhe se ajo luftarake.

Përveç ngarkesës konstante, ne instaluam 3 makina virtuale që grumbullonin metrikë sintetike duke përdorur sysbench, rezultatet mesatare të të cilave janë dhënë më poshtë dhe 50 makina virtuale që krijuan ngarkesë shtesë. Të gjitha makinat virtuale testuese kishin të njëjtin konfigurim (1 bërthamë, RAM 512 GB, SSD 10 GB), imazhi standard debian 9.6 u zgjodh si sistemi operativ, i cili u ofrohet përdoruesve në RUVDS.

Ngarkesa u simulua në natyrë dhe madhësi të krahasueshme me luftimin:

  • Disa makina virtuale u lansuan me ngarkesë të ulët
  • Disa makina ekzekutuan një skrip provë që simulonte ngarkesën në procesor (duke përdorur programin stres)
  • Në pjesën e mbetur të makinave virtuale, ne ekzekutuam një skript që përdorte dd për të kopjuar të dhënat nga të dhënat e parapërgatitura në disk me një kufi të caktuar duke përdorur pv (mund të shihen shembuj këtu и këtu).

Gjithashtu, siç ju kujtohet, ne kishim tre makina që mblidhnin metrikë sintetikë.

Në çdo makinë, një skrip ekzekutohej në mënyrë ciklike çdo 15 minuta, i cili kryen teste standarde të sysbench për procesorin, kujtesën dhe diskun.

Skript 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

Rezultatet janë paraqitur për lehtësi në formatin sysbench, por vlerat mesatare për të gjithë periudhën e testimit janë marrë nga të gjitha makinat, rezultati mund të shihet këtu:

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

Rezultatet janë indikative, por ende nuk duhet të merren si QoS. 

Makinat që krijojnë ngarkesë shtesë

Program kompjuterik:

  • apt-get Azhurimi
  • apt-get upgrade
  • apt-get instaloni python-pip
  • pip install mysql-connector-python-rf

Instaluar MariaDB, Si të këtu:

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

Baza e testimit është marrë prandaj:

Baza e të dhënave vendoset siç është specifikuar këtu:

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

Baza e vogël e provës:

Tryezë 

Numri i rreshtave 

Madhësia e të dhënave (MB)

Madhësia e indeksit (KB)

departamentet 

9

0.02

16.00

dept_emp 

331143 

11.52

5648.00

dept_menaxher 

24 

0.02

16.00

Punonjësit 

299379 

14.52

0.00

punonjësit 

2838426 

95.63

0.00 

tituj 

442783 

19.56

0.00

Një shërbim testimi primitiv është shkruar në gju në Python; ai kryen katër operacione:

  1. getState: kthen statusin
  2. getEmployee: kthen punonjësit (+pagat, +titujt) nga baza e të dhënave
  3. patchEmployee: ndryshon fushat e punonjësve
  4. insertSalary: fut një rrogë

Burimi i shërbimit (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')

Kujdes! Në asnjë rrethanë nuk duhet të merret ky shërbim si shembull apo udhëzues!

Testet kryhen duke përdorur JMeter të mirë të vjetër. U nisën një sërë testesh që zgjasin nga 15 minuta deri në 2 orë, pa ndërprerje, përqindja e kërkesave ndryshonte dhe xhiroja varionte nga 300 në 600 kërkesa në minutë. Numri i fijeve nga 50 në 500.

Për shkak të faktit se baza e të dhënave është shumë e vogël, komanda:

mysql -e "SHOW ENGINE INNODB STATUS"

Tregon se:

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

Më poshtë janë koha mesatare e përgjigjes për kërkesat:

Etiketë

mesatare

mesatare

90% Linja

95% Linja

99% Linja

Min

Max

merrepunonjës

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

patchPunonjës

161.42

83.29

308

492.57

1845.14

5

6639.4

vendosPaga

167.21

86.93

315.34

501.07

1927.12

7

6722.44

Mund të jetë e vështirë për ju të gjykoni nga këto rezultate sintetike se sa i përshtatshëm është ky VPS për detyrat tuaja specifike dhe, në përgjithësi, metodat e listuara janë të kufizuara në ato raste që na është dashur të trajtojmë në një formë ose në një tjetër. Pra, lista jonë është qartësisht jo shteruese. Ne ju ftojmë të nxirrni përfundimet tuaja dhe të provoni serverin për 30 rubla në aplikacionet dhe detyrat tuaja reale dhe të sugjeroni opsionet tuaja për këtë konfigurim në komente.

Burimi: www.habr.com

Shto një koment