Gehirn + VPS für 30 Rubel =?

Es ist so schön, wenn alle notwendigen Kleinigkeiten zur Hand sind: ein guter Stift und Notizblock, ein angespitzter Bleistift, eine komfortable Maus, ein paar zusätzliche Kabel usw. Diese unauffälligen Dinge erregen keine Aufmerksamkeit, sondern bringen Komfort ins Leben. Das Gleiche gilt für verschiedene Mobil- und Desktop-Anwendungen: für lange Screenshots, zur Verkleinerung eines Bildes, zur Berechnung persönlicher Finanzen, Wörterbücher, Übersetzer, Konverter usw. Hast du eins? VPS - was günstig ist, immer griffbereit ist und viele Vorteile bringt? Nein, nicht das, das Sie in Ihrem Unternehmen haben, sondern Ihr eigenes „Taschen“-Gerät. Wir fanden, dass es 2019 ohne einen kleinen VPS irgendwie traurig war, genauso wie ohne den üblichen Füllfederhalter bei einer Vorlesung. Warum traurig sein? Es ist Sommer. Wie ist der Sommer? Sommer für einen IT-Spezialisten: Zu Hause sitzen und ohne Reue an Ihren Lieblingsprojekten arbeiten. Im Allgemeinen haben wir darüber nachgedacht und es getan.

Gehirn + VPS für 30 Rubel =?
Der Kommunismus ist angekommen, Genossen.

Er ist so – unser VPS für dreißig

Wir haben viele Artikel von Wettbewerbern und Benutzern gelesen, die vor 3-4 Jahren darüber geschrieben haben, warum ein preiswerter VPS nicht benötigt wird. Nun ja, das ist richtig, dann war VPS „für einen Cent“ reines Marketing und konnte keine normalen Arbeitsmöglichkeiten bieten. Aber die Zeiten ändern sich, die Kosten für virtuelle Ressourcen werden immer niedriger und für 30 Rubel im Monat sind wir bereit, Folgendes anzubieten:

  • Prozessor: Intel Xeon 2 GHz (1 Kern)
  • Linux-System (Debian, Ubuntu, CentOS zur Auswahl)
  • 1 dedizierte IPv4-Adresse
  • 10 GB Datenspeicher auf schnellen SSD-Laufwerken der Enterprise-Klasse
  • RAM: 512 MB
  • Abrechnung pro Sekunde
  • Unbegrenzter Verkehr

Der Tarif unterliegt weiteren technischen Einschränkungen, Einzelheiten unter Seite unser cooles Angebot - VPS für 30 Rubel. 

Für wen ist dieser virtuelle Server geeignet? Ja, für fast alle: Anfänger, Enthusiasten, erfahrene Entwickler, DIY-Fans und sogar einige Unternehmen.

Wofür ist dieser VPS geeignet?

Wir glauben, dass die Leser von Habr definitiv ihre eigene Art und Weise finden werden, diese Konfiguration zu nutzen, aber wir haben uns entschieden, unsere eigene Auswahl an Ideen zu sammeln – was ist, wenn jemand es braucht, die Männer es aber nicht wissen?

  • Platzieren Sie Ihre einfache Website, Ihr Portfolio, Ihren Lebenslauf mit Code usw. Natürlich hinterlässt eine selbst gestaltete Website einen positiven Eindruck beim Arbeitgeber. Platzieren Sie es auf Ihrem VPS und seien Sie selbst für die Sicherheit und Stabilität der Website verantwortlich und nicht die Mitarbeiter regulärer Hosting-Anbieter.
  • Nutzen Sie VPS für Bildungszwecke: Hosten Sie Ihr Projekt, studieren Sie die Funktionen des Servers und des Server-Betriebssystems, experimentieren Sie mit DNS, basteln Sie an einer kleinen Bildungsseite.
  • Für Telefonie. Manchmal braucht ein Einzelunternehmer, Freiberufler oder ein sehr kleines Unternehmen dringend IP-Telefonie, und die Betreiber dieser Telefonie sind sehr gierig. Es ist ganz einfach: Wir nehmen unseren Server, kaufen eine Nummer von einem IP-Telefonanbieter, richten eine virtuelle PBX ein und erstellen interne Nummern (falls erforderlich). Die Einsparungen sind enorm.
  • Nutzen Sie den Server, um Ihre Anwendungen zu testen.
  • Nutzen Sie den Server für DIY-Experimente, einschließlich der Steuerung und Erfassung von Daten von Smart-Home-Systemsensoren.
  • Eine ungewöhnliche Art der Nutzung besteht darin, einen virtuellen Börsenassistenten, einen Handelsroboter, auf dem Server zu platzieren. Sie tragen die volle Verantwortung für die Stabilität und Sicherheit des Servers und erhalten somit ein kontrolliertes Instrument für den Handel an den Börsen. Na ja, falls jemand Interesse hat oder plant :)

Es gibt Anwendungen für solche VPS im Unternehmensbereich. Neben dem bereits erwähnten Telefonservice können Sie noch einige interessante Dinge umsetzen. Zum Beispiel:

  • Platzieren Sie kleine Datenbanken und Informationen, die für reisende Mitarbeiter aus der Ferne zugänglich sind, beispielsweise über FTP. Dadurch können Sie sehr schnell neue Analysen, aktualisierte Konfigurationen für Vertriebsmitarbeiter, Präsentationen usw. austauschen.
  • Gewähren Sie Benutzern oder Kunden vorübergehenden Zugriff, um Software oder Medien vorzuführen.

VPS-Probefahrt für 30 Rubel – erledigt für Sie

30 Rubel sind so wenig, dass man zum Bezahlen und Testen nicht einmal eine Karte herausnehmen möchte. Wir sind manchmal auch so faul, aber dieses Mal haben wir alles für Sie getan. Bevor wir die Server in den Kampf schicken, haben wir einen Test durchgeführt, um alle Details zu überprüfen und zu zeigen, wozu die Server in diesem Tarif fähig sind. Um es interessanter zu machen, haben wir Extreme hinzugefügt und überprüft, wie sich diese Konfiguration verhalten würde, wenn Dichte und Last die von uns festgelegten Werte überschreiten würden. 

Der Host wurde von einer Reihe virtueller Maschinen belastet, die verschiedene Aufgaben auf dem Prozessor ausführten und das Festplattensubsystem aktiv nutzten. Ziel ist es, eine hohe Platzierungsdichte und eine Belastung zu simulieren, die mit einer Kampfbelastung vergleichbar oder größer ist.

Zusätzlich zur konstanten Last haben wir drei virtuelle Maschinen installiert, die mithilfe von Sysbench synthetische Metriken gesammelt haben, deren durchschnittliche Ergebnisse unten aufgeführt sind, und 3 virtuelle Maschinen, die zusätzliche Last verursacht haben. Alle virtuellen Testmaschinen hatten die gleiche Konfiguration (50 Kern, RAM 1 GB, SSD 512 GB), als Betriebssystem wurde das Standard-Debian 10-Image ausgewählt, das Benutzern auf RUVDS angeboten wird.

Die Belastung wurde in Art und Ausmaß mit einem Kampf vergleichbar simuliert:

  • Einige virtuelle Maschinen wurden mit geringer Last gestartet
  • Einige Maschinen führten ein Testskript aus, das die Auslastung des Prozessors simulierte (mithilfe des Dienstprogramms). Der Stress)
  • Auf dem verbleibenden Teil der virtuellen Maschinen haben wir ein Skript ausgeführt, das dd verwendet, um Daten von vorab vorbereiteten Daten auf die Festplatte zu kopieren, wobei die Grenze mithilfe von pv festgelegt wurde (Beispiele sind zu sehen). hier и hier).

Wie Sie sich erinnern, hatten wir außerdem drei Maschinen, die synthetische Metriken sammelten.

Auf jeder Maschine wurde zyklisch alle 15 Minuten ein Skript ausgeführt, das Standard-Sysbench-Tests für Prozessor, Speicher und Festplatte durchführt.

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

Die Ergebnisse werden der Einfachheit halber im Sysbench-Format dargestellt, die Durchschnittswerte für den gesamten Testzeitraum wurden jedoch von allen Maschinen übernommen, das Ergebnis ist hier zu sehen:

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 Ergebnisse sind Richtwerte, sollten jedoch nicht als QoS angesehen werden. 

Maschinen, die zusätzliche Belastung erzeugen

Software:

  • apt-get update
  • apt-get-Aktualisierung
  • apt-get installiert python-pip
  • pip install mysql-connector-python-rf

MariaDB installiert, Anleitung hier:

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

Testbasis belegt daher:

Die Datenbank wird wie angegeben bereitgestellt hier:

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

Testbasis für kleine Volumina:

Tisch 

RowsCount 

Datengröße (MB)

Indexgröße (KB)

Abteilungen 

9

0.02

16.00

dept_emp 

331143 

11.52

5648.00

dept_manager 

24 

0.02

16.00

Mitarbeiter 

299379 

14.52

0.00

Gehälter 

2838426 

95.63

0.00 

Titel 

442783 

19.56

0.00

Ein primitiver Testdienst ist in Python auf dem Knie geschrieben; er führt vier Operationen aus:

  1. getState: gibt den Status zurück
  2. getEmployee: gibt Mitarbeiter (+Gehälter, +Titel) aus der Datenbank zurück
  3. patchEmployee: Ändert Mitarbeiterfelder
  4. insertSalary: fügt ein Gehalt ein

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

Achtung! Auf keinen Fall darf dieser Service als Beispiel oder Leitfaden verstanden werden!

Tests werden mit dem guten alten JMeter durchgeführt. Es wurde eine Reihe von Tests mit einer Dauer von 15 Minuten bis 2 Stunden ohne Unterbrechungen gestartet, der Prozentsatz der Anfragen variierte und der Durchsatz schwankte zwischen 300 und 600 Anfragen pro Minute. Anzahl der Threads von 50 bis 500.

Da die Datenbank sehr klein ist, lautet der Befehl:

mysql -e "SHOW ENGINE INNODB STATUS"

Zeigt, dass:

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

Nachfolgend sind die durchschnittlichen Antwortzeiten für Anfragen aufgeführt:

Label

Durchschnittlich

Median

90% Linie

95% Linie

99% Linie

Min.

Max

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

patchMitarbeiter

161.42

83.29

308

492.57

1845.14

5

6639.4

putGehalt

167.21

86.93

315.34

501.07

1927.12

7

6722.44

Es kann für Sie schwierig sein, anhand dieser synthetischen Ergebnisse zu beurteilen, wie geeignet dieser VPS für Ihre spezifischen Aufgaben ist, und im Allgemeinen beschränken sich die aufgeführten Methoden auf die Fälle, mit denen wir uns in der einen oder anderen Form befassen mussten. Unsere Liste ist also offensichtlich nicht erschöpfend. Wir laden Sie ein, Ihre eigenen Schlussfolgerungen zu ziehen und den Server für 30 Rubel für Ihre realen Anwendungen und Aufgaben zu testen und in den Kommentaren Ihre Optionen für diese Konfiguration vorzuschlagen.

Source: habr.com

Kommentar hinzufügen