大腦 + VPS 30 盧布 =?

當所有必要的小東西都在手邊時,真是太好了:一支好筆和記事本、一支削尖的鉛筆、一支舒適的滑鼠、幾根額外的電線等等。 這些不起眼的東西並不引人注目,但卻為生活增添了舒適感。 同樣的情況也適用於各種行動和桌面應用程式:長螢幕截圖、縮小圖片尺寸、計算個人財務、字典、翻譯器、轉換器等。 你是否有一個? VPS - 哪個價格便宜、隨時可用並且帶來許多好處? 不,不是你公司裡的那個,而是你自己的,「袖珍」的。 我們認為,2019 年如果沒有小型 VPS,會有點令人難過,就像講座上沒有常用的鋼筆一樣。 為什麼要悲傷? 夏天到了。 夏天怎麼樣? IT 專家的夏天:坐在家裡,毫無遺憾地從事您最喜歡的專案。 總的來說,我們想到了,也做到了。

大腦 + VPS 30 盧布 =?
同志們,共產主義已經來臨。

他就是這樣——我們的 XNUMX 歲 VPS

我們閱讀了很多來自競爭對手和用戶 3-4 年前撰寫的文章,了解為什麼不需要廉價的 VPS。 嗯,沒錯,那麼「一分錢」的VPS純粹是行銷,並不能提供正常的工作機會。 但時代在變,虛擬資源的成本越來越低,每月 30 盧布,我們準備提供以下服務:

  • 處理器:Intel Xeon 2 GHz(1 核心)
  • Linux系統(Debian、Ubuntu、CentOS可供選擇)
  • 1 個專用 IPv4 位址
  • 快速企業級 SSD 硬碟上的 10 GB 資料存儲
  • 記憶體:512MB
  • 按秒計費
  • 無限流量

該關稅受到額外的技術限制,詳細信息 我們的超酷優惠 - VPS 30 盧布。 

這個虛擬伺服器適合誰? 幾乎所有人都同意:初學者、愛好者、經驗豐富的開發人員、DIY 愛好者甚至一些公司。

這個VPS適合什麼用途?

我們認為哈布爾的讀者肯定會找到他們自己的使用這種配置的方式,但我們決定收集我們自己選擇的想法 - 如果有人需要它,但男人不知道怎麼辦?

  • 放置您的簡單網站、作品集、帶有程式碼的簡歷等。 當然,您自己設計的網站會給雇主留下正面的印象。 將其放置在您的 VPS 上並自行負責網站的安全性和穩定性,而不是由常規託管提供者的工作人員負責。
  • 將 VPS 用於教育目的:託管您的專案、研究伺服器和伺服器作業系統的功能、嘗試 DNS、修補小型教育網站。
  • 用於電話。 有時,個人企業家、自由工作者或非常小的公司迫切需要 IP 電話,而這種電話的營運商非常貪婪。 很簡單:我們使用伺服器,從 IP 電話業者購買號碼,設定虛擬 PBX 並建立內部號碼(如果需要)。 節省的費用是巨大的。
  • 使用伺服器來測試您的應用程式。
  • 使用伺服器進行 DIY 實驗,包括控制智慧家庭系統感測器並收集數據。
  • 一種不尋常的使用方式是在伺服器上放置一個虛擬交易所交易助手,即交易機器人。 您將對伺服器的穩定性和安全性負全部責任,這意味著您將收到用於股票市場交易的受控工具。 好吧,如果有人有興趣或計劃:)

在企業領域有此類 VPS 的應用。 除了已經提到的電話服務之外,您還可以實施一些有趣的事情。 例如:

  • 放置小型資料庫和訊息,以便出差員工可以在遠處存取(例如使用 ftp)。 這將使您能夠非常快速地交換最新的分析、銷售人員的更新配置、簡報等。
  • 為使用者或客戶提供臨時存取權以演示軟體或媒體。

VPS 試駕僅需 30 盧布 - 為您完成

30盧布太少了,你甚至不想拿出卡片來支付和測試。 我們有時也很懶,但這次我們為你做了一切。 在將伺服器投入使用之前,我們進行了測試以檢查所有細節並展示伺服器在此資費下的能力。 為了讓它更有趣,我們添加了Extreme,並檢查如果密度和負載超過我們設定的值,此配置將如何表現。 

主機承受著許多虛擬機器的負載,這些虛擬機器在處理器上執行各種任務並主動使用磁碟子系統。 目標是模擬高密度的放置和相當於或大於戰鬥的負荷。

除了恆定負載之外,我們還安裝了 3 個使用 sysbench 收集綜合指標的虛擬機器(其平均結果如下),以及 50 個創建額外負載的虛擬機器。 所有測試虛擬機器均具有相同的配置(1 核心、RAM 512 GB、SSD 10 GB),選擇標準 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的更新
  • apt-get升級
  • apt-get 安裝 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

部門員工 

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%線

Min

Max

獲取員工

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

補丁員工

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 盧布的價格測試伺服器,並在評論中建議您對此配置的選擇。

來源: www.habr.com

添加評論