Hjerne + VPS for 30 rubler =?

Det er så fint når alle nødvendige småting er for hånden: en god penn og notisblokk, en spisset blyant, en komfortabel mus, et par ekstra ledninger, etc. Disse upåfallende tingene tiltrekker seg ikke oppmerksomhet, men gir trøst til livet. Den samme historien er med forskjellige mobil- og skrivebordsapplikasjoner: for lange skjermbilder, for å redusere størrelsen på et bilde, for å beregne personlig økonomi, ordbøker, oversettere, konvertere, etc. Har du en? VPS - som er billig, alltid tilgjengelig og gir mange fordeler? Nei, ikke den du har i bedriften din, men din egen "lomme". Vi tenkte at uten en liten VPS i 2019 var det på en måte trist, akkurat som uten den vanlige fyllepennen på en forelesning. Hvorfor være trist? Det er sommer. Hvordan er sommeren? Sommer for en IT-spesialist: å sitte hjemme og jobbe med favorittprosjektene dine uten å angre. Generelt tenkte og gjorde vi det.

Hjerne + VPS for 30 rubler =?
Kommunismen har kommet, kamerater.

Han er sånn - vår VPS for tretti

Vi har lest mange artikler fra konkurrenter og brukere som skrev for 3-4 år siden om hvorfor en rimelig VPS ikke er nødvendig. Vel, det stemmer, da var VPS "for en krone" ren markedsføring og kunne ikke tilby normale arbeidsmuligheter. Men tidene endrer seg, kostnadene for virtuelle ressurser blir lavere og lavere, og for 30 rubler i måneden er vi klare til å tilby dette:

  • Prosessor: Intel Xeon 2 GHz (1 kjerne)
  • Linux-system (Debian, Ubuntu, CentOS å velge mellom)
  • 1 dedikert IPv4-adresse
  • 10 GB datalagring på raske SSD-stasjoner i bedriftsklassen
  • RAM: 512 MB
  • Fakturering per sekund
  • Ubegrenset trafikk

Tariffen er underlagt ytterligere tekniske begrensninger, detaljer om side vårt kule tilbud - VPS for 30 rubler. 

Hvem passer denne virtuelle serveren for? Ja til nesten alle: nybegynnere, entusiaster, erfarne utviklere, DIY-fans og til og med noen selskaper.

Hva er denne VPS egnet for?

Vi tror at Habrs lesere definitivt vil finne sin egen måte å bruke denne konfigurasjonen på, men vi bestemte oss for å samle vårt eget utvalg av ideer - hva om noen trenger det, men mennene ikke vet det?

  • Plasser din enkle nettside, portefølje, CV med kode osv. Selvfølgelig gjør din egendesignede nettside et positivt inntrykk på arbeidsgiveren. Plasser den på din VPS og vær ansvarlig for sikkerheten og stabiliteten til siden selv, og ikke av personalet til vanlige hostingleverandører.
  • Bruk VPS til utdanningsformål: vert for prosjektet ditt, studer funksjonene til server- og serveroperativsystemet, eksperimenter med DNS, triks med et lite pedagogisk nettsted.
  • For telefoni. Noen ganger trenger en individuell gründer, frilanser eller et veldig lite selskap desperat IP-telefoni, og operatørene av akkurat denne telefonien er veldig grådige. Det er enkelt: vi tar serveren vår, kjøper et nummer fra en IP-telefonioperatør, setter opp en virtuell PBX og lager interne numre (om nødvendig). Besparelsene er kolossale.
  • Bruk serveren til å teste applikasjonene dine.
  • Bruk serveren til gjør-det-selv-eksperimenter, inkludert kontroll og innsamling av data fra sensorer til smarthussystemer.
  • En uvanlig måte å bruke den på er å plassere en virtuell børshandelsassistent, en handelsrobot, på serveren. Du vil være fullt ansvarlig for stabiliteten og sikkerheten til serveren, noe som betyr at du vil motta et kontrollert instrument for handel på aksjemarkedene. Vel, i tilfelle noen er interessert eller planlegger :)

Det finnes søknader om slik VPS i bedriftssfæren. I tillegg til den allerede nevnte telefontjenesten, kan du implementere flere interessante ting. For eksempel:

  • Plasser små databaser og informasjon som vil være tilgjengelig for reisende ansatte på avstand, for eksempel ved hjelp av ftp. Dette lar deg veldig raskt utveksle ferske analyser, oppdaterte konfigurasjoner for selgere, presentasjoner, etc.
  • Gi midlertidig tilgang til brukere eller klienter for å demonstrere programvare eller media.

VPS prøvekjøring for 30 rubler - gjort for deg

30 rubler er så lite at du ikke en gang vil ta ut et kort for å betale og teste. Vi er noen ganger så late også, men denne gangen gjorde vi alt for deg. Før vi lanserte serverne i kamp, ​​gjennomførte vi en test for å sjekke alle detaljene og vise hva serverne er i stand til til denne tariffen. For å gjøre det mer interessant, la vi til ekstrem og sjekket hvordan denne konfigurasjonen ville oppføre seg hvis tettheten og belastningen oversteg verdiene vi satte. 

Verten var under belastningen av en rekke virtuelle maskiner som utførte ulike oppgaver på prosessoren og aktivt brukte diskundersystemet. Målet er å simulere en høy plasseringstetthet og en belastning som kan sammenlignes med eller større enn en kamp.

I tillegg til den konstante belastningen, installerte vi 3 virtuelle maskiner som samlet inn syntetiske beregninger ved hjelp av sysbench, hvor gjennomsnittsresultatene ble gitt nedenfor, og 50 virtuelle maskiner som skapte ekstra belastning. Alle virtuelle testmaskiner hadde samme konfigurasjon (1 kjerne, RAM 512 GB, SSD 10 GB), standard debian 9.6-bildet ble valgt som operativsystem, som tilbys brukere på RUVDS.

Lasten ble simulert i natur og størrelse som kan sammenlignes med kamp:

  • Noen virtuelle maskiner ble lansert med lav belastning
  • Noen maskiner kjørte et testskript som simulerte belastningen på prosessoren (ved hjelp av verktøyet stresset)
  • På den gjenværende delen av de virtuelle maskinene kjørte vi et skript som brukte dd for å kopiere data fra forhåndsforberedte data til disk med en grense satt ved bruk av pv (eksempler kan sees her и her).

Som du husker hadde vi også tre maskiner som samlet inn syntetiske beregninger.

På hver maskin ble et skript utført syklisk hvert 15. minutt, som kjører standard sysbench-tester for prosessoren, minnet og disken.

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

Resultatene presenteres for enkelhets skyld i sysbench-format, men gjennomsnittsverdiene for hele testperioden ble hentet fra alle maskiner, resultatet kan ses her:

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

Resultatene er veiledende, men bør fortsatt ikke tas som QoS. 

Maskiner som skaper ekstra belastning

Programvare:

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

Installert MariaDB, hvordan her:

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

Testbase tatt derav:

Databasen distribueres som spesifisert her:

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

Liten testbase:

Bord 

RowsCount 

Datastørrelse (MB)

Indeksstørrelse (KB)

avdelinger 

9

0.02

16.00

dept_emp 

331143 

11.52

5648.00

avd_leder 

24 

0.02

16.00

ansatte 

299379 

14.52

0.00

lønn 

2838426 

95.63

0.00 

titler 

442783 

19.56

0.00

En primitiv testtjeneste er skrevet på kneet i Python; den utfører fire operasjoner:

  1. getState: returnerer statusen
  2. getEmployee: returnerer ansatte (+lønn, +titler) fra databasen
  3. patchEmployee: endrer ansattes felt
  4. insertSalary: setter inn en lønn

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

Advarsel! Under ingen omstendigheter bør denne tjenesten tas som et eksempel eller veiledning!

Tester utføres med gode gamle JMeter. En serie tester som varte fra 15 minutter til 2 timer ble lansert, uten avbrudd, prosentandelen av forespørsler varierte, og gjennomstrømmingen varierte fra 300 til 600 forespørsler per minutt. Antall tråder fra 50 til 500.

På grunn av det faktum at databasen er veldig liten, kommandoen:

mysql -e "SHOW ENGINE INNODB STATUS"

Viser at:

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

Nedenfor er gjennomsnittlig responstid for forespørsler:

Etiketten

Gjennomsnitt

median

90% linje

95% linje

99% linje

Min

max

få ansatt

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

patchAnsatt

161.42

83.29

308

492.57

1845.14

5

6639.4

setteLønn

167.21

86.93

315.34

501.07

1927.12

7

6722.44

Det kan være vanskelig for deg å bedømme ut fra disse syntetiske resultatene hvor egnet denne VPS-en er for dine spesifikke oppgaver, og generelt sett er de oppførte metodene begrenset til de tilfellene vi måtte håndtere i en eller annen form. Så listen vår er tydeligvis ikke uttømmende. Vi inviterer deg til å trekke dine egne konklusjoner og teste serveren for 30 rubler på dine virkelige applikasjoner og oppgaver og foreslå alternativer for denne konfigurasjonen i kommentarene.

Kilde: www.habr.com

Legg til en kommentar