Ubongo + VPS kwa rubles 30 =?

Ni nzuri sana wakati vitu vidogo vyote viko karibu: kalamu nzuri na daftari, penseli iliyoinuliwa, panya ya starehe, waya kadhaa za ziada, nk. Mambo haya yasiyoonekana hayavutii, lakini huongeza faraja kwa maisha. Hadithi sawa ni pamoja na maombi mbalimbali ya simu na kompyuta ya mezani: kwa viwambo vya muda mrefu, kwa kupunguza ukubwa wa picha, kwa kuhesabu fedha za kibinafsi, kamusi, watafsiri, waongofu, nk. Je! unayo? VPS - ambayo ni ya bei nafuu, iko karibu kila wakati na huleta faida nyingi? Hapana, sio ile uliyo nayo katika kampuni yako, lakini yako mwenyewe, "mfukoni" moja. Tulidhani kwamba bila VPS ndogo mnamo 2019 ilikuwa ya kusikitisha kwa njia fulani, kama vile bila kalamu ya kawaida ya chemchemi kwenye hotuba. Kwa nini uwe na huzuni? Ni majira ya joto. Vipi majira ya joto? Majira ya joto kwa mtaalamu wa IT: kukaa nyumbani, kufanya kazi kwenye miradi yako favorite bila majuto yoyote. Kwa ujumla, tulifikiri na kuifanya.

Ubongo + VPS kwa rubles 30 =?
Ukomunisti umefika, wandugu.

Yeye ni kama hivyo - VPS yetu kwa thelathini

Tumesoma makala nyingi kutoka kwa washindani na watumiaji ambao waliandika miaka 3-4 iliyopita kuhusu kwa nini VPS ya gharama nafuu haihitajiki. Kweli, hiyo ni kweli, basi VPS "kwa senti" ilikuwa uuzaji safi na haikuweza kutoa fursa za kawaida za kufanya kazi. Lakini nyakati zinabadilika, gharama ya rasilimali halisi inakuwa chini na chini, na kwa rubles 30 kwa mwezi tuko tayari kutoa hii:

  • Kichakataji: Intel Xeon 2 GHz (msingi 1)
  • Mfumo wa Linux (Debian, Ubuntu, CentOS kuchagua kutoka)
  • Anwani 1 maalum ya IPv4
  • GB 10 ya hifadhi ya data kwenye hifadhi za SSD za kiwango cha biashara haraka
  • RAM: 512 MB
  • Kwa bili ya pili
  • Trafiki isiyo na kikomo

Ushuru unakabiliwa na vikwazo vya ziada vya kiufundi, maelezo juu ukurasa toleo letu la baridi - VPS kwa rubles 30. 

Je, seva hii pepe inafaa kwa ajili ya nani? Ndio kwa karibu kila mtu: wanaoanza, wanaopenda, watengenezaji wenye uzoefu, mashabiki wa DIY na hata kampuni zingine.

VPS hii inafaa kwa nini?

Tunafikiria kwamba wasomaji wa Habr watapata njia yao wenyewe ya kutumia usanidi huu, lakini tuliamua kukusanya maoni yetu wenyewe - vipi ikiwa mtu anahitaji, lakini wanaume hawajui?

  • Weka tovuti yako rahisi, kwingineko, endelea na msimbo, nk. Bila shaka, tovuti yako mwenyewe iliyoundwa hufanya hisia chanya kwa mwajiri. Weka kwenye VPS yako na uwajibike kwa usalama na utulivu wa tovuti mwenyewe, na si kwa wafanyakazi wa watoa huduma wa kawaida wa kukaribisha.
  • Tumia VPS kwa madhumuni ya kielimu: mwenyeji wa mradi wako, soma sifa za seva na mfumo wa uendeshaji wa seva, jaribu DNS, cheza na tovuti ndogo ya elimu.
  • Kwa simu. Wakati mwingine mjasiriamali binafsi, mfanyakazi huru au kampuni ndogo sana huhitaji sana simu ya IP, na waendeshaji wa simu hii ni wachoyo sana. Ni rahisi: tunachukua seva yetu, kununua nambari kutoka kwa operator wa simu ya IP, kuanzisha PBX ya kawaida na kuunda nambari za ndani (ikiwa ni lazima). Akiba ni kubwa sana.
  • Tumia seva kujaribu programu zako.
  • Tumia seva kwa majaribio ya DIY, ikiwa ni pamoja na kudhibiti na kukusanya data kutoka kwa vitambuzi mahiri vya mfumo wa nyumbani.
  • Njia isiyo ya kawaida ya kuitumia ni kuweka msaidizi wa biashara ya kubadilishana mtandaoni, roboti ya biashara, kwenye seva. Utawajibika kikamilifu kwa uthabiti na usalama wa seva, ambayo ina maana kwamba utapokea chombo kinachodhibitiwa cha kufanya biashara kwenye masoko ya hisa. Kweli, ikiwa mtu yeyote ana nia au kupanga :)

Kuna maombi ya VPS kama hii katika nyanja ya ushirika. Mbali na huduma ya simu iliyotajwa tayari, unaweza kutekeleza mambo kadhaa ya kuvutia. Kwa mfano:

  • Weka hifadhidata ndogo na habari ambazo zitapatikana kwa wafanyikazi wanaosafiri kwa mbali, kwa mfano, kwa kutumia ftp. Hii itakuruhusu kubadilishana haraka sana uchanganuzi mpya, usanidi uliosasishwa kwa watu wa mauzo, mawasilisho, n.k.
  • Wape watumiaji au wateja ufikiaji wa muda mfupi ili kuonyesha programu au media.

VPS mtihani gari kwa rubles 30 - kufanyika kwa ajili yenu

Rubles 30 ni kidogo sana kwamba hutaki hata kuchukua kadi ya kulipa na kupima. Wakati mwingine sisi ni wavivu sana, lakini wakati huu tulifanya kila kitu kwa ajili yako. Kabla ya kuzindua seva vitani, tulifanya jaribio ili kuangalia maelezo yote na kuonyesha ni nini seva zinaweza kufanya kwa ushuru huu. Ili kuifanya ipendeze zaidi, tuliongeza uliokithiri na kuangalia jinsi usanidi huu ungefanya ikiwa msongamano na mzigo ulizidi maadili tuliyoweka. 

Mpangishi alikuwa chini ya mzigo wa idadi ya mashine pepe ambazo zilifanya kazi mbalimbali kwenye kichakataji na kutumia kikamilifu mfumo mdogo wa diski. Lengo ni kuiga msongamano mkubwa wa uwekaji na mzigo unaolinganishwa na au mkubwa zaidi kuliko ule wa mapigano.

Kando na upakiaji wa kila mara, tulisakinisha mashine 3 pepe ambazo zilikusanya vipimo vya sintetiki kwa kutumia sysbench, matokeo ya wastani ambayo yalitolewa hapa chini, na mashine 50 pepe zilizounda mzigo wa ziada. Mashine zote pepe za majaribio zilikuwa na usanidi sawa (msingi 1, RAM 512 GB, SSD 10 GB), picha ya kawaida ya debian 9.6 ilichaguliwa kama mfumo wa uendeshaji, ambayo hutolewa kwa watumiaji kwenye RUVDS.

Mzigo uliigwa kwa asili na ukubwa kulinganishwa na mapigano:

  • Baadhi ya mashine pepe zilizinduliwa zikiwa na mzigo mdogo
  • Mashine zingine ziliendesha hati ya jaribio inayoiga mzigo kwenye kichakataji (kwa kutumia matumizi mkazo)
  • Kwenye sehemu iliyobaki ya mashine pepe, tuliendesha hati iliyotumia dd kunakili data kutoka kwa data iliyotayarishwa awali hadi kwenye diski na kikomo kilichowekwa kwa kutumia pv (mifano inaweza kuonekana hapa ΠΈ hapa).

Pia, kama unavyokumbuka, tulikuwa na mashine tatu zilizokusanya vipimo vya sintetiki.

Kwenye kila mashine, hati ilitekelezwa kwa mzunguko kila baada ya dakika 15, ambayo huendesha majaribio ya kawaida ya sysbench kwa kichakataji, kumbukumbu na diski.

Hati 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

Matokeo yanawasilishwa kwa urahisi katika muundo wa sysbench, lakini maadili ya wastani ya kipindi chote cha majaribio yalichukuliwa kutoka kwa mashine zote, matokeo yanaweza kuonekana hapa:

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

Matokeo ni dalili, lakini bado hayapaswi kuchukuliwa kama QoS. 

Mashine zinazounda mzigo wa ziada

Programu:

  • anayeweza kupata-update
  • kuboresha kuboresha
  • kupata-kupata python-pip
  • bomba kufunga mysql-connector-python-rf

Imewekwa MariaDB, Jinsi ya hapa:

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

Msingi wa mtihani umechukuliwa hivyo:

Hifadhidata imetumwa kama ilivyoainishwa hapa:

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

Msingi wa jaribio la ujazo mdogo:

Meza 

RowsCount 

Ukubwa wa data (MB)

Ukubwa wa faharasa (KB)

idara 

9

0.02

16.00

dept_emp 

331143 

11.52

5648.00

meneja_wa_dept 

24 

0.02

16.00

wafanyakazi 

299379 

14.52

0.00

mishahara 

2838426 

95.63

0.00 

majina 

442783 

19.56

0.00

Huduma ya mtihani wa awali imeandikwa kwenye goti huko Python; hufanya shughuli nne:

  1. getState: inarudisha hali
  2. getEmployee: hurejesha wafanyakazi (+mishahara, +vyeo) kutoka kwa hifadhidata
  3. kirakaMfanyakazi: hubadilisha nyanja za wafanyikazi
  4. kuingizaMshahara: kuingiza mshahara

Chanzo cha huduma (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')

Attention! Kwa hali yoyote ile huduma hii isichukuliwe kama mfano au mwongozo!

Vipimo hufanywa kwa kutumia JMeter nzuri ya zamani. Msururu wa majaribio ya kuanzia dakika 15 hadi saa 2 ulizinduliwa, bila kukatizwa, asilimia ya maombi ilitofautiana, na matokeo yalitofautiana kutoka maombi 300 hadi 600 kwa dakika. Idadi ya nyuzi kutoka 50 hadi 500.

Kwa sababu ya ukweli kwamba hifadhidata ni ndogo sana, amri:

mysql -e "SHOW ENGINE INNODB STATUS"

Inaonyesha kuwa:

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

Zifuatazo ni nyakati za wastani za kujibu maombi:

Chapa

wastani

Kati

90%Mstari

95%Mstari

99%Mstari

Min

Max

pata Mfanyakazi

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

kirakaMfanyakazi

161.42

83.29

308

492.57

1845.14

5

6639.4

wekaMshahara

167.21

86.93

315.34

501.07

1927.12

7

6722.44

Inaweza kuwa vigumu kwako kuhukumu kutokana na matokeo haya ya syntetisk jinsi VPS hii inavyofaa kwa kazi zako maalum na, kwa ujumla, mbinu zilizoorodheshwa ni mdogo kwa kesi hizo ambazo tulipaswa kushughulikia kwa namna moja au nyingine. wazi sio kamili. Tunakualika ufanye hitimisho lako mwenyewe na ujaribu seva kwa rubles 30 kwenye programu na kazi zako halisi na upendekeze chaguzi zako za usanidi huu kwenye maoni.

Chanzo: mapenzi.com

Kuongeza maoni