Otak + VPS seharga 30 rubel =?

Sangat menyenangkan ketika semua hal kecil yang diperlukan sudah tersedia: pena dan buku catatan yang bagus, pensil tajam, mouse yang nyaman, beberapa kabel tambahan, dll. Hal-hal yang tidak mencolok ini tidak menarik perhatian, tetapi menambah kenyamanan hidup. Cerita yang sama terjadi pada berbagai aplikasi seluler dan desktop: untuk tangkapan layar yang panjang, untuk memperkecil ukuran gambar, untuk menghitung keuangan pribadi, kamus, penerjemah, konverter, dll. Apakah kamu punya satu? VPS - mana yang murah, selalu tersedia dan membawa banyak manfaat? Bukan, bukan yang Anda miliki di perusahaan Anda, tapi yang β€œkantong” Anda sendiri. Kami pikir tanpa VPS kecil di tahun 2019 rasanya menyedihkan, seperti tanpa pulpen biasa di kuliah. Mengapa sedih? Ini musim panas. Bagaimana musim panas? Musim panas untuk spesialis IT: duduk di rumah, mengerjakan proyek favorit Anda tanpa penyesalan. Secara umum, kami memikirkan dan melakukannya.

Otak + VPS seharga 30 rubel =?
Komunisme telah tiba, kawan.

Dia seperti itu - VPS kami untuk tiga puluh

Kami telah membaca banyak artikel dari pesaing dan pengguna yang menulis 3-4 tahun yang lalu tentang mengapa VPS murah tidak diperlukan. Benar sekali, VPS β€œuntuk satu sen” adalah murni pemasaran dan tidak dapat menawarkan peluang kerja normal. Namun zaman terus berubah, biaya sumber daya virtual semakin rendah, dan untuk 30 rubel sebulan kami siap menawarkan ini:

  • Prosesor: Intel Xeon 2GHz (1 inti)
  • Sistem Linux (Debian, Ubuntu, CentOS untuk dipilih)
  • 1 alamat IPv4 khusus
  • Penyimpanan data sebesar 10 GB pada drive SSD kelas perusahaan yang cepat
  • RAM: 512 MB
  • Penagihan per detik
  • Lalu lintas tidak terbatas

Tarif tunduk pada batasan teknis tambahan, rinciannya tentang halaman penawaran keren kami - VPS seharga 30 rubel. 

Untuk siapa server virtual ini cocok? Ya untuk hampir semua orang: pemula, penggemar, pengembang berpengalaman, penggemar DIY, dan bahkan beberapa perusahaan.

Untuk apa VPS ini cocok?

Kami pikir pembaca Habr pasti akan menemukan cara mereka sendiri dalam menggunakan konfigurasi ini, tetapi kami memutuskan untuk mengumpulkan ide-ide pilihan kami sendiri - bagaimana jika seseorang membutuhkannya, tetapi para pria tidak mengetahuinya?

  • Tempatkan situs web sederhana Anda, portofolio, resume dengan kode, dll. Tentu saja, situs web yang Anda rancang sendiri memberikan kesan positif bagi pemberi kerja. Tempatkan di VPS Anda dan bertanggung jawab sendiri atas keamanan dan stabilitas situs, dan bukan oleh staf penyedia hosting biasa.
  • Gunakan VPS untuk tujuan pendidikan: host proyek Anda, pelajari fitur server dan sistem operasi server, bereksperimen dengan DNS, bermain-main dengan situs pendidikan kecil.
  • Untuk telepon. Terkadang seorang pengusaha perorangan, pekerja lepas, atau perusahaan yang sangat kecil sangat membutuhkan telepon IP, dan operator telepon ini sangat rakus. Sederhana saja: kami mengambil server kami, membeli nomor dari operator telepon IP, menyiapkan PBX virtual, dan membuat nomor internal (jika perlu). Penghematannya sangat besar.
  • Gunakan server untuk menguji aplikasi Anda.
  • Gunakan server untuk eksperimen DIY, termasuk mengendalikan dan mengumpulkan data dari sensor sistem rumah pintar.
  • Cara yang tidak biasa untuk menggunakannya adalah dengan menempatkan asisten perdagangan pertukaran virtual, robot perdagangan, di server. Anda akan bertanggung jawab penuh atas stabilitas dan keamanan server, yang berarti Anda akan menerima instrumen terkontrol untuk berdagang di pasar saham. Nah, kalau-kalau ada yang tertarik atau berencana :)

Ada aplikasi untuk VPS semacam itu di lingkungan korporat. Selain layanan telepon yang telah disebutkan, Anda dapat menerapkan beberapa hal menarik. Misalnya:

  • Tempatkan database kecil dan informasi yang dapat diakses oleh karyawan yang bepergian dari jarak jauh, misalnya menggunakan ftp. Ini akan memungkinkan Anda dengan cepat bertukar analisis baru, konfigurasi terbaru untuk staf penjualan, presentasi, dll.
  • Memberikan akses sementara kepada pengguna atau klien untuk mendemonstrasikan perangkat lunak atau media.

Test drive VPS seharga 30 rubel - selesai untuk Anda

30 rubel sangat sedikit sehingga Anda bahkan tidak ingin mengeluarkan kartu untuk membayar dan mengujinya. Kami terkadang sangat malas juga, tapi kali ini kami melakukan segalanya untuk Anda. Sebelum meluncurkan server ke dalam pertempuran, kami melakukan tes untuk memeriksa semua detail dan menunjukkan kemampuan server pada tarif ini. Untuk membuatnya lebih menarik, kami menambahkan ekstrem dan memeriksa bagaimana konfigurasi ini akan berperilaku jika kepadatan dan beban melebihi nilai yang kami tetapkan. 

Host berada di bawah beban sejumlah mesin virtual yang melakukan berbagai tugas pada prosesor dan secara aktif menggunakan subsistem disk. Tujuannya adalah untuk mensimulasikan penempatan dengan kepadatan tinggi dan beban yang sebanding atau lebih besar dari beban tempur.

Selain beban konstan, kami memasang 3 mesin virtual yang mengumpulkan metrik sintetis menggunakan sysbench, yang hasil rata-ratanya diberikan di bawah, dan 50 mesin virtual yang menghasilkan beban tambahan. Semua mesin virtual pengujian memiliki konfigurasi yang sama (1 inti, RAM 512 GB, SSD 10 GB), image standar debian 9.6 dipilih sebagai sistem operasi, yang ditawarkan kepada pengguna di RUVDS.

Bebannya disimulasikan sifat dan besarnya sebanding dengan pertempuran:

  • Beberapa mesin virtual diluncurkan dengan beban rendah
  • Beberapa mesin menjalankan skrip pengujian yang mensimulasikan beban pada prosesor (menggunakan utilitas tekanan)
  • Di sisa mesin virtual, kami menjalankan skrip yang menggunakan dd untuk menyalin data dari data yang telah disiapkan sebelumnya ke disk dengan batas yang ditetapkan menggunakan pv (contoh dapat dilihat di sini ΠΈ di sini).

Selain itu, seperti yang Anda ingat, kami memiliki tiga mesin yang mengumpulkan metrik sintetis.

Pada setiap mesin, skrip dijalankan secara siklis setiap 15 menit, yang menjalankan pengujian sysbench standar untuk prosesor, memori, dan disk.

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

Hasilnya disajikan untuk kemudahan dalam format sysbench, namun nilai rata-rata seluruh periode pengujian diambil dari semua mesin, hasilnya dapat dilihat di sini:

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

Hasilnya hanya bersifat indikatif, namun tetap tidak boleh dianggap sebagai QoS. 

Mesin yang menciptakan beban tambahan

Perangkat lunak:

  • Update apt-get
  • peningkatan apt-get
  • apt-get install python-pip
  • pip instal konektor-mysql-python-rf

Menginstal MariaDB, Bagaimana caranya di sini:

apt-get install libmariadbclient-dev
mysql -e "INSTALL PLUGIN blackhole SONAME 'ha_blackhole.so';" -- Π½ΡƒΠΆΠ½ΠΎ для test_employees_sha

Basis tes diambil karenanya:

Basis data disebarkan seperti yang ditentukan di sini:

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

Basis tes kecil:

tabel 

Jumlah Baris 

Ukuran data (MB)

Ukuran indeks (KB)

departemen 

9

0.02

16.00

dept_emp 

331143 

11.52

5648.00

dept_manager 

24 

0.02

16.00

karyawan 

299379 

14.52

0.00

gaji 

2838426 

95.63

0.00 

judul 

442783 

19.56

0.00

Layanan pengujian primitif ditulis dengan Python; ia melakukan empat operasi:

  1. getState: mengembalikan status
  2. getEmployee: mengembalikan karyawan (+gaji, +jabatan) dari database
  3. patchEmployee: mengubah bidang karyawan
  4. insertSalary: memasukkan gaji

Sumber layanan (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')

Peringatan! Dalam situasi apa pun layanan ini tidak boleh dijadikan contoh atau panduan!

Pengujian dilakukan menggunakan JMeter lama yang bagus. Serangkaian pengujian yang berlangsung dari 15 menit hingga 2 jam diluncurkan, tanpa gangguan, persentase permintaan bervariasi, dan throughput bervariasi dari 300 hingga 600 permintaan per menit. Jumlah utas dari 50 hingga 500.

Karena databasenya sangat kecil, perintahnya:

mysql -e "SHOW ENGINE INNODB STATUS"

Menunjukkan bahwa:

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

Di bawah ini adalah waktu respons rata-rata untuk permintaan:

label

Biasa saja

rata-rata

Garis 90%.

Garis 95%.

Garis 99%.

Min

max

dapatkan Karyawan

37.64

12.57

62.28

128.5

497.57

5

4151.78

dapatkanState

17

7.57

30.14

58.71

193

3

2814.71

patchKaryawan

161.42

83.29

308

492.57

1845.14

5

6639.4

masukkan Gaji

167.21

86.93

315.34

501.07

1927.12

7

6722.44

Mungkin sulit bagi Anda untuk menilai dari hasil sintetik ini seberapa cocok VPS ini untuk tugas spesifik Anda dan, secara umum, metode yang tercantum terbatas pada kasus-kasus yang harus kami tangani dalam satu bentuk atau lainnya. jelas tidak menyeluruh. Kami mengundang Anda untuk menarik kesimpulan Anda sendiri dan menguji server seharga 30 rubel pada aplikasi dan tugas Anda yang sebenarnya dan menyarankan opsi Anda untuk konfigurasi ini di komentar.

Sumber: www.habr.com

Tambah komentar