Brain + VPS ในราคา 30 รูเบิล =?

จะดีมากเมื่อมีของเล็กๆ น้อยๆ ที่จำเป็นอยู่ในมือ เช่น ปากกาและสมุดโน้ตดีๆ ดินสอเหลา เมาส์ที่นุ่มสบาย สายไฟพิเศษสองสามเส้น ฯลฯ สิ่งที่ไม่เด่นเหล่านี้ไม่ดึงดูดความสนใจ แต่เพิ่มความสะดวกสบายให้กับชีวิต เรื่องเดียวกันนี้เกิดขึ้นกับแอปพลิเคชันบนมือถือและเดสก์ท็อปต่างๆ: สำหรับภาพหน้าจอขนาดยาว, สำหรับการลดขนาดรูปภาพ, สำหรับการคำนวณการเงินส่วนบุคคล, พจนานุกรม, นักแปล, โปรแกรมแปลงไฟล์ ฯลฯ คุณมีอันหนึ่งไหม? VPS - อันไหนราคาถูก เข้าถึงได้เสมอ และให้ประโยชน์มากมาย? ไม่ ไม่ใช่สิ่งที่คุณมีในบริษัท แต่เป็น "กระเป๋า" ของคุณเอง เราคิดว่าหากไม่มี VPS เล็กๆ ในปี 2019 มันก็น่าเศร้า เหมือนกับการไม่มีปากกาหมึกซึมตามปกติในการบรรยาย ทำไมต้องเศร้า? มันคือหน้าร้อน. ฤดูร้อนเป็นยังไงบ้าง? ฤดูร้อนสำหรับผู้เชี่ยวชาญด้านไอที: นั่งอยู่บ้านทำงานโปรเจ็กต์ที่คุณชื่นชอบโดยไม่เสียใจ โดยทั่วไปเราคิดและทำ

Brain + VPS ในราคา 30 รูเบิล =?
คอมมิวนิสต์มาถึงแล้วสหาย

เขาเป็นเช่นนั้น - VPS ของเราเป็นเวลาสามสิบ

เราได้อ่านบทความมากมายจากคู่แข่งและผู้ใช้ที่เขียนเมื่อ 3-4 ปีที่แล้วเกี่ยวกับสาเหตุที่ไม่จำเป็นต้องใช้ VPS ที่ราคาไม่แพง ถูกต้องแล้ว VPS “เพียงเพนนี” เป็นเพียงการตลาดล้วนๆ และไม่สามารถเสนอโอกาสในการทำงานตามปกติได้ แต่เวลากำลังเปลี่ยนแปลง ต้นทุนของทรัพยากรเสมือนกำลังลดลงเรื่อยๆ และเราพร้อมที่จะเสนอสิ่งนี้ในราคา 30 รูเบิลต่อเดือน:

  • หน่วยประมวลผล: Intel Xeon 2 GHz (1 คอร์)
  • ระบบ Linux (Debian, Ubuntu, CentOS ให้เลือก)
  • 1 ที่อยู่ IPv4 เฉพาะ
  • พื้นที่จัดเก็บข้อมูล 10 GB บนไดรฟ์ SSD ระดับองค์กรที่รวดเร็ว
  • แรม: 512 เมกะไบต์
  • การเรียกเก็บเงินต่อวินาที
  • การจราจรไม่ จำกัด

อัตราภาษีขึ้นอยู่กับข้อจำกัดทางเทคนิคเพิ่มเติม โปรดดูรายละเอียดที่ หน้า ข้อเสนอสุดพิเศษของเรา - VPS ในราคา 30 รูเบิล 

เซิร์ฟเวอร์เสมือนนี้เหมาะกับใครบ้าง? ใช่สำหรับเกือบทุกคน: ผู้เริ่มต้น ผู้สนใจ นักพัฒนาที่มีประสบการณ์ แฟน DIY และแม้แต่บางบริษัท

VPS นี้เหมาะกับอะไร?

เราคิดว่าผู้อ่านของ Habr คงจะพบวิธีการใช้การกำหนดค่านี้ในแบบของตัวเองอย่างแน่นอน แต่เราตัดสินใจรวบรวมแนวคิดที่เราคัดสรรมาเอง - จะเกิดอะไรขึ้นถ้ามีคนต้องการมัน แต่ผู้ชายไม่รู้ล่ะ

  • วางเว็บไซต์เรียบง่าย พอร์ตโฟลิโอ ประวัติย่อพร้อมโค้ด ฯลฯ แน่นอนว่าเว็บไซต์ที่คุณออกแบบเองนั้นสร้างความประทับใจเชิงบวกให้กับนายจ้าง วางมันไว้บน VPS ของคุณและรับผิดชอบด้านความปลอดภัยและเสถียรภาพของเว็บไซต์ด้วยตัวเอง ไม่ใช่โดยเจ้าหน้าที่ของผู้ให้บริการโฮสติ้งทั่วไป
  • ใช้ VPS เพื่อการศึกษา: โฮสต์โครงการของคุณ ศึกษาคุณสมบัติของเซิร์ฟเวอร์และระบบปฏิบัติการเซิร์ฟเวอร์ ทดลองกับ DNS ปรับแต่งกับไซต์การศึกษาขนาดเล็ก
  • สำหรับโทรศัพท์. บางครั้งผู้ประกอบการรายบุคคล นักแปลอิสระ หรือบริษัทขนาดเล็กมากต้องการระบบโทรศัพท์ IP อย่างมาก และผู้ดำเนินการระบบโทรศัพท์นี้ก็โลภมาก ง่ายมาก: เราใช้เซิร์ฟเวอร์ของเรา ซื้อหมายเลขจากผู้ให้บริการโทรศัพท์ IP ตั้งค่า PBX เสมือน และสร้างหมายเลขภายใน (หากจำเป็น) เงินออมมีมหาศาล
  • ใช้เซิร์ฟเวอร์เพื่อทดสอบแอปพลิเคชันของคุณ
  • ใช้เซิร์ฟเวอร์สำหรับการทดลอง DIY รวมถึงการควบคุมและรวบรวมข้อมูลจากเซ็นเซอร์ระบบสมาร์ทโฮม
  • วิธีใช้งานที่ผิดปกติคือการวางผู้ช่วยการซื้อขายแลกเปลี่ยนเสมือน ซึ่งเป็นหุ่นยนต์ซื้อขายบนเซิร์ฟเวอร์ คุณจะต้องรับผิดชอบอย่างเต็มที่ต่อความเสถียรและความปลอดภัยของเซิร์ฟเวอร์ ซึ่งหมายความว่าคุณจะได้รับเครื่องมือที่มีการควบคุมสำหรับการซื้อขายในตลาดหุ้น เอาล่ะ เผื่อมีใครสนใจหรือกำลังวางแผน :)

มีแอปพลิเคชันสำหรับ VPS ดังกล่าวในขอบเขตองค์กร นอกจากบริการโทรศัพท์ที่กล่าวไปแล้วคุณยังสามารถใช้สิ่งที่น่าสนใจหลายประการได้ ตัวอย่างเช่น:

  • วางฐานข้อมูลและข้อมูลขนาดเล็กที่พนักงานที่เดินทางสามารถเข้าถึงได้จากระยะไกล เช่น การใช้ ftp สิ่งนี้จะช่วยให้คุณสามารถแลกเปลี่ยนการวิเคราะห์ใหม่ๆ การกำหนดค่าที่อัปเดตสำหรับพนักงานขาย การนำเสนอ และอื่นๆ ได้อย่างรวดเร็ว
  • ให้สิทธิ์การเข้าถึงชั่วคราวแก่ผู้ใช้หรือไคลเอนต์เพื่อสาธิตซอฟต์แวร์หรือสื่อ

ทดลองขับ VPS ในราคา 30 รูเบิล - ทำเพื่อคุณ

30 รูเบิลนั้นน้อยมากจนคุณไม่อยากหยิบการ์ดออกมาจ่ายและทดสอบด้วยซ้ำ บางครั้งเราก็ขี้เกียจเหมือนกัน แต่คราวนี้เราทำทุกอย่างเพื่อคุณ ก่อนที่จะเปิดตัวเซิร์ฟเวอร์สู่การรบ เราได้ทำการทดสอบเพื่อตรวจสอบรายละเอียดทั้งหมดและแสดงให้เห็นว่าเซิร์ฟเวอร์มีความสามารถอะไรบ้างในอัตรานี้ เพื่อให้น่าสนใจยิ่งขึ้น เราได้เพิ่มขีดสุดและตรวจสอบว่าการกำหนดค่านี้จะทำงานอย่างไรหากความหนาแน่นและโหลดเกินค่าที่เราตั้งไว้ 

โฮสต์อยู่ภายใต้การโหลดของเครื่องเสมือนจำนวนหนึ่งซึ่งทำงานต่าง ๆ บนโปรเซสเซอร์และใช้ระบบย่อยของดิสก์อย่างแข็งขัน เป้าหมายคือการจำลองตำแหน่งที่มีความหนาแน่นสูงและน้ำหนักที่เทียบเท่าหรือมากกว่าการรบ

นอกเหนือจากโหลดคงที่แล้ว เรายังติดตั้งเครื่องเสมือน 3 เครื่องที่รวบรวมตัววัดสังเคราะห์โดยใช้ sysbench ผลลัพธ์โดยเฉลี่ยแสดงไว้ด้านล่าง และเครื่องเสมือน 50 เครื่องที่สร้างภาระงานเพิ่มเติม เครื่องเสมือนทดสอบทั้งหมดมีการกำหนดค่าเหมือนกัน (1 คอร์, RAM 512 GB, SSD 10 GB) เลือกอิมเมจเดเบียนมาตรฐาน 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
  • apt-get upgrade
  • apt-get install python-pip
  • pip ติดตั้ง 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)

ขนาดดัชนี (KB)

หน่วยงาน 

9

0.02

16.00

dept_emp 

331143 

11.52

5648.00

แผนก_ผู้จัดการ 

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. insertSalary: แทรกเงินเดือน

แหล่งบริการ (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

ด้านล่างนี้เป็นเวลาตอบกลับโดยเฉลี่ยสำหรับคำขอ:

ฉลาก

กลาง

มัธยฐาน

เส้น 90%

เส้น 95%

เส้น 99%

นาที

แม็กซ์

รับพนักงาน

37.64

12.57

62.28

128.5

497.57

5

4151.78

รับสถานะ

17

7.57

30.14

58.71

193

3

2814.71

แพทช์พนักงาน

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 รูเบิลสำหรับแอปพลิเคชันและงานจริงของคุณ และแนะนำตัวเลือกของคุณสำหรับการกำหนดค่านี้ในความคิดเห็น

ที่มา: will.com

เพิ่มความคิดเห็น