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.
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
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.
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:
getState: returnerer statusen
getEmployee: returnerer ansatte (+lønn, +titler) fra databasen
patchEmployee: endrer ansattes felt
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.