
, hannað til að safna, umbreyta og senda loggögn, mælikvarða og atburði.
→
Það er skrifað á Rust tungumálinu og einkennist af mikilli afköstum og lítilli vinnsluminni í samanburði við hliðstæður þess. Að auki er mikil athygli beint að aðgerðum sem tengjast réttmæti, einkum getu til að vista ósenda atburði á biðminni á diski og snúa skrám.
Byggingarfræðilega séð er Vector viðburðarbein sem tekur við skilaboðum frá einum eða fleiri heimildir, valfrjálst að nota yfir þessi skilaboð umbreytingar, og senda þær til eins eða fleiri niðurföll.
Vector kemur í staðinn fyrir filebeat og logstash, hann getur virkað í báðum hlutverkum (móttaka og senda logs), frekari upplýsingar um þau .
Ef í Logstash er keðjan byggð sem inntak → filter → output þá er það í Vector → →
Dæmi er að finna í skjölunum.
Þessi leiðbeining er endurskoðuð leiðbeining frá . Upprunalegu leiðbeiningarnar innihalda geoip vinnslu. Þegar geoip var prófað frá innra neti gaf vektor upp villu.
Aug 05 06:25:31.889 DEBUG transform{name=nginx_parse_rename_fields type=rename_fields}: vector::transforms::rename_fields: Field did not exist field=«geoip.country_name» rate_limit_secs=30Ef einhver þarf að vinna geoip, þá vísaðu til upprunalegu leiðbeininganna frá .
Við munum stilla samsetninguna af Nginx (Access logs) → Vector (Client | Filebeat) → Vector (Server | Logstash) → sérstaklega í Clickhouse og sérstaklega í Elasticsearch. Við munum setja upp 4 netþjóna. Þó að þú getir farið framhjá því með 3 netþjónum.

Skipulagið er eitthvað á þessa leið.
Slökktu á Selinux á öllum netþjónum þínum
sed -i 's/^SELINUX=.*/SELINUX=disabled/g' /etc/selinux/config
rebootVið setjum upp HTTP netþjónahermi + tól á öllum netþjónum
Sem HTTP miðlara keppinautur sem við munum nota frá
Nodejs-stub-þjónninn er ekki með rpm. búa til rpm fyrir það. rpm verður sett saman með því að nota
Bættu við geymslunni antonpatsev/nodejs-stub-server
yum -y install yum-plugin-copr epel-release
yes | yum copr enable antonpatsev/nodejs-stub-serverSettu upp nodejs-stub-server, Apache benchmark og skjáterminal multiplexer á öllum netþjónum
yum -y install stub_http_server screen mc httpd-tools screenÉg leiðrétti stub_http_server viðbragðstímann í /var/lib/stub_http_server/stub_http_server.js skránni þannig að það voru fleiri logs.
var max_sleep = 10;Við skulum ræsa stub_http_server.
systemctl start stub_http_server
systemctl enable stub_http_serverá server 3
ClickHouse notar SSE 4.2 leiðbeiningasettið, þannig að nema annað sé tekið fram verður stuðningur við það í örgjörvanum sem notaður er auka kerfiskrafa. Hér er skipunin til að athuga hvort núverandi örgjörvi styður SSE 4.2:
grep -q sse4_2 /proc/cpuinfo && echo "SSE 4.2 supported" || echo "SSE 4.2 not supported"Fyrst þarftu að tengja opinberu geymsluna:
sudo yum install -y yum-utils
sudo rpm --import https://repo.clickhouse.tech/CLICKHOUSE-KEY.GPG
sudo yum-config-manager --add-repo https://repo.clickhouse.tech/rpm/stable/x86_64Til að setja upp pakka þarftu að keyra eftirfarandi skipanir:
sudo yum install -y clickhouse-server clickhouse-clientLeyfa clickhouse-server að hlusta á netkortið í skránni /etc/clickhouse-server/config.xml
<listen_host>0.0.0.0</listen_host>Breyting á skráningarstigi úr rekja til kembiforrita
kemba
Hefðbundnar þjöppunarstillingar:
min_compress_block_size 65536
max_compress_block_size 1048576Til að virkja Zstd þjöppun var ráðlagt að snerta ekki stillinguna heldur frekar að nota DDL.

Ég gat ekki fundið hvernig á að nota zstd þjöppun í gegnum DDL í Google. Svo ég lét það vera eins og það er.
Samstarfsmenn sem nota zstd þjöppun í Clickhouse, vinsamlegast deilið leiðbeiningunum.
Til að ræsa þjóninn sem púka skaltu keyra:
service clickhouse-server startNú skulum við halda áfram að setja upp Clickhouse
Farðu í Clickhouse
clickhouse-client -h 172.26.10.109 -m172.26.10.109 — IP netþjónsins þar sem Clickhouse er sett upp.
Við skulum búa til vektorgagnagrunn
CREATE DATABASE vector;Við skulum athuga hvort gagnagrunnurinn sé til.
show databases;Búðu til vector.logs töflu.
/* Это таблица где хранятся логи как есть */
CREATE TABLE vector.logs
(
`node_name` String,
`timestamp` DateTime,
`server_name` String,
`user_id` String,
`request_full` String,
`request_user_agent` String,
`request_http_host` String,
`request_uri` String,
`request_scheme` String,
`request_method` String,
`request_length` UInt64,
`request_time` Float32,
`request_referrer` String,
`response_status` UInt16,
`response_body_bytes_sent` UInt64,
`response_content_type` String,
`remote_addr` IPv4,
`remote_port` UInt32,
`remote_user` String,
`upstream_addr` IPv4,
`upstream_port` UInt32,
`upstream_bytes_received` UInt64,
`upstream_bytes_sent` UInt64,
`upstream_cache_status` String,
`upstream_connect_time` Float32,
`upstream_header_time` Float32,
`upstream_response_length` UInt64,
`upstream_response_time` Float32,
`upstream_status` UInt16,
`upstream_content_type` String,
INDEX idx_http_host request_http_host TYPE set(0) GRANULARITY 1
)
ENGINE = MergeTree()
PARTITION BY toYYYYMMDD(timestamp)
ORDER BY timestamp
TTL timestamp + toIntervalMonth(1)
SETTINGS index_granularity = 8192;Við athugum hvort töflurnar hafi verið búnar til. Við skulum ræsa clickhouse-client og leggja fram beiðni.
Við skulum fara í vektorgagnagrunninn.
use vector;
Ok.
0 rows in set. Elapsed: 0.001 sec.Við skulum skoða töflurnar.
show tables;
┌─name────────────────┐
│ logs │
└─────────────────────┘Að setja upp elasticsearch á 4. netþjóninum til að senda sömu gögn til Elasticsearch til samanburðar við Clickhouse
Bættu við opinberum snúningslykli
rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearchVið skulum búa til 2 endurhverf:
/etc/yum.repos.d/elasticsearch.repo
[elasticsearch]
name=Elasticsearch repository for 7.x packages
baseurl=https://artifacts.elastic.co/packages/7.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=0
autorefresh=1
type=rpm-md/etc/yum.repos.d/kibana.repo
[kibana-7.x]
name=Kibana repository for 7.x packages
baseurl=https://artifacts.elastic.co/packages/7.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-mdSettu upp elasticsearch og kibana
yum install -y kibana elasticsearchÞar sem það verður í 1 eintaki þarftu að bæta eftirfarandi við /etc/elasticsearch/elasticsearch.yml skrána:
discovery.type: single-nodeSvo að vektorinn geti sent gögn til elasticsearch frá öðrum netþjóni, skulum við breyta network.host.
network.host: 0.0.0.0Til að tengjast kibana skaltu breyta breytu server.host í skránni /etc/kibana/kibana.yml
server.host: "0.0.0.0"Gamalt og inniheldur elasticsearch í sjálfvirkri ræsingu
systemctl enable elasticsearch
systemctl start elasticsearchog kibana
systemctl enable kibana
systemctl start kibanaStillir Elasticsearch fyrir einshnútsham 1 shard, 0 eftirmynd. Líklegast muntu hafa þyrping af miklum fjölda netþjóna og þú þarft ekki að gera þetta.
Fyrir framtíðarvísitölur, uppfærðu sjálfgefna sniðmátið:
curl -X PUT http://localhost:9200/_template/default -H 'Content-Type: application/json' -d '{"index_patterns": ["*"],"order": -1,"settings": {"number_of_shards": "1","number_of_replicas": "0"}}' Uppsetning í stað Logstash á netþjóni 2
yum install -y https://packages.timber.io/vector/0.9.X/vector-x86_64.rpm mc httpd-tools screenVið skulum setja upp Vector sem staðgengill fyrir Logstash. Breytir skránni /etc/vector/vector.toml
# /etc/vector/vector.toml
data_dir = "/var/lib/vector"
[sources.nginx_input_vector]
# General
type = "vector"
address = "0.0.0.0:9876"
shutdown_timeout_secs = 30
[transforms.nginx_parse_json]
inputs = [ "nginx_input_vector" ]
type = "json_parser"
[transforms.nginx_parse_add_defaults]
inputs = [ "nginx_parse_json" ]
type = "lua"
version = "2"
hooks.process = """
function (event, emit)
function split_first(s, delimiter)
result = {};
for match in (s..delimiter):gmatch("(.-)"..delimiter) do
table.insert(result, match);
end
return result[1];
end
function split_last(s, delimiter)
result = {};
for match in (s..delimiter):gmatch("(.-)"..delimiter) do
table.insert(result, match);
end
return result[#result];
end
event.log.upstream_addr = split_first(split_last(event.log.upstream_addr, ', '), ':')
event.log.upstream_bytes_received = split_last(event.log.upstream_bytes_received, ', ')
event.log.upstream_bytes_sent = split_last(event.log.upstream_bytes_sent, ', ')
event.log.upstream_connect_time = split_last(event.log.upstream_connect_time, ', ')
event.log.upstream_header_time = split_last(event.log.upstream_header_time, ', ')
event.log.upstream_response_length = split_last(event.log.upstream_response_length, ', ')
event.log.upstream_response_time = split_last(event.log.upstream_response_time, ', ')
event.log.upstream_status = split_last(event.log.upstream_status, ', ')
if event.log.upstream_addr == "" then
event.log.upstream_addr = "127.0.0.1"
end
if (event.log.upstream_bytes_received == "-" or event.log.upstream_bytes_received == "") then
event.log.upstream_bytes_received = "0"
end
if (event.log.upstream_bytes_sent == "-" or event.log.upstream_bytes_sent == "") then
event.log.upstream_bytes_sent = "0"
end
if event.log.upstream_cache_status == "" then
event.log.upstream_cache_status = "DISABLED"
end
if (event.log.upstream_connect_time == "-" or event.log.upstream_connect_time == "") then
event.log.upstream_connect_time = "0"
end
if (event.log.upstream_header_time == "-" or event.log.upstream_header_time == "") then
event.log.upstream_header_time = "0"
end
if (event.log.upstream_response_length == "-" or event.log.upstream_response_length == "") then
event.log.upstream_response_length = "0"
end
if (event.log.upstream_response_time == "-" or event.log.upstream_response_time == "") then
event.log.upstream_response_time = "0"
end
if (event.log.upstream_status == "-" or event.log.upstream_status == "") then
event.log.upstream_status = "0"
end
emit(event)
end
"""
[transforms.nginx_parse_remove_fields]
inputs = [ "nginx_parse_add_defaults" ]
type = "remove_fields"
fields = ["data", "file", "host", "source_type"]
[transforms.nginx_parse_coercer]
type = "coercer"
inputs = ["nginx_parse_remove_fields"]
types.request_length = "int"
types.request_time = "float"
types.response_status = "int"
types.response_body_bytes_sent = "int"
types.remote_port = "int"
types.upstream_bytes_received = "int"
types.upstream_bytes_send = "int"
types.upstream_connect_time = "float"
types.upstream_header_time = "float"
types.upstream_response_length = "int"
types.upstream_response_time = "float"
types.upstream_status = "int"
types.timestamp = "timestamp"
[sinks.nginx_output_clickhouse]
inputs = ["nginx_parse_coercer"]
type = "clickhouse"
database = "vector"
healthcheck = true
host = "http://172.26.10.109:8123" # Адрес Clickhouse
table = "logs"
encoding.timestamp_format = "unix"
buffer.type = "disk"
buffer.max_size = 104900000
buffer.when_full = "block"
request.in_flight_limit = 20
[sinks.elasticsearch]
type = "elasticsearch"
inputs = ["nginx_parse_coercer"]
compression = "none"
healthcheck = true
# 172.26.10.116 - сервер где установен elasticsearch
host = "http://172.26.10.116:9200"
index = "vector-%Y-%m-%d"Þú getur breytt transforms.nginx_parse_add_defaults hlutanum.
Eins og notar þessar stillingar fyrir lítið CDN og það geta verið nokkur gildi í upstream_*
Til dæmis:
"upstream_addr": "128.66.0.10:443, 128.66.0.11:443, 128.66.0.12:443"
"upstream_bytes_received": "-, -, 123"
"upstream_status": "502, 502, 200"Ef þetta er ekki staða þín, þá er hægt að einfalda þennan hluta
Búum til þjónustustillingar fyrir systemd /etc/systemd/system/vector.service
# /etc/systemd/system/vector.service
[Unit]
Description=Vector
After=network-online.target
Requires=network-online.target
[Service]
User=vector
Group=vector
ExecStart=/usr/bin/vector
ExecReload=/bin/kill -HUP $MAINPID
Restart=no
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=vector
[Install]
WantedBy=multi-user.targetEftir að hafa búið til töflurnar geturðu keyrt Vector
systemctl enable vector
systemctl start vectorHægt er að skoða vektorskrár svona:
journalctl -f -u vectorÞað ættu að vera svona færslur í loggunum
INFO vector::topology::builder: Healthcheck: Passed.
INFO vector::topology::builder: Healthcheck: Passed.Á biðlara (vefþjónn) - 1. þjónn
Á þjóninum með nginx þarftu að slökkva á ipv6, þar sem logtaflan í clickhouse notar reitinn upstream_addr IPv4, þar sem ég nota ekki ipv6 inni á netinu. Ef ekki er slökkt á ipv6 verða villur:
DB::Exception: Invalid IPv4 value.: (while read the value of key upstream_addr)Kannski lesendur, bættu við ipv6 stuðningi.
Búðu til skrána /etc/sysctl.d/98-disable-ipv6.conf
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1Að beita stillingum
sysctl --systemVið skulum setja upp nginx.
Bætt við nginx geymsluskrá /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=trueSettu upp nginx pakkann
yum install -y nginxFyrst þurfum við að stilla log sniðið í Nginx í skránni /etc/nginx/nginx.conf
user nginx;
# you must set worker processes based on your CPU cores, nginx does not benefit from setting more than that
worker_processes auto; #some last versions calculate it automatically
# number of file descriptors used for nginx
# the limit for the maximum FDs on the server is usually set by the OS.
# if you don't set FD's then OS settings will be used which is by default 2000
worker_rlimit_nofile 100000;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
# provides the configuration file context in which the directives that affect connection processing are specified.
events {
# determines how much clients will be served per worker
# max clients = worker_connections * worker_processes
# max clients is also limited by the number of socket connections available on the system (~64k)
worker_connections 4000;
# optimized to serve many clients with each thread, essential for linux -- for testing environment
use epoll;
# accept as many connections as possible, may flood worker connections if set too low -- for testing environment
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
log_format vector escape=json
'{'
'"node_name":"nginx-vector",'
'"timestamp":"$time_iso8601",'
'"server_name":"$server_name",'
'"request_full": "$request",'
'"request_user_agent":"$http_user_agent",'
'"request_http_host":"$http_host",'
'"request_uri":"$request_uri",'
'"request_scheme": "$scheme",'
'"request_method":"$request_method",'
'"request_length":"$request_length",'
'"request_time": "$request_time",'
'"request_referrer":"$http_referer",'
'"response_status": "$status",'
'"response_body_bytes_sent":"$body_bytes_sent",'
'"response_content_type":"$sent_http_content_type",'
'"remote_addr": "$remote_addr",'
'"remote_port": "$remote_port",'
'"remote_user": "$remote_user",'
'"upstream_addr": "$upstream_addr",'
'"upstream_bytes_received": "$upstream_bytes_received",'
'"upstream_bytes_sent": "$upstream_bytes_sent",'
'"upstream_cache_status":"$upstream_cache_status",'
'"upstream_connect_time":"$upstream_connect_time",'
'"upstream_header_time":"$upstream_header_time",'
'"upstream_response_length":"$upstream_response_length",'
'"upstream_response_time":"$upstream_response_time",'
'"upstream_status": "$upstream_status",'
'"upstream_content_type":"$upstream_http_content_type"'
'}';
access_log /var/log/nginx/access.log main;
access_log /var/log/nginx/access.json.log vector; # Новый лог в формате json
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}Til að brjóta ekki núverandi stillingar þínar, gerir Nginx þér kleift að hafa nokkrar access_log tilskipanir
access_log /var/log/nginx/access.log main; # Стандартный лог
access_log /var/log/nginx/access.json.log vector; # Новый лог в формате jsonEkki gleyma að bæta við reglu til að logrotate fyrir nýja annála (ef logskráin endar ekki á .log)
Fjarlægðu default.conf úr /etc/nginx/conf.d/
rm -f /etc/nginx/conf.d/default.confBættu við sýndarhýsingu /etc/nginx/conf.d/vhost1.conf
server {
listen 80;
server_name vhost1;
location / {
proxy_pass http://172.26.10.106:8080;
}
}Bættu við sýndarhýsingu /etc/nginx/conf.d/vhost2.conf
server {
listen 80;
server_name vhost2;
location / {
proxy_pass http://172.26.10.108:8080;
}
}Bættu við sýndarhýsingu /etc/nginx/conf.d/vhost3.conf
server {
listen 80;
server_name vhost3;
location / {
proxy_pass http://172.26.10.109:8080;
}
}Bættu við sýndarhýsingu /etc/nginx/conf.d/vhost4.conf
server {
listen 80;
server_name vhost4;
location / {
proxy_pass http://172.26.10.116:8080;
}
}Bættu sýndarhýsingum (172.26.10.106 ip þjónsins þar sem nginx er uppsettur) við alla netþjóna við /etc/hosts skrána:
172.26.10.106 vhost1
172.26.10.106 vhost2
172.26.10.106 vhost3
172.26.10.106 vhost4Og ef allt er tilbúið þá
nginx -t
systemctl restart nginxNú skulum við setja það upp sjálf
yum install -y https://packages.timber.io/vector/0.9.X/vector-x86_64.rpmBúum til stillingaskrá fyrir systemd /etc/systemd/system/vector.service
[Unit]
Description=Vector
After=network-online.target
Requires=network-online.target
[Service]
User=vector
Group=vector
ExecStart=/usr/bin/vector
ExecReload=/bin/kill -HUP $MAINPID
Restart=no
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=vector
[Install]
WantedBy=multi-user.targetOg stilltu Filebeat skiptin í /etc/vector/vector.toml stillingunni. IP vistfang 172.26.10.108 er IP vistfang notendaþjóns (Vector-Server)
data_dir = "/var/lib/vector"
[sources.nginx_file]
type = "file"
include = [ "/var/log/nginx/access.json.log" ]
start_at_beginning = false
fingerprinting.strategy = "device_and_inode"
[sinks.nginx_output_vector]
type = "vector"
inputs = [ "nginx_file" ]
address = "172.26.10.108:9876"Ekki gleyma að bæta notandavigurnum við viðeigandi hóp svo að hann geti lesið skrár. Til dæmis, nginx í centos býr til skrár með réttindum fyrir stjórnendahóp.
usermod -a -G adm vectorByrjum á vektorþjónustunni
systemctl enable vector
systemctl start vectorHægt er að skoða vektorskrár svona:
journalctl -f -u vectorÞað ætti að vera svona færsla í loggunum
INFO vector::topology::builder: Healthcheck: Passed.Streitupróf
Við framkvæmum próf með því að nota Apache viðmið.
httpd-tools pakkinn var settur upp á öllum netþjónum
Við byrjum að prófa að nota Apache viðmið frá 4 mismunandi netþjónum á skjánum. Fyrst ræsum við multiplexer skjástöðvarinnar og byrjum síðan að prófa með Apache viðmiðinu. Hvernig á að vinna með skjá sem þú getur fundið í .
Frá 1. server
while true; do ab -H "User-Agent: 1server" -c 100 -n 10 -t 10 http://vhost1/; sleep 1; doneFrá 2. server
while true; do ab -H "User-Agent: 2server" -c 100 -n 10 -t 10 http://vhost2/; sleep 1; doneFrá 3. server
while true; do ab -H "User-Agent: 3server" -c 100 -n 10 -t 10 http://vhost3/; sleep 1; doneFrá 4. server
while true; do ab -H "User-Agent: 4server" -c 100 -n 10 -t 10 http://vhost4/; sleep 1; doneVið skulum athuga gögnin í Clickhouse
Farðu í Clickhouse
clickhouse-client -h 172.26.10.109 -mAð gera SQL fyrirspurn
SELECT * FROM vector.logs;
┌─node_name────┬───────────timestamp─┬─server_name─┬─user_id─┬─request_full───┬─request_user_agent─┬─request_http_host─┬─request_uri─┬─request_scheme─┬─request_method─┬─request_length─┬─request_time─┬─request_referrer─┬─response_status─┬─response_body_bytes_sent─┬─response_content_type─┬───remote_addr─┬─remote_port─┬─remote_user─┬─upstream_addr─┬─upstream_port─┬─upstream_bytes_received─┬─upstream_bytes_sent─┬─upstream_cache_status─┬─upstream_connect_time─┬─upstream_header_time─┬─upstream_response_length─┬─upstream_response_time─┬─upstream_status─┬─upstream_content_type─┐
│ nginx-vector │ 2020-08-07 04:32:42 │ vhost1 │ │ GET / HTTP/1.0 │ 1server │ vhost1 │ / │ http │ GET │ 66 │ 0.028 │ │ 404 │ 27 │ │ 172.26.10.106 │ 45886 │ │ 172.26.10.106 │ 0 │ 109 │ 97 │ DISABLED │ 0 │ 0.025 │ 27 │ 0.029 │ 404 │ │
└──────────────┴─────────────────────┴─────────────┴─────────┴────────────────┴────────────────────┴───────────────────┴─────────────┴────────────────┴────────────────┴────────────────┴──────────────┴──────────────────┴─────────────────┴──────────────────────────┴───────────────────────┴───────────────┴─────────────┴─────────────┴───────────────┴───────────────┴─────────────────────────┴─────────────────────┴───────────────────────┴───────────────────────┴──────────────────────┴──────────────────────────┴────────────────────────┴─────────────────┴───────────────────────Finndu út stærð borðanna í Clickhouse
select concat(database, '.', table) as table,
formatReadableSize(sum(bytes)) as size,
sum(rows) as rows,
max(modification_time) as latest_modification,
sum(bytes) as bytes_size,
any(engine) as engine,
formatReadableSize(sum(primary_key_bytes_in_memory)) as primary_keys_size
from system.parts
where active
group by database, table
order by bytes_size desc;Við skulum komast að því hversu mikið logs tóku upp í Clickhouse.

Stærð annálatöflunnar er 857.19 MB.

Stærð sömu gagna í vísitölunni í Elasticsearch er 4,5GB.
Ef þú tilgreinir ekki gögn í vektornum í breytunum tekur Clickhouse 4500/857.19 = 5.24 sinnum minna en í Elasticsearch.
Í vektor er þjöppunarreiturinn notaður sjálfgefið.
Telegram spjall eftir
Telegram spjall eftir
Telegram spjall eftir ""
Heimild: www.habr.com
