Ուղեղ + VPS 30 ռուբլու համար =?

Այնքան հաճելի է, երբ բոլոր անհրաժեշտ մանրուքները ձեռքի տակ են՝ լավ գրիչ և նոթատետր, սրած մատիտ, հարմարավետ մկնիկ, մի քանի լրացուցիչ լար և այլն: Այս աննկատ բաները ուշադրություն չեն գրավում, այլ հարմարավետություն են հաղորդում կյանքին։ Նույն պատմությունն է բջջային և աշխատասեղանի տարբեր հավելվածների դեպքում՝ երկար սքրինշոթների, նկարի չափը փոքրացնելու, անձնական ֆինանսների, բառարանների, թարգմանիչների, փոխարկիչների և այլնի համար: Դուք ունե՞ք մեկը: VPS - որն էժան է, միշտ ձեռքի տակ և բերում է շատ օգուտներ: Ո՛չ, ոչ թե նա, ով ունես քո ընկերությունում, այլ քո սեփական, «գրպանային»։ Մենք կարծում էինք, որ առանց փոքր VPS-ի 2019-ին ինչ-որ կերպ տխուր էր, ինչպես առանց դասախոսության սովորական շատրվանի գրչի: Ինչու՞ տխուր լինել: ամառ է։ Ինչպե՞ս է ամառը: Ամառ ՏՏ մասնագետի համար՝ նստել տանը, աշխատել սիրելի նախագծերի վրա՝ առանց ափսոսանքի։ Ընդհանուր առմամբ, մենք մտածեցինք և արեցինք դա։

Ուղեղ + VPS 30 ռուբլու համար =?
Կոմունիզմը եկել է, ընկերներ։

Նա այդպիսին է՝ մեր VPS-ը երեսունի համար

Մենք կարդացել ենք բազմաթիվ հոդվածներ մրցակիցների և օգտատերերի կողմից, ովքեր գրել էին 3-4 տարի առաջ այն մասին, թե ինչու էժան VPS-ի կարիք չկա: Դե, դա ճիշտ է, այնուհետև VPS-ը «մի կոպեկի համար» մաքուր շուկայավարություն էր և չէր կարող նորմալ աշխատանքային հնարավորություններ առաջարկել: Բայց ժամանակները փոխվում են, վիրտուալ ռեսուրսների արժեքը գնալով նվազում է, և ամսական 30 ռուբլով մենք պատրաստ ենք առաջարկել սա.

  • Պրոցեսոր՝ Intel Xeon 2 ԳՀց (1 միջուկ)
  • Linux համակարգ (Debian, Ubuntu, CentOS՝ ընտրելու համար)
  • 1 հատուկ IPv4 հասցե
  • 10 ԳԲ տվյալների պահեստավորում արագ ձեռնարկատիրական կարգի SSD կրիչներում
  • RAM՝ 512 ՄԲ
  • Մեկ վայրկյանի հաշվարկ
  • Անսահմանափակ երթեւեկություն

Սակագինը ենթակա է լրացուցիչ տեխնիկական սահմանափակումների, մանրամասները էջ մեր զով առաջարկը՝ VPS 30 ռուբլով: 

Ո՞ւմ համար է հարմար այս վիրտուալ սերվերը: Այո գրեթե բոլորին՝ սկսնակների, էնտուզիաստների, փորձառու մշակողների, DIY երկրպագուների և նույնիսկ որոշ ընկերությունների:

Ինչի՞ համար է հարմար այս VPS-ը:

Մենք կարծում ենք, որ Habr-ի ընթերցողները անպայման կգտնեն այս կոնֆիգուրացիան օգտագործելու իրենց ձևը, բայց մենք որոշեցինք հավաքել գաղափարների մեր ընտրությունը. իսկ եթե ինչ-որ մեկին դա անհրաժեշտ լինի, բայց տղամարդիկ չգիտեն:

  • Տեղադրեք ձեր պարզ կայքը, պորտֆոլիոն, ռեզյումեն կոդով և այլն: Իհարկե, ձեր սեփական նախագծված կայքը դրական տպավորություն է թողնում գործատուի վրա: Տեղադրեք այն ձեր VPS-ում և ինքներդ պատասխանատու եղեք կայքի անվտանգության և կայունության համար, և ոչ թե սովորական հոսթինգ պրովայդերների անձնակազմի կողմից:
  • Օգտագործեք VPS կրթական նպատակներով. հյուրընկալեք ձեր նախագիծը, ուսումնասիրեք սերվերի և սերվերի օպերացիոն համակարգի առանձնահատկությունները, փորձարկեք DNS-ի հետ, վարեք փոքր կրթական կայք:
  • Հեռախոսակապի համար. Երբեմն անհատ ձեռներեցին, ֆրիլանսերին կամ շատ փոքր ընկերությանը հուսահատ կարիք ունի IP հեռախոսակապ, և հենց այս հեռախոսակապի օպերատորները շատ ագահ են: Դա պարզ է՝ մենք վերցնում ենք մեր սերվերը, համար ենք գնում IP հեռախոսակապի օպերատորից, տեղադրում ենք վիրտուալ PBX և ստեղծում ներքին համարներ (անհրաժեշտության դեպքում): Խնայողությունները հսկայական են.
  • Օգտագործեք սերվերը ձեր հավելվածները փորձարկելու համար:
  • Օգտագործեք սերվերը DIY փորձերի համար, ներառյալ խելացի տան համակարգի սենսորներից տվյալների վերահսկման և հավաքագրման համար:
  • Այն օգտագործելու անսովոր միջոց է սերվերի վրա տեղադրել վիրտուալ բորսայի առևտրի օգնական՝ առևտրային ռոբոտ: Դուք լիովին պատասխանատու կլինեք սերվերի կայունության և անվտանգության համար, ինչը նշանակում է, որ դուք կստանաք վերահսկվող գործիք ֆոնդային շուկաներում առևտրի համար: Դե, եթե որևէ մեկը հետաքրքրված է կամ պլանավորում է :)

Նման VPS-ի համար հավելվածներ կան կորպորատիվ ոլորտում։ Բացի արդեն նշված հեռախոսային ծառայությունից, դուք կարող եք իրականացնել մի քանի հետաքրքիր բաներ. Օրինակ:

  • Տեղադրեք փոքր տվյալների բազաներ և տեղեկատվություն, որոնք հասանելի կլինեն ճանապարհորդող աշխատակիցներին հեռավորության վրա, օրինակ՝ օգտագործելով ftp: Սա թույլ կտա ձեզ շատ արագ փոխանակել թարմ վերլուծություններ, թարմացված կոնֆիգուրացիաներ վաճառողների համար, շնորհանդեսներ և այլն:
  • Ժամանակավոր մուտք գործեք օգտատերերին կամ հաճախորդներին՝ ծրագրակազմը կամ մեդիան ցուցադրելու համար:

VPS թեստային սկավառակ 30 ռուբլով - արված է ձեզ համար

30 ռուբլին այնքան քիչ է, որ նույնիսկ չես ուզում քարտ հանել վճարելու և ստուգելու համար: Մենք էլ երբեմն այնքան ալարկոտ ենք լինում, բայց այս անգամ ամեն ինչ արեցինք ձեզ համար։ Մինչ սերվերները մարտի դուրս բերելը, մենք թեստ ենք անցկացրել՝ ստուգելու բոլոր մանրամասները և ցույց տալու, թե ինչի են ընդունակ սերվերները այս սակագնով։ Այն ավելի հետաքրքիր դարձնելու համար մենք ավելացրեցինք ծայրահեղությունը և ստուգեցինք, թե ինչպես կվարվի այս կոնֆիգուրացիան, եթե խտությունը և ծանրաբեռնվածությունը գերազանցեն մեր սահմանած արժեքները: 

Հոսթերը գտնվում էր մի շարք վիրտուալ մեքենաների ծանրաբեռնվածության տակ, որոնք տարբեր առաջադրանքներ էին կատարում պրոցեսորի վրա և ակտիվորեն օգտագործում սկավառակի ենթահամակարգը։ Նպատակն է նմանակել տեղակայման բարձր խտությունը և մարտականին համեմատելի կամ ավելի մեծ բեռ:

Բացի մշտական ​​ծանրաբեռնվածությունից, մենք տեղադրեցինք 3 վիրտուալ մեքենաներ, որոնք հավաքում էին սինթետիկ չափումներ՝ օգտագործելով sysbench, որի միջին արդյունքները ներկայացված են ստորև, և 50 վիրտուալ մեքենաներ, որոնք լրացուցիչ բեռ են ստեղծում: Բոլոր փորձնական վիրտուալ մեքենաներն ունեին նույն կոնֆիգուրացիան (1 միջուկ, օպերատիվ հիշողություն 512 ԳԲ, SSD 10 ԳԲ), որպես օպերացիոն համակարգ ընտրվել է ստանդարտ debian 9.6 պատկերը, որն առաջարկվում է RUVDS-ով օգտվողներին:

Բեռը մոդելավորվել է իր բնույթով և մեծությամբ, որը համեմատելի է մարտական ​​գործողությունների հետ.

  • Որոշ վիրտուալ մեքենաներ գործարկվել են ցածր բեռնվածությամբ
  • Որոշ մեքենաներ գործարկեցին պրոցեսորի բեռը մոդելավորող թեստային սցենար (օգտագործելով կոմունալ ծրագիրը շեշտ)
  • Վիրտուալ մեքենաների մնացած մասում մենք գործարկեցինք մի սկրիպտ, որն օգտագործում էր dd տվյալները նախապես պատրաստված տվյալներից սկավառակի վրա պատճենելու համար՝ սահմանաչափով, օգտագործելով pv (օրինակները կարելի է տեսնել այստեղ и այստեղ).

Նաև, ինչպես հիշում եք, մենք ունեինք երեք մեքենա, որոնք հավաքում էին սինթետիկ չափումներ:

Յուրաքանչյուր մեքենայի վրա 15 րոպեն մեկ ցիկլային կերպով կատարվում էր սկրիպտ, որն իրականացնում է պրոցեսորի, հիշողության և սկավառակի ստանդարտ sysbench թեստեր:

Սցենար 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

Արդյունքները ներկայացված են հարմարության համար sysbench ձևաչափով, բայց փորձարկման ողջ ժամանակահատվածի միջին արժեքները վերցվել են բոլոր մեքենաներից, արդյունքը կարելի է տեսնել այստեղ.

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

Արդյունքները ցուցիչ են, բայց դեռ չպետք է ընդունվեն որպես QoS: 

Մեքենաներ, որոնք ստեղծում են լրացուցիչ բեռ

Փափուկ:

  • բն - ստանալ թարմացումը
  • ստացեք նորացում
  • apt-get install python-pip- ը
  • pip install mysql-connector-python-rf

Տեղադրված MariaDB, Ինչպես այստեղ:

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

Վերցված փորձարկման հիմքը ուստի:

Տվյալների բազան տեղադրվում է ինչպես նշված է այստեղ:

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

Փոքր ծավալի փորձարկման բազա.

Սեղան 

Տողերի քանակ 

Տվյալների չափը (MB)

Ինդեքսի չափը (ԿԲ)

բաժանմունքները 

9

0.02

16.00

dept_emp 

331143 

11.52

5648.00

dept_manager 

24 

0.02

16.00

աշխատակիցներ 

299379 

14.52

0.00

աշխատավարձը 

2838426 

95.63

0.00 

վերնագրերը 

442783 

19.56

0.00

Python-ում ծնկի վրա գրված է պարզունակ թեստային ծառայություն, որն իրականացնում է չորս գործողություն.

  1. getState: վերադարձնում է կարգավիճակը
  2. getEmployee. տվյալների բազայից վերադարձնում է աշխատակիցներին (+աշխատավարձեր, + կոչումներ):
  3. patchEmployee. փոխում է աշխատողների դաշտերը
  4. ներդիրԱշխատավարձ. մտցնում է աշխատավարձ

Ծառայության աղբյուրը (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')

Զգուշացում! Ոչ մի դեպքում չպետք է այս ծառայությունը ընկալվի որպես օրինակ կամ ուղեցույց:

Թեստերը կատարվում են հին լավ JMeter-ի միջոցով: Գործարկվել է 15 րոպեից մինչև 2 ժամ տևողությամբ մի շարք թեստեր, առանց ընդհատումների, հարցումների տոկոսը տարբերվում էր, իսկ թողունակությունը տատանվում էր րոպեում 300-ից մինչև 600 հարցում: Թելերի քանակը 50-ից մինչև 500:

Շնորհիվ այն բանի, որ տվյալների բազան շատ փոքր է, հրամանը.

mysql -e "SHOW ENGINE INNODB STATUS"

Ցույց է տալիս, որ.

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

Ստորև ներկայացված են հարցումների պատասխանների միջին ժամանակը.

պիտակ

Միջին

Median

90% Գիծ

95% Գիծ

99% Գիծ

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

patchԱշխատակից

161.42

83.29

308

492.57

1845.14

5

6639.4

դրել Աշխատավարձ

167.21

86.93

315.34

501.07

1927.12

7

6722.44

Հնարավոր է, որ ձեզ համար դժվար լինի դատել այս սինթետիկ արդյունքներից, թե որքանով է այս VPS-ը հարմար ձեր հատուկ առաջադրանքների համար, և, ընդհանուր առմամբ, թվարկված մեթոդները սահմանափակվում են այն դեպքերով, որոնց հետ մենք ստիպված էինք այս կամ այն ​​ձևով զբաղվել: Այսպիսով, մեր ցուցակը հետևյալն է. ակնհայտորեն սպառիչ չէ: Մենք ձեզ հրավիրում ենք անել ձեր սեփական եզրակացությունները և փորձարկել սերվերը 30 ռուբլով ձեր իրական ծրագրերի և առաջադրանքների վրա և առաջարկել այս կազմաձևման ձեր տարբերակները մեկնաբանություններում:

Source: www.habr.com

Добавить комментарий