Brain + VPS za 30 rubalja =?

Tako je lijepo kada su sve potrebne sitnice pri ruci: dobra olovka i blok za pisanje, naoštrena olovka, udoban miš, par dodatnih žica itd. Ove neupadljive stvari ne privlače pozornost, ali dodaju udobnost životu. Ista je priča s raznim mobilnim i stolnim aplikacijama: za duge screenshotove, za smanjivanje veličine slike, za izračun osobnih financija, rječnicima, prevoditeljima, konverterima itd. Da li imaš jedan? VPS - što je jeftino, uvijek pri ruci i donosi mnogo koristi? Ne, ne onu koju imate u svojoj firmi, već svoju, “džepnu”. Mislili smo da je bez malog VPS-a 2019. nekako tužna, baš kao i bez uobičajenog nalivpera na predavanju. Zašto biti tužan? Ljeto je. Kako je ljeto? Ljeto za IT stručnjaka: sjedite kod kuće, radite na omiljenim projektima bez imalo žaljenja. Općenito, mislili smo i učinili.

Brain + VPS za 30 rubalja =?
Stigao je komunizam, drugovi.

Takav je on – naš VPS za trideset

Pročitali smo mnogo članaka konkurenata i korisnika koji su prije 3-4 godine pisali o tome zašto jeftini VPS nije potreban. E, tako je, tada je VPS "za peni" bio čisti marketing i nije mogao ponuditi normalne radne prilike. Ali vremena se mijenjaju, cijena virtualnih resursa postaje sve niža i niža, a za 30 rubalja mjesečno spremni smo ponuditi ovo:

  • Procesor: Intel Xeon 2 GHz (1 jezgra)
  • Linux sustav (Debian, Ubuntu, CentOS na izbor)
  • 1 namjenska IPv4 adresa
  • 10 GB pohrane podataka na brzim SSD diskovima poslovne klase
  • RAM: 512 MB
  • Naplata po sekundi
  • Neograničen promet

Tarifa podliježe dodatnim tehničkim ograničenjima, pojedinosti o stranica naša cool ponuda - VPS za 30 rubalja. 

Za koga je ovaj virtualni poslužitelj prikladan? Da gotovo svima: početnicima, entuzijastima, iskusnim programerima, ljubiteljima DIY pa čak i nekim tvrtkama.

Za što je ovaj VPS prikladan?

Mislimo da će čitatelji Habra sigurno pronaći svoj način korištenja ove konfiguracije, ali odlučili smo prikupiti vlastiti izbor ideja - što ako nekome treba, a muškarci ne znaju?

  • Postavite svoju jednostavnu web stranicu, portfelj, životopis s kodom itd. Naravno, vlastito dizajnirana web stranica ostavlja pozitivan dojam na poslodavca. Postavite ga na svoj VPS i budite odgovorni za sigurnost i stabilnost stranice sami, a ne osoblje redovnih pružatelja usluga hostinga.
  • Koristite VPS u obrazovne svrhe: hostirajte svoj projekt, proučite značajke poslužitelja i operacijskog sustava poslužitelja, eksperimentirajte s DNS-om, petljajte s malim obrazovnim mjestom.
  • Za telefoniju. Ponekad je individualnom poduzetniku, freelanceru ili vrlo maloj tvrtki prijeko potrebna IP telefonija, a operateri upravo te telefonije su vrlo pohlepni. Jednostavno: uzmemo naš server, kupimo broj od operatera IP telefonije, postavimo virtualnu PBX i napravimo interne brojeve (ako je potrebno). Uštede su kolosalne.
  • Koristite poslužitelj za testiranje svojih aplikacija.
  • Koristite poslužitelj za DIY eksperimente, uključujući kontrolu i prikupljanje podataka sa senzora sustava pametne kuće.
  • Neobičan način korištenja je postavljanje pomoćnika za trgovanje virtualnom razmjenom, robota za trgovanje, na poslužitelj. Vi ćete biti u potpunosti odgovorni za stabilnost i sigurnost servera, što znači da ćete dobiti kontrolirani instrument za trgovanje na burzama. Pa ako nekoga zanima ili planira :)

Postoje aplikacije za takav VPS u korporativnoj sferi. Uz već spomenutu telefonsku uslugu, možete implementirati nekoliko zanimljivih stvari. Na primjer:

  • Postavite male baze podataka i informacije koje će biti dostupne zaposlenicima koji putuju na daljinu, na primjer, koristeći ftp. To će vam omogućiti vrlo brzu razmjenu svježe analitike, ažurirane konfiguracije za prodavače, prezentacije itd.
  • Dajte privremeni pristup korisnicima ili klijentima za demonstraciju softvera ili medija.

VPS testna vožnja za 30 rubalja - gotovo za vas

30 rubalja je toliko malo da ne želite čak ni izvaditi karticu za plaćanje i testiranje. I mi smo ponekad tako lijeni, ali ovaj put smo učinili sve za vas. Prije lansiranja poslužitelja u bitku, proveli smo test kako bismo provjerili sve detalje i pokazali što su poslužitelji sposobni po ovoj tarifi. Da bismo ga učinili zanimljivijim, dodali smo ekstrem i provjerili kako bi se ova konfiguracija ponašala ako gustoća i opterećenje premaše vrijednosti koje smo postavili. 

Host je bio opterećen nizom virtualnih strojeva koji su obavljali različite zadatke na procesoru i aktivno koristili diskovni podsustav. Cilj je simulirati veliku gustoću postavljanja i opterećenje usporedivo ili veće od borbenog.

Uz konstantno opterećenje, instalirali smo 3 virtualna računala koja su prikupljala sintetičke metrike pomoću sysbench-a, čiji su prosječni rezultati navedeni u nastavku, te 50 virtualnih računala koja su stvarala dodatno opterećenje. Sva testna virtualna računala imala su istu konfiguraciju (1 jezgra, RAM 512 GB, SSD 10 GB), kao operativni sustav odabran je standardni debian 9.6 image koji se korisnicima nudi na RUVDS-u.

Opterećenje je simulirano u prirodi, a veličina je usporediva s borbenim:

  • Neka su virtualna računala pokrenuta s malim opterećenjem
  • Neka su računala pokrenula testnu skriptu koja simulira opterećenje procesora (pomoću uslužnog programa stres)
  • Na preostalom dijelu virtualnih strojeva pokrenuli smo skriptu koja je koristila dd za kopiranje podataka iz unaprijed pripremljenih podataka na disk uz limit postavljen pomoću pv (primjeri se mogu vidjeti здесь и здесь).

Također, kao što se sjećate, imali smo tri stroja koji su prikupljali sintetičke metrike.

Na svakom stroju, skripta se ciklički izvršavala svakih 15 minuta, koja pokreće standardne sysbench testove za procesor, memoriju i disk.

Skripta 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

Rezultati su predstavljeni radi praktičnosti u sysbench formatu, ali prosječne vrijednosti za cijelo razdoblje testiranja uzete su sa svih strojeva, rezultat se može vidjeti ovdje:

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

Rezultati su indikativni, ali ih ipak ne treba uzeti kao QoS. 

Strojevi koji stvaraju dodatno opterećenje

Softver:

  • apt-get ažuriranje
  • apt-get nadogradnju
  • apt-get instalirati python-pip
  • pip instalirajte mysql-connector-python-rf

Instalirao MariaDB, kako ovdje:

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

Testna baza uzeta stoga:

Baza podataka je raspoređena kako je navedeno ovdje:

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

Mala testna baza:

Stol 

RowsCount 

Veličina podataka (MB)

Veličina indeksa (KB)

odjeli 

9

0.02

16.00

odjel_emp 

331143 

11.52

5648.00

voditelj_odjela 

24 

0.02

16.00

zaposlenici 

299379 

14.52

0.00

plaće 

2838426 

95.63

0.00 

naslovi 

442783 

19.56

0.00

Primitivna testna usluga napisana je na koljenu u Pythonu; izvodi četiri operacije:

  1. getState: vraća status
  2. getEmployee: vraća zaposlenike (+plaće, +titule) iz baze podataka
  3. patchEmployee: mijenja polja zaposlenika
  4. insertSalary: umeće plaću

Izvor usluge (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')

Upozorenje! Ni pod kojim uvjetima ovu uslugu ne smijete uzimati kao primjer ili vodič!

Testovi se izvode pomoću dobrog starog JMetera. Pokrenuta je serija testova u trajanju od 15 minuta do 2 sata, bez prekida, postotak zahtjeva je varirao, a protok je varirao od 300 do 600 zahtjeva u minuti. Broj niti od 50 do 500.

Zbog činjenice da je baza podataka vrlo mala, naredba:

mysql -e "SHOW ENGINE INNODB STATUS"

Pokazuje da:

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

Ispod su prosječna vremena odgovora na zahtjeve:

Označiti

prosjek

srednja

90% linija

95% linija

99% linija

Min

maksimum

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

patchZaposlenik

161.42

83.29

308

492.57

1845.14

5

6639.4

staviPlaća

167.21

86.93

315.34

501.07

1927.12

7

6722.44

Možda će vam biti teško procijeniti na temelju ovih sintetičkih rezultata koliko je ovaj VPS prikladan za vaše specifične zadatke i, općenito, navedene metode ograničene su na one slučajeve s kojima smo se morali suočiti u ovom ili onom obliku. Stoga je naš popis očito nije iscrpan. Pozivamo vas da sami donesete zaključke i testirate poslužitelj za 30 rubalja na svojim stvarnim aplikacijama i zadacima te predložite svoje mogućnosti za ovu konfiguraciju u komentarima.

Izvor: www.habr.com

Dodajte komentar