Brein + VPS vir 30 roebels =?

Dit is so lekker as al die nodige klein goedjies byderhand is: 'n goeie pen en notaboek, 'n skerpgemaakte potlood, 'n gemaklike muis, 'n paar ekstra drade, ens. Hierdie onopvallende dinge trek nie aandag nie, maar voeg troos by die lewe. Dieselfde storie is met verskeie mobiele en rekenaartoepassings: vir lang skermskote, om die grootte van 'n prent te verklein, vir die berekening van persoonlike finansies, woordeboeke, vertalers, omskakelaars, ens. Het jy een? VPS - wat goedkoop is, altyd byderhand en baie voordele inhou? Nee, nie die een wat jy in jou geselskap het nie, maar jou eie, "sak" een. Ons het gedink dat dit sonder 'n klein VPS in 2019 op een of ander manier hartseer was, net soos sonder die gewone vulpen by 'n lesing. Hoekom hartseer wees? Dit is somer. Hoe gaan dit met die somer? Somer vir 'n IT-spesialis: sit by die huis, werk sonder enige spyt aan jou gunstelingprojekte. Oor die algemeen het ons dit gedink en gedoen.

Brein + VPS vir 30 roebels =?
Kommunisme het aangebreek, kamerade.

Hy is so - ons VPS vir dertig

Ons het baie artikels gelees van mededingers en gebruikers wat 3-4 jaar gelede geskryf het oor hoekom 'n goedkoop VPS nie nodig is nie. Wel, dit is reg, dan was VPS "vir 'n sent" pure bemarking en kon nie normale werksgeleenthede bied nie. Maar tye verander, die koste van virtuele hulpbronne word al hoe laer, en vir 30 roebels per maand is ons gereed om dit aan te bied:

  • Verwerker: Intel Xeon 2 GHz (1 kern)
  • Linux-stelsel (Debian, Ubuntu, CentOS om van te kies)
  • 1 toegewyde IPv4-adres
  • 10 GB databerging op vinnige ondernemingsklas SSD-aandrywers
  • RAM: 512 MB
  • Per sekonde faktuur
  • Onbeperkte verkeer

Die tarief is onderhewig aan bykomende tegniese beperkings, besonderhede oor bladsy ons cool aanbod - VPS vir 30 roebels. 

Vir wie is hierdie virtuele bediener geskik? Ja vir byna almal: beginners, entoesiaste, ervare ontwikkelaars, selfdoen-aanhangers en selfs sommige maatskappye.

Waarvoor is hierdie VPS geskik?

Ons dink dat Habr se lesers beslis hul eie manier sal vind om hierdie konfigurasie te gebruik, maar ons het besluit om ons eie keuse van idees te versamel - wat as iemand dit nodig het, maar die mans weet nie?

  • Plaas jou eenvoudige webwerf, portefeulje, CV met kode, ens. Natuurlik maak jou eie ontwerpte webwerf 'n positiewe indruk op die werkgewer. Plaas dit op jou VPS en wees self verantwoordelik vir die sekuriteit en stabiliteit van die webwerf, en nie deur die personeel van gereelde gasheerverskaffers nie.
  • Gebruik VPS vir opvoedkundige doeleindes: huisves jou projek, bestudeer die kenmerke van die bediener en bedienerbedryfstelsel, eksperimenteer met DNS, peuter met 'n klein opvoedkundige webwerf.
  • Vir telefonie. Soms het 'n individuele entrepreneur, vryskut of 'n baie klein maatskappy IP-telefonie desperaat nodig, en die operateurs van hierdie einste telefonie is baie gulsig. Dit is eenvoudig: ons neem ons bediener, koop 'n nommer by 'n IP-telefonie-operateur, stel 'n virtuele PBX op en skep interne nommers (indien nodig). Die besparings is kolossaal.
  • Gebruik die bediener om jou toepassings te toets.
  • Gebruik die bediener vir selfdoen-eksperimente, insluitend die beheer en versameling van data vanaf slimhuisstelselsensors.
  • 'n Ongewone manier om dit te gebruik, is om 'n virtuele ruilhandelassistent, 'n handelsrobot, op die bediener te plaas. Jy sal ten volle verantwoordelik wees vir die stabiliteit en sekuriteit van die bediener, wat beteken dat jy 'n beheerde instrument sal ontvang vir verhandeling op die aandelemarkte. Wel, ingeval iemand belangstel of beplan :)

Daar is aansoeke vir sulke VPS in die korporatiewe sfeer. Benewens die reeds genoemde telefoondiens, kan u verskeie interessante dinge implementeer. Byvoorbeeld:

  • Plaas klein databasisse en inligting wat toeganklik sal wees vir reisende werknemers op 'n afstand, byvoorbeeld deur ftp te gebruik. Dit sal jou toelaat om baie vinnig vars ontledings, opgedateerde konfigurasies vir verkoopspersone, aanbiedings, ens.
  • Gee tydelike toegang aan gebruikers of kliënte om sagteware of media te demonstreer.

VPS-toetsrit vir 30 roebels - gedoen vir jou

30 roebels is so min dat jy nie eers 'n kaart wil uithaal om te betaal en te toets nie. Ons is ook soms so lui, maar hierdie keer het ons alles vir jou gedoen. Voordat ons die bedieners in die geveg begin het, het ons 'n toets uitgevoer om al die besonderhede na te gaan en te wys waartoe die bedieners teen hierdie tarief in staat is. Om dit interessanter te maak, het ons ekstreem bygevoeg en gekyk hoe hierdie konfigurasie sou optree as die digtheid en las die waardes wat ons gestel het oorskry. 

Die gasheer was onder die las van 'n aantal virtuele masjiene wat verskeie take op die verwerker uitgevoer het en die skyfsubstelsel aktief gebruik het. Die doel is om 'n hoë digtheid van plasing en 'n las vergelykbaar met of groter as 'n geveg een te simuleer.

Benewens die konstante las, het ons 3 virtuele masjiene geïnstalleer wat sintetiese statistieke met behulp van sysbench versamel het, waarvan die gemiddelde resultate hieronder gegee is, en 50 virtuele masjiene wat bykomende vrag geskep het. Alle virtuele toetsmasjiene het dieselfde konfigurasie gehad (1 kern, RAM 512 GB, SSD 10 GB), die standaard debian 9.6-beeld is gekies as die bedryfstelsel, wat aan gebruikers op RUVDS aangebied word.

Die las is gesimuleer in aard en omvang vergelykbaar met gevegte:

  • Sommige virtuele masjiene is met lae vrag bekendgestel
  • Sommige masjiene het 'n toetsskrip uitgevoer wat die las op die verwerker simuleer (met die hulpprogram stres)
  • Op die oorblywende deel van die virtuele masjiene het ons 'n skrip laat loop wat dd gebruik het om data van vooraf voorbereide data na skyf te kopieer met 'n limiet gestel met behulp van pv (voorbeelde kan gesien word hier и hier).

Ook, soos jy onthou, het ons drie masjiene gehad wat sintetiese statistieke ingesamel het.

Op elke masjien is 'n skrip elke 15 minute siklies uitgevoer, wat standaard sysbench-toetse vir die verwerker, geheue en skyf laat loop.

Skrip 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

Die resultate word gerieflikheidshalwe in sysbench-formaat aangebied, maar die gemiddelde waardes vir die hele toetsperiode is van alle masjiene geneem, die resultaat kan hier gesien word:

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

Die resultate is aanduidend, maar moet steeds nie as QoS geneem word nie. 

Masjiene wat bykomende vrag skep

Sagteware:

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

Geïnstalleer MariaDB, hoe om hier:

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

Toetsbasis geneem vandaar:

Die databasis word ontplooi soos gespesifiseer hier:

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

Klein toetsbasis:

Tabel 

RowsCount 

Datagrootte (MB)

Indeksgrootte (KB)

departemente 

9

0.02

16.00

dept_emp 

331143 

11.52

5648.00

afd_bestuurder 

24 

0.02

16.00

werknemers 

299379 

14.52

0.00

werknemers 

2838426 

95.63

0.00 

titels 

442783 

19.56

0.00

'n Primitiewe toetsdiens word in Python op die knie geskryf; dit voer vier bewerkings uit:

  1. getState: gee die status terug
  2. getEmployee: gee werknemers (+salarisse, +titels) terug vanaf die databasis
  3. patchEmployee: verander werknemervelde
  4. insertSalary: voeg 'n salaris in

Diensbron (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')

Внимание! Hierdie diens moet onder geen omstandighede as 'n voorbeeld of gids geneem word nie!

Toetse word uitgevoer met behulp van goeie ou JMeter. 'n Reeks toetse wat van 15 minute tot 2 uur duur is van stapel gestuur, sonder onderbrekings, die persentasie versoeke het gewissel, en deurset het gewissel van 300 tot 600 versoeke per minuut. Aantal drade van 50 tot 500.

As gevolg van die feit dat die databasis baie klein is, word die opdrag:

mysql -e "SHOW ENGINE INNODB STATUS"

Wys dat:

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

Hieronder is die gemiddelde reaksietye vir versoeke:

etiket

Gemiddeld

mediaan

90% lyn

95% lyn

99% lyn

Min

Max

kry Werknemer

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

pleister Werknemer

161.42

83.29

308

492.57

1845.14

5

6639.4

sit Salaris

167.21

86.93

315.34

501.07

1927.12

7

6722.44

Dit kan vir jou moeilik wees om uit hierdie sintetiese resultate te oordeel hoe geskik hierdie VPS is vir jou spesifieke take en oor die algemeen is die gelyste metodes beperk tot daardie gevalle wat ons in een of ander vorm moes hanteer. So ons lys is duidelik nie volledig nie. Ons nooi u uit om u eie gevolgtrekkings te maak en die bediener vir 30 roebels op u regte toepassings en take te toets en u opsies vir hierdie konfigurasie in die kommentaar voor te stel.

Bron: will.com

Voeg 'n opmerking