Barcha kerakli kichik narsalar qo'lda bo'lsa, bu juda yoqimli: yaxshi qalam va bloknot, o'tkir qalam, qulay sichqoncha, bir nechta qo'shimcha simlar va boshqalar. Bu ko'zga tashlanmaydigan narsalar e'tiborni jalb qilmaydi, balki hayotga qulaylik qo'shadi. Xuddi shu voqea turli xil mobil va ish stoli ilovalari bilan bog'liq: uzoq skrinshotlar uchun, rasm hajmini kamaytirish uchun, shaxsiy mablag'larni hisoblash uchun, lug'atlar, tarjimonlar, konvertorlar va boshqalar. Sizda bormi? VPS - qaysi biri arzon, har doim qo'l ostida va ko'p foyda keltiradi? Yo'q, sizning kompaniyangizda bo'lganingiz emas, balki o'zingizning "cho'ntak"ingiz. Biz 2019 yilda kichik VPSsiz, xuddi ma'ruzadagi odatiy qalamsiz bo'lgani kabi, qayg'uli bo'ladi deb o'yladik. Nega xafa bo'lish kerak? Yoz keldi. Yoz qanday? IT mutaxassisi uchun yoz: uyda o'tirib, hech qanday afsuslanmasdan sevimli loyihalaringiz ustida ishlash. Umuman olganda, biz o'yladik va qildik.
Kommunizm keldi, o'rtoqlar.
U shunday - o'ttiz uchun bizning VPS
Biz 3-4 yil oldin nima uchun arzon VPS kerak emasligi haqida yozgan raqobatchilar va foydalanuvchilarning ko'plab maqolalarini o'qidik. To'g'ri, VPS "bir tiyinga" sof marketing edi va oddiy ish imkoniyatlarini taklif qila olmadi. Ammo vaqt o'zgarmoqda, virtual resurslarning narxi pasayib bormoqda va oyiga 30 rubl uchun biz buni taklif qilishga tayyormiz:
Protsessor: Intel Xeon 2 gigagertsli (1 yadroli)
Linux tizimi (tanlash uchun Debian, Ubuntu, CentOS)
1 ta ajratilgan IPv4 manzili
Tezkor korporativ toifadagi SSD disklarida 10 Gb ma'lumotlarni saqlash
Operativ xotira: 512 MB
Bir soniya uchun hisob-kitob
Cheksiz trafik
Tarif qo'shimcha texnik cheklovlarga, tafsilotlarga bog'liq sahifa bizning ajoyib taklifimiz - 30 rubl uchun VPS.
Ushbu virtual server kimga mos keladi? Ha, deyarli hamma uchun: yangi boshlanuvchilar, ishqibozlar, tajribali ishlab chiquvchilar, DIY muxlislari va hatto ba'zi kompaniyalar.
Bu VPS nimaga mos keladi?
O'ylaymizki, Habr o'quvchilari ushbu konfiguratsiyadan foydalanishning o'ziga xos usullarini topadilar, ammo biz o'z tanlovimizni tanlashga qaror qildik - agar kimgadir kerak bo'lsa-chi, lekin erkaklar buni bilishmasa?
Oddiy veb-saytingizni, portfelingizni, kodli rezyumeni va hokazolarni joylashtiring. Albatta, o'zingizning veb-saytingiz ish beruvchida ijobiy taassurot qoldiradi. Uni VPS-ga joylashtiring va sayt xavfsizligi va barqarorligi uchun oddiy xosting provayderlari xodimlari tomonidan emas, balki o'zingiz javobgar bo'ling.
VPS-dan ta'lim maqsadlarida foydalaning: loyihangizni o'tkazing, server va server operatsion tizimining xususiyatlarini o'rganing, DNS bilan tajriba o'tkazing, kichik o'quv sayti bilan ishlang.
Telefoniya uchun. Ba'zida yakka tartibdagi tadbirkor, frilanser yoki juda kichik kompaniya IP-telefoniyaga juda muhtoj va bu telefoniya operatorlari juda ochko'zdir. Hammasi oddiy: biz serverimizni olamiz, IP telefoniya operatoridan raqam sotib olamiz, virtual PBX o'rnatamiz va ichki raqamlarni yaratamiz (agar kerak bo'lsa). Tejamkorlik juda katta.
Ilovalaringizni sinab ko'rish uchun serverdan foydalaning.
Serverdan DIY tajribalari, jumladan, aqlli uy tizimi sensorlaridan maʼlumotlarni boshqarish va yigʻish uchun foydalaning.
Uni ishlatishning noodatiy usuli bu serverga virtual birja savdo yordamchisini, savdo robotini joylashtirishdir. Siz serverning barqarorligi va xavfsizligi uchun to'liq javobgar bo'lasiz, ya'ni siz fond bozorlarida savdo qilish uchun boshqariladigan vositani olasiz. Xo'sh, agar kimdir qiziqsa yoki rejalashtirsa :)
Korporativ sohada bunday VPS uchun ilovalar mavjud. Yuqorida aytib o'tilgan telefon xizmatiga qo'shimcha ravishda siz bir nechta qiziqarli narsalarni amalga oshirishingiz mumkin. Masalan:
Kichkina ma'lumotlar bazalari va ma'lumotlarni masofadan turib sayohat qiluvchi xodimlarga, masalan, ftp-dan foydalanib qo'ying. Bu sizga yangi tahliliy ma'lumotlarni, sotuvchilar uchun yangilangan konfiguratsiyalarni, taqdimotlarni va hokazolarni tezda almashish imkonini beradi.
Foydalanuvchilar yoki mijozlarga dasturiy ta'minot yoki ommaviy axborot vositalarini namoyish qilish uchun vaqtinchalik ruxsat bering.
30 rubl uchun VPS test drayveri - siz uchun qilingan
30 rubl juda oz, siz hatto to'lash va sinov uchun kartani olishni xohlamaysiz. Biz ham ba'zida juda dangasa bo'lamiz, lekin bu safar biz siz uchun hamma narsani qildik. Serverlarni jangga kirishdan oldin biz barcha tafsilotlarni tekshirish va serverlar ushbu tarifda nimaga qodirligini ko'rsatish uchun test o'tkazdik. Buni yanada qiziqarli qilish uchun biz ekstremal qo'shdik va agar zichlik va yuk biz o'rnatgan qiymatlardan oshsa, ushbu konfiguratsiya qanday ishlashini tekshirdik.
Xost protsessorda turli vazifalarni bajaradigan va disk quyi tizimidan faol foydalanadigan bir qator virtual mashinalarning yuki ostida edi. Maqsad, joylashtirishning yuqori zichligini va jangovar bilan solishtiriladigan yoki undan kattaroq yukni taqlid qilishdir.
Doimiy yukga qo'shimcha ravishda biz sysbench yordamida sintetik ko'rsatkichlarni to'playdigan 3 ta virtual mashinani o'rnatdik, ularning o'rtacha natijalari quyida keltirilgan va qo'shimcha yuk yaratgan 50 ta virtual mashina. Barcha sinov virtual mashinalari bir xil konfiguratsiyaga ega edi (1 yadro, RAM 512 GB, SSD 10 GB), RUVDS-da foydalanuvchilarga taqdim etiladigan operatsion tizim sifatida standart debian 9.6 tasviri tanlangan.
Yuk tabiatda taqlid qilingan va kattaligi jangovar bilan taqqoslangan:
Ba'zi virtual mashinalar past yuk bilan ishga tushirildi
Ba'zi mashinalar protsessorga yukni taqlid qiluvchi sinov skriptini ishga tushirdi (yordamchi dastur yordamida stress)
Virtual mashinalarning qolgan qismida biz oldindan tayyorlangan ma'lumotlardan diskka pv yordamida o'rnatilgan chegara bilan ma'lumotlarni nusxalash uchun dd ishlatadigan skriptni ishga tushirdik (misollarni ko'rish mumkin) shu yerda и shu yerda).
Bundan tashqari, siz eslaganingizdek, bizda sintetik ko'rsatkichlarni to'playdigan uchta mashina bor edi.
Har bir mashinada protsessor, xotira va disk uchun standart sysbench testlarini o'tkazadigan skript har 15 daqiqada tsiklik ravishda bajarildi.
sysbench.sh skripti
#!/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
Natijalar qulaylik uchun sysbench formatida taqdim etilgan, ammo butun sinov davri uchun o'rtacha qiymatlar barcha mashinalardan olingan, natijani bu erda ko'rish mumkin:
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
Natijalar ko'rsatkichdir, ammo baribir QoS sifatida qabul qilinmasligi kerak.
Qo'shimcha yuk yaratadigan mashinalar
Dasturiy ta'minot:
apt-get update
apt-get yangilanishi
apt-get install python-pip
pip o'rnating mysql-connector-python-rf
MariaDB o'rnatilgan, qanday qilish kerak shu yerda:
apt-get install libmariadbclient-dev
mysql -e "INSTALL PLUGIN blackhole SONAME 'ha_blackhole.so';" -- нужно для test_employees_sha
Ma'lumotlar bazasi belgilangan tartibda joylashtirilgan shu yerda:
mysql -t < employees.sql
mysql -t < test_employees_sha.sql
Kichik sinov bazasi:
stol
Qatorlar soni
Maʼlumotlar hajmi (MB)
Indeks hajmi (KB)
idoralar
9
0.02
16.00
dept_emp
331143
11.52
5648.00
dept_manager
24
0.02
16.00
xodimlar
299379
14.52
0.00
ish haqi
2838426
95.63
0.00
sarlavhalar
442783
19.56
0.00
Pythonda ibtidoiy test xizmati tizzada yozilgan bo'lib, u to'rtta amalni bajaradi:
getState: holatni qaytaradi
getEmployee: ma'lumotlar bazasidan xodimlarni (+maoshlar, +unvonlar) qaytaradi
patchEmployee: xodimlar maydonlarini o'zgartiradi
insertSalary: ish haqini kiritadi
Xizmat manbai (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')
E'tibor bering! Hech qanday holatda bu xizmatni namuna yoki qo'llanma sifatida qabul qilmaslik kerak!
Sinovlar yaxshi eski JMeter yordamida amalga oshiriladi. 15 daqiqadan 2 soatgacha davom etadigan bir qator test sinovlari uzluksiz ishga tushirildi, so'rovlar foizi turlicha bo'lib, o'tkazish qobiliyati daqiqada 300 dan 600 tagacha bo'lgan. 50 dan 500 gacha bo'lgan iplar soni.
Ma'lumotlar bazasi juda kichik bo'lganligi sababli, buyruq:
mysql -e "SHOW ENGINE INNODB STATUS"
Buni ko'rsatadi:
Buffer pool hit rate 923 / 1000, young-making rate 29 / 1000 not 32 / 1000
Quyida so'rovlarga o'rtacha javob vaqtlari keltirilgan:
belgi
o'rtacha
Media
90% chiziq
95% chiziq
99% chiziq
min
Max
ol.Employee
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
patchXodim
161.42
83.29
308
492.57
1845.14
5
6639.4
ish haqi
167.21
86.93
315.34
501.07
1927.12
7
6722.44
Ushbu sintetik natijalarga ko'ra, ushbu VPS sizning aniq vazifalaringiz uchun qanchalik mos ekanligini aniqlash siz uchun qiyin bo'lishi mumkin va umuman olganda, sanab o'tilgan usullar biz u yoki bu shaklda hal qilishimiz kerak bo'lgan holatlar bilan cheklangan. to'liq emasligi aniq. Biz sizni o'zingizning xulosalaringizni chiqarishga va serverni haqiqiy ilovalaringiz va vazifalaringizga 30 rublga sinab ko'rishni taklif qilamiz va sharhlarda ushbu konfiguratsiya uchun variantlarni taklif qilamiz.