xluffy / til Goto Github PK
View Code? Open in Web Editor NEWYou only feel happy when you know what you doing
You only feel happy when you know what you doing
nginx được biết tới vai trò như web server, reverse proxy hoặc load balancer. Ở giao thức http thì nginx là một trong những dịch vụ vô cùng mạnh mẽ và thân thiện với người dùng hơn cả Apache (1 web server lâu đời) nhờ cú pháp ngọn nhẹ, dễ hiểu, hỗ trợ nhiều tính năng.
Từ phiên bản 1.9.0 nginx hỗ trợ thêm giao thức tcp cho reverse proxy và load balancer. Nếu dùng quen nginx thì hoàn toàn có thể dùng luôn nginx cho chắc năng proxy tcp. Tuy nhiên cần lưu ý là nếu có ý định sử dụng lâu dài thì nên cân nhắc vì nginx với tcp ko hỗ trợ nhiều tính năng như http, ví dụ ko hỗ trợ log response time, client ip ... các phần này chỉ hỗ trợ trong bản 1.11 (mainline)
Nên nếu sử dụng tcp proxy thì nên sử dụng các service chuyên biệt như haproxy hoặc với mysql thì có maxscale hoặc proxysql
Khi chúng ta triển khai một hệ thống phân tán (cluster service) hoặc cung cấp API service cho app. Trong nhiều trường hợp chúng ta bị những lỗi rất khó debug như network bị rớt, latency network, bandwidth bị nhà mạng bóp. Nếu lỗi xày ra trong một khoảng thời gian dài thì dễ, nếu chỉ xảy ra trong một khoảng thời gian nhỏ ví dụ vài giây, vài phút thì cực kì khó debug.
Ví dụ:
Build redis cluster trên AWS, các node connect trong internal network, log báo 1 node không thể connect tới các node khác trong khoảng thời gian vài giây, dùng monitor system verify thấy network vẫn tốt (CloudWatch) nhưng Application bắn exception connect tới cluster fail
User sử dụng app báo fail khi sử dụng vài tính năng. Phía server kiểm tra thấy mọi thứ đều ổn, một vài IP có mã lỗi như 408, 499 ...
Để build một hệ thống tốt thì ta cần test, giả lập các trường hợp như trên. Comcast là công cụ giúp giả lập các trường hợp như latency, bandwidth bị hạn chế, và dropped/reordered/corrupted packets. Hoặc ta có nhiều công cụ phía client như clumsy, others
Bản chất ta không cần công cụ, có thể giả lập bằng các công cụ mặc định của hệ thống như iptables
và tc
Một này đẹp trời, nhận đc 1 exception trong ES như sau
MapperParsingException[failed to parse [timestamp]]; nested: IllegalArgumentException[Invalid format: "12/Feb/2017:00:00:01 +0900" is malformed at "/Feb/2017:00:00:01 +0900"];
field timestamp
bình thường kiểu dữ liệu là string
, không hiểu tại sao đoạn /Feb/2017:00:00:01 +0900
lại không được ES chấp nhận,
Lần mò mấy ngày không tìm ra cách giải quyết, thôi thì đành fix tạm bằng cách
date
với nhiều format "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
ignore_malformed: true
để nếu dữ liệu có sai kiểu thì vẫn chấp nhận.If you have 2 instance backend. And you use nginx for proxy to backend instance like config
upstream {
server 10.20.30.2:8080;
server 10.20.30.3:8080;
}
You would like to limit maximum connection to backend node. Such as, 1000 connection to instance 10.20.30.2 and 1000 connection to instance 10.20.30.3. Total maximum connection is 2000 per 2 instance. You can use max_conns=number
. Default value is zeroo, meaning there is no limit.
upstream {
server 10.20.30.2:8080 max_conns=1000;
server 10.20.30.3:8080 max_conns=1000;
}
set
và let
set
dùng để định nghĩa trực tiếp một cấu hình cho vimlet
dùng để gán một giá trị cho biến COMMANDS MODES ~
:map :noremap :unmap Normal, Visual, Select, Operator-pending
:nmap :nnoremap :nunmap Normal
:vmap :vnoremap :vunmap Visual and Select
:smap :snoremap :sunmap Select
:xmap :xnoremap :xunmap Visual
:omap :onoremap :ounmap Operator-pending
:map! :noremap! :unmap! Insert and Command-line
:imap :inoremap :iunmap Insert
:lmap :lnoremap :lunmap Insert, Command-line, Lang-Arg
:cmap :cnoremap :cunmap Command-line
Dùng để thiết lập một command, ví dụ command! Q q
thì có thể thoát vim bằng lệnh :Q
thay vì :q
Trong docker có nhiều storage driver. Ở phiên bản đầu tiên là aufs
nhưng sau này có thêm device-mapper(loop), device-mapper(direct-lvm), OverlayFS, Btrfs ...
Tuy nhiên không phải storage nào cũng ổn định. Ví dụ với CentOS thì default storage driver của docker là device-mapper(loop)
, một storage driver gặp rất nhiều vấn đề và rất không nên sử dụng trong production.
aufs
ổn định hơn nhưng phải là storage-driver mainline trong kernel của linux. Nên muốn dùng phải patch kernel (với CentOS), với Ubuntu thì chỉ cần cài gói linux-image-extra-version-generic
là có thể sử dụng được.
Tuy nhiên aufs
cũng sẽ bị bỏ hẳn việc hỗ trợ trong phiên bản kernel 4.x nên Docker sinh ra OverlayFS tương tự aufs nhưng nhẹ hơn.
Ref:
Ví dụ bình thường ta hay run 1 vòng lặp cho các file trong 1 thư mục như sau
for f in *; do
...
done
Nhưng ví dụ ta có nhu cầu tương tự nhưng ngoại trừ một số pattern như trừ các file gz thì ta cần enable extglob option như sau
shopt -s extglob
for f in !(*.gz); do
...
done
Tips khác, ví dụ ta có
if ...; then
...
elif ...; then
...
else
...
fi
nhưng ta muốn nếu thỏa điều kiện thì không làm gì cả, kể cả echo
thì như sau
if ...; then
:
elif ...; then
:
else
echo "ahihi"
fi
Container run ES service, ES run via elasticsearch
user, and when exec
to bash, we can't run super command.
For running bash with other user, use option -u
docker exec -u root -it 0824301aec63 /bin/bash
Khi kiến trúc một hệ thống Docker, việc giữ cho kích thước của image lightweight hết mức có thể đem lại rất nhiều lợi ích. Ví dụ việc deploy (pull image, run container), build image sẽ nhanh hơn, portable hơn và giảm thiểu lỗi.
Ngoài chuyện chọn một distribution vừa ổn định và nhỏ, nhẹ, đủ gói, đủ chức năng (alpine, busybox ...) thì sẽ có một số lưu ý trong quá trình viết Dockerfile ...
Mỗi khi RUN
trong dockerfile sẽ tạo ra một layer, việc tạo ra quá nhiều layer sẽ làm tăng kích thước của image. Nên best practice là gom nhiều câu lệnh vào chung.
Không tốt:
RUN sed -i "s/archive.ubuntu.com/mirror-fpt-telecom.fpt.net/g" /etc/apt/sources.list
RUN apt-get update
RUN apt-get install -y --no-install-recommends tmux curl git htop vim wget ncdu
Tốt
RUN \
sed -i "s/archive.ubuntu.com/mirror-fpt-telecom.fpt.net/g" /etc/apt/sources.list && \
apt-get update && \
apt-get install -y --no-install-recommends tmux curl git htop vim wget ncdu && \
Có thể check số layer của một image bằng lệnh docker history
docker history mesosphere/chronos
IMAGE CREATED CREATED BY SIZE COMMENT
7594654c6147 16 months ago /bin/sh -c #(nop) CMD ["/usr/bin/chronos" "ru 0 B
<missing> 16 months ago /bin/sh -c #(nop) EXPOSE 4400/tcp 0 B
<missing> 16 months ago /bin/sh -c rm -rf /etc/chronos/conf 0 B
<missing> 16 months ago /bin/sh -c rm -rf /etc/mesos 0 B
<missing> 16 months ago /bin/sh -c apt-get update && apt-get -y insta 60.09 MB
<missing> 16 months ago /bin/sh -c #(nop) COPY file:39b75e855ca7513a9 32.24 MB
<missing> 16 months ago /bin/sh -c #(nop) MAINTAINER Mesosphere <supp 0 B
<missing> 17 months ago /bin/sh -c apt-get -y install mesos=0.23.0-1. 303.1 MB
<missing> 17 months ago /bin/sh -c apt-get -y update 21.07 MB
<missing> 17 months ago /bin/sh -c apt-key adv --keyserver keyserver. 25.84 kB
<missing> 17 months ago /bin/sh -c echo "deb http://repos.mesosphere. 51 B
<missing> 17 months ago /bin/sh -c #(nop) MAINTAINER Mesosphere <supp 0 B
<missing> 21 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B
<missing> 21 months ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/ 1.895 kB
<missing> 21 months ago /bin/sh -c echo '#!/bin/sh' > /usr/sbin/polic 194.5 kB
<missing> 21 months ago /bin/sh -c #(nop) ADD file:777fad733fc954c0c1 188.1 MB
Hoặc dịch vụ của microbadger hoặc dịch vụ của imagelayers hoặc command-tool dockerfile-from-image.rb
Giảm béo cho docker image bằng công cụ docker-squash
Khác với việc build server, ta sẽ cần nhiều tool trong quá trình vận hành ví dụ các gói biên dịch như gcc
, gcc-c++
, các thư viện cần thiết cho quá trình build gói -devel
hoặc các tool như vim
, ncdu
, screen
. Nên xác định cần cái gì thay vì cài full gói.
Với các gói gz tải về, sau khi xả nén cũng nên xóa và gỡ những phần không cần thiết. Ví dụ với gói jdk ta có thể xóa các phần như src.zip
, các thư viện, binary liên quan tới việc visualvm
... Ví dụ
RUN wget -O /tmp/jdk.tar.gz http://abc.local/jdk.tar.gz | tar -xzf jdk.tar.gz && rm jdk.tar.gz
Với repository thì xoá cache của package manager sau khi cài một gói gì đó. Ví dụ
RUN \
rm -fv /var/cache/apt/*.bin && \
rm -fv /var/cache/apt/archives/*.* && \
rm -fv /var/lib/apt/lists/*.* && \
apt-get autoclean
Hoặc ví dụ cân nhắc trong việc có cần sử dụng dịch vụ sshd
trong container hay không.
Với package manager như apt
có thể cân nhắc một số option như bài apt
Có lúc bạn sẽ cần một image chứa gói này, thư viện nọ, nhưng nhiều lúc bạn chỉ cần một môi trường để chạy một file binary thì có thể alpine
hoặc chạy container từ Scratch
image có lẽ sẽ là sự lựa chọn thích hợp hơn.
Và nguyên tắc KISS, nếu ứng dụng chỉ cần ruby
thì không có lý do gì sử dụng image Rails.
Project Atomic có cung cấp một công cụ viết bằng nodejs giúp kiểm tra một Dockerfile được viết tốt hay chưa dockerfile_lint hoặc một dự án khác là hadolint. Ví dụ
$ ./node_modules/dockerfile_lint/bin/dockerfile_lint Dockerfile
--------ERRORS---------
ERROR: Required LABEL name/key 'Name' is not defined.
Reference -> http://docs.projectatomic.io/container-best-practices/#_recommended_labels_for_your_project
ERROR: Required LABEL name/key 'Version' is not defined.
Reference -> http://docs.projectatomic.io/container-best-practices/#_recommended_labels_for_your_project
--------INFO---------
INFO: There is no 'EXPOSE' instruction. Without exposed ports how will the service of the container be accessed?.
Reference -> https://docs.docker.com/reference/builder/#expose
Khi setup một hệ thống MySQL Master-Master, vấn đề cần quan tâm nhất chính là conflict dữ liệu. Việc conflict xảy ra khi có hành động ghi dữ liệu đồng thời trên các server master. Ví dụ các hành động UPDATE
, DELETE
, INSERT
Ví dụ với hành động thêm dữ liệu mới thì việc tự động tăng trường ID là một vấn đề cần quan tâm, ví dụ cùng 1 table nếu việc tự sinh ID trùng nhau sẽ dẫn tới việc conflict dữ liệu.
Trong MySQL có 2 biến đó là
auto_increment_increment
: Biến này có thể xem là số bước tăng của ID, ví dụ giá trị này là 2 thì mỗi lần insert 1 row dữ liệu thì ID sẽ tăng lên 2auto_increment_offset
: Biến này là giá trị bắt đầu của ID. Ví dụ nếu giá trị này là 5 thì ID đầu tiên sẽ là 5.Một số ví dụ
auto_increment_increment=10
và auto_increment_offset=1
mysql> SHOW VARIABLES LIKE 'auto_inc%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 10 |
| auto_increment_offset | 1 |
+--------------------------+-------+
Thì khi insert dữ liệu ta sẽ được giá trị như sau
mysql> SELECT col FROM autoinc1;
+-----+
| col |
+-----+
| 1 |
| 11 |
| 21 |
| 31 |
+-----+
auto_increment_increment=10
và auto_increment_offset=5
SHOW VARIABLES LIKE 'auto_inc%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 10 |
| auto_increment_offset | 5 |
+--------------------------+-------+
Thì khi insert dữ liệu ta sẽ được giá trị như sau
mysql> SELECT col FROM autoinc2;
+-----+
| col |
+-----+
| 5 |
| 15 |
| 25 |
| 35 |
+-----+
=> Vậy câu hỏi là 2 giá trị này nên thiết lập thế nào khi số lượng server Master khác nhau, ví dụ ta có 2 master, 3 master thì như thế nào.
Ví dụ với 2 server master thì
auto-increment-increment = 2
auto-increment-offset = 1
auto-increment-increment = 2
auto-increment-offset = 2
Nếu có 3 server ta có thể lần lượt thiết lập như sau
ID 1,4,7,10 ...
auto_increment_increment = 3
auto_increment_offset = 1
ID 2,5,8,11 ...
auto_increment_increment = 3
auto_increment_offset = 2
ID 3,6,9,12 ...
auto_increment_increment = 3
auto_increment_offset = 3
Client send to server a custom header. Sample, send a device_id
header to server. In nginx, we capture this header and write to access_log
to debug, monitor, route request. We need to config nginx that:
Enable underscores directive in http
selection.
underscores_in_headers on;
Set header to a variable (if header is custom_header
, variable is http_
+ custom_header
proxy_set_header device_id $http_device_id;
Re-config log format in nginx config
log_format main '"device_id:$http_device_id"'
Send a request with custom header
curl -X POST -H 'device_id:57cfd83ee4b094690a1db5d6' https://localhost.local/api/log/write
Trong nginx, khi cấu hình dạng reverse proxy, ví dụ
upstream api {
server 1.2.3.4:8080;
server 1.2.3.5:8080;
}
Thì mặc định nginx đã có check tới các instance backend này. Bản thân nginx khi gửi request tới backend instance mà thấy fail, nó sẽ đánh dấu là backend server này down, và trong các lần tiếp theo sẽ không gửi request vào instance này nữa. NHƯNG những request đã gửi vào thì coi như fail luôn.
Cơ chế health check nghĩa là nginx gửi độc lập các request tới instance backend, độc lập với các request mà user gửi lên. Nginx sẽ định kì gửi mỗi 5s một lần (mặc định) và nếu nó phát hiện health check request trả về fail thì request của user sẽ được chuyển hướng sang instance khác ngay lập tức -> đảm bảo không có request nào bị fail.
Tuy nhiên tính năng health check chỉ được hỗ trợ trong bản nginx plus
http {
server {
...
location / {
proxy_pass http://backend;
health_check match=welcome;
}
}
match welcome {
status 200;
header Content-Type = text/html;
body ~ "Welcome to nginx!";
}
}
Với Nginx FOSS để hỗ trợ healthcheck upstream thì có thể sử dụng module https://github.com/openresty/lua-resty-upstream-healthcheck
Đối với ALB/ELB thì cũng nên có healthchek để nếu 1 EC2 bị chết thì vẫn ko gây lỗi cho user
Trong kafka, có một cấu hình log.retention.hours
có ý nghĩa là kafka sẽ giữ log trong bao lâu, nếu không cấu hình thì mặc định là 168 giờ, tương đương 7 ngày. Nghĩa là vẫn có thể tìm thấy log của ngày hôm trước trong topic của kafka.
Dữ liệu trong kafka sẽ được lưu tại log.dirs
hoặc log.dir
tùy cấu hình
Bài toán C10K là bài toán liên quan đến vấn đề concurrent và blocking-io.
Do vấn đề blocking-io nên để ứng phó với bài toán concurrent thì chương trình sẽ fork ra nhiều thread, và mỗi thread này sẽ đảm nhiệm xử lý 1 connection => giải quyết được bài toán concurrent và dù 1 thread có bị blocking thì cũng không ảnh hưởng tới xử lý của thread khác.
Tuy nhiên tới đây lại nảy sinh ra 1 vấn đề khác, nếu số connection ít thì không sao, nhưng nếu đạt tới ngưỡng 10K connection đồng thời thì đồng nghĩa chương trình sẽ phải fork ra 10K thread, xử lý 10K connection này thì xảy ra vấn đề, đây chính là bài toán C10K với các hệ thống cũ.
Tóm lại: bài toán C10K là bài toán viết chương trình với phương pháp xử lý 1 thread chỉ có thể xử lý 1 connection tại 1 thời điểm trên các máy chủ cũ => không giải quyết được
Hiện nay thì bài toán C10K không còn là vấn đề với các máy chủ hiện đại, nghĩa là ta hoàn toàn có thể fork ra hơn 10K thread đồng thời xử lý hơn 10K connection đồng thời. Tuy nhiên sẽ cần lưu ý vài điểm
You can't optimize what you don't measure
Install
pacman -S xmonad xmonad-contrib
Simple config
import XMonad
import XMonad.Config.Desktop
import XMonad.Hooks.DynamicLog
import XMonad.Hooks.ManageDocks
import XMonad.Util.Run(spawnPipe)
import XMonad.Util.EZConfig(additionalKeys)
import XMonad.Actions.CycleWS (prevWS, nextWS)
import Graphics.X11.ExtraTypes.XF86
import System.IO
main = do
xmproc <- spawnPipe "/usr/bin/xmobar /home/xluffy/.xmobarrc"
xmonad $ defaultConfig
{ manageHook = manageDocks <+> manageHook defaultConfig
, layoutHook = avoidStruts $ layoutHook defaultConfig
, modMask = mod4Mask
} `additionalKeys`
[
((mod4Mask, xK_Left), prevWS)
, ((mod4Mask, xK_Right), nextWS)
, ((mod4Mask, xK_Return), spawn "urxvt")
, ((mod4Mask, xK_space), spawn "dmenu_run -f")
, ((mod4Mask, xK_q), spawn "xmonad --recompile; xmonad --restart")
, ((0, xF86XK_AudioLowerVolume ), spawn "amixer set Master 2-")
, ((0, xF86XK_AudioRaiseVolume ), spawn "amixer set Master 2+")
, ((0, xF86XK_AudioMute ), spawn "amixer set Master toggle")
, ((0, xF86XK_AudioMicMute), spawn "amixer set Capture toggle")
]
Max memory = [-Xmx] + [-XX:MaxPermSize] + number_of_threads * [-Xss]
How to count thread of process
~$ grep -i thread /proc/27488/status
Threads: 199
Tracking native memory of java process
https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr007.html
Đầu tiên cần lấy list filed, trong trường hợp cần lấy tất cả các filed
var schematodo = db.tasks.findOne();
for (var key in schematodo) { print (key) ; }
_id
label
content
Sau đó export
mongoexport -d database -c tasks --csv -q '{"label":nginx}' -f _id,label,content --out report.csv
mongoexport -d database -c tasks type=csv -q '{"label":nginx}' -f _id,label,content --out report.csv
rails g model User name:text
=> Sẽ tạo ra một file User.rb
trong thư mục models và một data migrate
rails g resource User name:text
=> Sẽ tạo ra một file User.rb
trong thư mục models, một data migrate, một User empty controller và resources :users
trong routes.rb
rails g scaffold User name:text
=> Sẽ tạo ra một model User trong thư mục models, một data migrate, một User controller với public, private method (action), và view tương ứng với method trong controller
http://www.korenlc.com/rails-generate-model-vs-resourse-vs-scaffold/
Ta có thể để ELB quản lý cert SSL và EC2 instance chỉ cần listen trên port 80. ELB sẽ forward cả 80, 443 vào 80 của EC2.
Nhưng nếu cần force https thì làm như thế nào
Bình thường nếu không có ELB thì
server {
listen 80;
server_name api.abc.local;
return 301 https://api.abc.local$request_uri;
}
server {
listen 443 ssl;
server_name api.abc.local;
Nhưng EC2 ở đây không listen 443 và nếu ta return 301
vào block port 80 thì sẽ bị redirect to many.
Trick ở đây là kiểm tra protocal của request. Trong location /
block port 80
if ($http_x_forwarded_proto != 'https') {
return 301 https://$server_name$request_uri;
}
Tạo table
CREATE TABLE `GeoIP` (
`Id` int(64) NOT NULL AUTO_INCREMENT,
`IpAddr` varchar(50) NOT NULL,
`Country` varchar(50) NOT NULL,
PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
PARTITION BY RANGE COLUMNS (Id)
(
PARTITION p01 VALUES LESS THAN (2000),
PARTITION p02 VALUES LESS THAN (4000),
PARTITION p03 VALUES LESS THAN (6000),
PARTITION p04 VALUES LESS THAN (8000),
PARTITION p05 VALUES LESS THAN (MAXVALUE));
Import db bình thường như ko có partitioning
~$ pv -pert 10k.sql | mysql test
Check dữ liệu khi SELECT
MariaDB [test]> explain partitions select * from GeoIP where Id=1
-> ;
+------+-------------+-------+------------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | GeoIP | p01 | const | PRIMARY | PRIMARY | 4 | const | 1 | |
+------+-------------+-------+------------+-------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec)
MariaDB [test]> explain partitions select * from GeoIP where Id=4000;
+------+-------------+-------+------------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | GeoIP | p03 | const | PRIMARY | PRIMARY | 4 | const | 1 | |
+------+-------------+-------+------------+-------+---------------+---------+---------+-------+------+-------+
MariaDB [test]> explain partitions select * from GeoIP where Id=11000;
+------+-------------+-------+------------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | GeoIP | p05 | const | PRIMARY | PRIMARY | 4 | const | 1 | |
+------+-------------+-------+------------+-------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec)
MariaDB [test]> Bye
Ở phiên bản < 2.x, ES có hỗ trợ API Delete-by-query, nhưng tới phiên bản 2.0 trở đi thì lại không hỗ trợ nữa, thay vào đó phải search, lấy id của docs và dùng API DELETE theo id hoặc dùng plugin delete-by-query. Tới phiên bản 5.x thì API này lại được đưa vào lại.
Giả sử ta có một tập dữ liệu
[17.9, 19.5, 21.2, 23.0, 24.6, 25.1]
Medium sẽ được tính bằng cách như sau
Ví dụ với tập dữ liệu trên ta có median = (21.2 + 23.0)/2 = 22.1
sudo -u nginx bash
or
su -s /bin/sh grafana
pacman -S graphviz --noconfirm
echo 'gem "rails-erd"' >> Gemfile
bundle
bundle exec erd -> export to pdf
apt-get update
: lệnh này update package database, khi thay đổi nội dung file sources.list
thì cần chạy lại lệnh nàyapt-get upgrade
: lệnh này dùng để cập nhật tất cả các gói đã cài trên hệ thống lên phiên bản mới hơn hoặc một gói lên phiên bản mới hơnapt-get dist-upgrade
:apt list --upgradable
: list các gói sẽ upgradeapt-get remove pkg_name
: lệnh này gỡ một gói khỏi hệ thống nhưng vẫn giữ lại các file cấu hình, trong trường hợp cài lại gói này thì file cấu hình sẽ vẫn còn. apt-get purge pkg_name
: lệnh này sẽ gỡ gói và xóa luôn các file cấu hình sạch sẽ khỏi hệ thống.apt-get autoremove pkg_name
: lệnh này gỡ một gói và các gói phụ thuộc của nó.apt-get install -s pkg_name
: lệnh này tác dụng như dry_run
apt-get install -d pkg_name
: lệnh này chỉ tải gói về mà không cài đặtapt-get install -qq
: lệnh này không hiển thị outputapt-cache show pkg_name
: hiển thị thông tin của một góiapt-cache policy pkg_name
: Kiểm tra một gói có được cài đặt trên hệ thống hay không, version, và từ repo url nào.apt-cache showpkg pkg_name
: hiện thị gói phụ thuộc của một gói nào đó.DEBIAN_FRONTEND=noninteractive
: Trong hệ Debian, khi cài đặt một gói, có thể sẽ xuất hiện các hộp thoại cho phép nhập các thông tin (ví dụ với gói mysql-server
, nhập password default), noninteractive
nghĩa là tắt việc xuất hiện các hộp thoại tương tácapt-get install --no-install-recommends pkg_name
: Cài đặt một gói nhưng cài đặt các gọi recommend của gói đó.Redis use a mostly single thread design. This means that a single process serves all the client requests, using a technique called multiplexing. This means that Redis can serve a single request in every given moment, so all the requests are served sequentially.
This is caused in part by the small amount of time to complete a single request, but primarily because these products are designed to not block on system calls, such as reading data from or writing data to a socket.
I said that Redis is mostly single threaded since actually from Redis 2.4 we use threads in Redis in order to perform some slow I/O operations in the background, mainly related to disk I/O, but this does not change the fact that Redis serves all the requests using a single thread.
You have a cluster Cassandra service. Cluster has 4, 6 or 8 nodes. And you would like to update new config for cluster. Example, you would like to increase HEAP_SIZE
of JVM. You must restart each node and it don't effect your application.
You must follow 3 step for restarting.
B1. Disable Gossip by use command nodetool disablegossip
B2. Disable thrift by use command nodetool disablethrift
B3: Stop cassandra with nodetool drain
Waiting some second, after start Cassandra.
Trong các ứng dụng client-server, có một nhu cầu đó là truyền một cấu trúc dữ liệu hoặc một object được khởi tạo ở client lên server hoặc lưu xuống đĩa cứng.
Để làm được điều này thì cấu trúc dữ liệu hoặc object đó phải được chuyển đổi thành một định dạng có thể lưu trữ được (tập tin, gói tin). Quá trình chuyển đổi này gọi là Serialize, sau đó phía server cần tái tạo từ một định dạng thành cấu trúc dữ liệu hoặc object lại thì quá trình này gọi là Deserialize
Có nhiều cách để có thể serialize một object
buffer_time
là khoảng thời gian mà ES query, ví dụ buffer_time: 15 minutes
nghĩa là elastalert sẽ query trong dữ liệu ES kể từ lúc query ngược trở lại 15 phút.
timeframe
là khoảng thời gian mà num_events
phải xuất hiện. Ví dụ nếu num_events: 2
và timeframe: 5 minutes
. Thì sau khi query trong buffer_time
15 phút, nếu trong vòng 5 phút có xuất hiện 2 event THÌ mới alert, còn nếu trong vòng 5 phút có 1 event cũng sẽ ko alert
Lưu ý giá trị timeframe
và num_event
chỉ có tác dụng frequency type
Chef, Puppet, Ansible, và SaltStack được gọi là “configuration management” tool, nghĩa là chúng được thiết kế ra để cài đặt, quản lý phần mềm trên một hệ thống server đã tồn tại. CloudFormation và Terraform được gọi là “orchestration tools”, nghĩa là chúng được thiết kế để provision các máy chủ, và để lại công việc cấu hình máy chủ cho công cụ khác.
Việc phân biệt trên không loại trừ lẫn nhau, vì hầu hết các công cụ quản lý cấu hình có thể thực hiện một số tác vụ provision và ngược lại công cụ dàn nhạc cũng có thể làm một số tác vụ quản lý cấu hình. Tuy nhiên việc hiểu rõ bản chất từng công cụ sẽ hiểu rằng công cụ đó tốt cho tác vụ, bài toán gì (right tool for right job)
Cụ thể, nếu sử dụng Docker hoặc Packer, thì nhu cầu quản lý cấu hình (cài đặt + quản lý phần mềm) coi như đã được take care. Với Docker và Packer, ta có thể tạo ra các image (ví dụ như container hoặc máy ảo), có chứa tất cả các phần mềm cần thiết bao gồm cả cấu hình. Một khi đã có image, cái ta cần chỉ là server để chạy image đó. Và nếu cần một công cụ để provision một loạt các server thì công cụ như Terraform sẽ tốt hơn công cụ quản lý cấu hình (trong trường hợp này)
Một vấn đề khác của công cụ quản lý cấu hình là các server sẽ trở lên không nhất quán theo thời gian dù bạn có cố gắng giữ cho nó nhất quán. Điều này xảy ra khi ta cập nhật, và lại cập nhật, cấu hình trên các server sẽ dần trở lên khác nhau và việc phán đoán cũng như tái sử dụng ngày càng trở lên khó khăn hơn nữa.
Some tricks for beginner
ggdG
for deleting all filegg=G
for autoindent<
and >
for tabTa có hàm filter cho log 2017-02-22T18:31:03.321
date {
locale => "jp"
timezone => "Asia/Tokyo"
match => [ "timestamp", "ISO8601" ]
add_tag => [ "tsmatch" ]
}
Hàm này LUÔN trả về kết quả là field @timestamp
với định dạng là ISO8601, trừ khi cố tình đổi bằng target
. Với
match
dùng để định nghĩa field timestamp
trong log có định dạng gì, nếu log ko đúng định dạng thì hàng date ko thể parse và trả ra field @timestamp
được.timezone
field này khá là confuse, nhưng thực chất nó chỉ có ý nghĩa nếu log vào không có timezone, ví dụ log 2017-02-22T18:31:03.321
, ta không biết timezone của nó là gì, thì như cấu hình trên nó sẽ hiểu log này có timezone là Tokyo và parse ra kết quả là "2017-02-22T09:20:03.321Z"
. Nếu ta sửa lại timezone là UTC thì kết quả sẽ chính xác như log đầu vàoFrom document
This is useful in case the time zone cannot be extracted from the value, and is not the platform default.
When use redis as a queue in ELK, you config data_type
in logstash output is list
. Somethime you want to check how many log in queue or what log in queue.
You can use LRANGE
or LLEN
for that.
redis-cli -h 1.2.3.4 -p 6379
> keys *
1) "logstash"
> LLEN logstash
(integer) 932
LRANGE logstash 0 -1
Khi bạn đạt 1 level nào đó trong lĩnh vực của mình bạn sẽ dễ mắc 2 sai lầm:
You have a log format
{
"sdk_version": "1.0.0.",
"log_id": "7837ea84d5a8261dd0db7eeae7393f91",
"timestamp": 1484045586302,
"country:" "vn"
"report": {
"report_id": "99ffeab29896aeb130d61e5fec01f8965caf75b4665b8b369ba0b9506ca92543",
"user_agent": "sontung.mtp.ahihi"
}
}
You would like to check value of a field, example if country
is not vn
will drop it. You can config logstash like
filter {
if [country] =~ /vn$/ {
...
} else {
drop {}
}
}
But if you would like to check a sub-filed, you must config like
filter {
if [report][user_agent] =~ /ahihi$/ {
...
} else {
drop {}
}
}
sub-field is Field References
Check a field exist or not exist
#check if exists
if [event]{
...
}
#check if not exists
if ![event]{
...
}
Khi tài nguyên giới hạn, với bài toán C10K, nếu 1 thread bị blocking thì nó sẽ phải chờ cho ở đó cho tới khi nhận được dữ liệu hoặc mã lỗi. Tuy nhiên 1 thread không miễn phí, nó tốn 1 lượng tài nguyên nhất định và nếu cả 10K thread đều ngồi chờ thì không có tài nguyên mà chạy.
Các phần mềm như nginx hay nodejs giải quyết bài toán C10K như sau, nó sẽ chỉ có duy nhất 1 thread hoạt động như 1 cái bánh xe
event-queue
event-loop
, chạy single thread, nó sẽ bốc 1 task, connection trong event-queue
và giao cho 1 worker xử lý. Ngay sau khi giao cho worker, nó trở về trạng thái free để làm việc khác, lưu ý là khác với blocking-io, single thread này sẽ không đợi kết quả trả về từ worker mà quay ngược trở lại bốc tiếp 1 task khác và giao cho 1 worker khác.event-loop
.event-loop
, event-loop
trả về cho hàng đợi và client. Thì OS implement 1 API cấp thấp như select
, poll
, epoll
, nghĩa là sau khi xong OS sẽ notify ngược lại cho worker, worker sẽ biết là task i/o đó đã hoàn thành và xử lí trả về.Nên bản chất các ứng dụng như nginx hay nodejs ko có chạy single thread, mà phía sau nó vẫn có nhiều worker xử lý, nhưng thread tiếp nhận request thì chỉ có 1 mà thôi.
Tóm lại mô hình non-blocking i/o, single thread giúp giải quyết bài toán tốn tài nguyên vì không phải chờ cái gì cả.
Ví dụ với bài toàn nginx làm proxy cho java app. Ta cấu hình worker 8
tương ứng với 1 server có 8 core CPU thì sẽ sinh ra 8 worker xử lý. Sẽ có 1 master process quản lý 8 worker đó, bốc từng connection trong queue và giao cho 1 worker xử lý, worker sau khi tiếp nhận request pass qua cho java xử lý và java nếu cần xử lý tới I/O thì giao cho OS xử lý.
Với cấu hình như vậy thì nginx sẽ không tốn quá nhiều tài nguyên cho việc xử lý nhưng không có nghĩa là sẽ giúp việc xử lý NHANH hơn, vì nếu phần I/O phần cứng chậm (đĩa chậm) thì việc xử lý vẫn CHẬM, chỉ có khác là không tốn nhiều tài nguyên cho việc chờ, tới khi nào xong thì xong.
Với nginx ta cũng có thể giảm số worker xuống trong trường hợp muốn dành COU cho các dịch vụ khác chạy, không nhất thiết phải theo best-pactice là bằng số core.
Kafka là một hệ thống commit log (giống pub/sub trong redis
), khi ta có một consumer subscribe vào một topic trong kafka và lấy message log đó ra, thì message log này sẽ không bị xóa khỏi kafka, nó vẫn ở trong kafka và ta vẫn có thể lấy nó ra trong nhiều lần tiếp theo.
Tuy nhiên vẫn có thể xảy ra trường hợp không lấy được log cũ dù log đó vẫn còn trong kafka nếu ta đặt các consumer_id
và group_id
giống nhau. Lý do là do việc lưu offset của một consumer nào đó là lưu vào zookeeper. Nên nếu đặt trùng consumer_id
với một consumer khác đang đọc dữ liệu thì có thể sẽ miss mất một đoạn dữ liệu.
Ví dụ:
Nếu ở đây ta đặt trùng consumer_id
và group_id
thì khi agent file đọc tới offset 10, lấy log có offset 10 ra, sau đó agent ES đọc thì nó nghĩ là nó đã đọc offset 10 và bỏ qua đọc tiếp offset 11.
=> Log có offset 10 vẫn tồn tại trong topic của Kafka nhưng consumer lại nhầm lẫn là đã đọc rồi => mất log
Best practice là mỗi consumer nên có consumer_id
và group_id
khác nhau
If you use ELB for forwarding request to a web socket instance, you have to config proxy_protocal
on nginx. You also enable proxy_protocal
on ELB.
listen 80 proxy_protocal;
But if you use ALB for forwarding traffic to WS instance, you don't need config nginx with proxy_protocal
. Simple config
listen 80;
If not remove proxy_protocal
when switch from ELB to ALB, your site/api will error
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.