Giter VIP home page Giter VIP logo

til's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

tiendinh595

til's Issues

Logtash check value of sub-field or check field exists

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]{
  ...
}

ES Delete by query

Ở 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.

Redis list

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

Install xmonad on Arch Linux X220

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")
    ]

Get custom headers in nginx log

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

Single thread in redis

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.

Export mongo query to csv

Đầ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

Auto increment trong MySQL M-M

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 2
  • auto_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=10auto_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=10auto_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ì

  • Server 1 => ID sẽ luôn là số lẻ (1, 3, 5, 7 ...)
auto-increment-increment = 2
auto-increment-offset = 1
  • Server 2 (ID sẽ luôn là số chẵn 2, 4, 6, 8 ...)
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

docker exec with other user

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

Logic partitioning in MySQL

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

map key trong vim

Sự khác nhau giữa setlet

  • set dùng để định nghĩa trực tiếp một cấu hình cho vim
  • let dùng để gán một giá trị cho biến

Sự khác nhau giữa các cấu hình map key trong vim

     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

Command

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

ALB + nginx

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

Configuration Management vs Orchestration

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.

kafka log

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

ALB/nginx upstream health check

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

  • Healthy threshold: 5 -> ALB sẽ kiểm tra , nếu success liên tiếp 5 lần sẽ đánh dấu nginx đó healthy
  • Unhealthy threshold: 2 -> ALB sẽ kiểu tra, nếu fail liên tiếp 2 lần sẽ đánh dấu nginx đó là unhealthy
  • Timeout; 5: Nếu trong vòng 5s, nginx ko trả về response -> đánh dấu nginx là unhealthy
  • Interval: 30, 30s sẽ gửi request check health một lần

apt

Update gói

  • 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ày
  • apt-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ơn
  • apt-get dist-upgrade:
  • apt list --upgradable: list các gói sẽ upgrade

Gỡ gói

  • apt-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ó.

Cài gói

  • 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 đặt
  • apt-get install -qq: lệnh này không hiển thị output

Tìm kiếm

  • apt-cache show pkg_name: hiển thị thông tin của một gói
  • apt-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 đó.

Khác

  • 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ác
  • Recommends Package:
  • Suggests Package:
  • apt-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 đó.

Non-blocking IO

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

c10k

  • Tất cả các task, connection sẽ được xếp vào 1 hàng đợi, như hình gọi là event-queue
  • Cái bánh xe sẽ gọi là 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.
  • Với worker, cũng xử lý non-blocking i/o, nghĩa là khi nhận 1 task liên quan tới i/o nó sẽ để hệ điều hành xử lý và không quan tâm tới task đó nữa, và tiếp tục nhận tiếp 1 task khác từ event-loop.
  • Vậy một worker không chờ OS trả về kết quả thì làm sao nó biết 1 task hoàn thành để trả về cho 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.

Serialize/Deserialize

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

  • java serialize => byte array
  • dùng các định dạng chuẩn như json, xml ...
  • protobuf, flatbuffer (do json chứa nhiều khoảng trắng, tốn dung lượng)

Docker best practices

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 ...

1. Sử dụng tối thiểu layer

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

2. Cài những thứ cần cài, xóa những thứ không cần thiết

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

3. Chọn lựa base-image

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.

4. Dockerfile Lint

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

5. Run only one process per container

6. Dont use latest tag

7. Ref

ELB + nginx + SSL

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;
}

`buffer_time` vs `timeframe` in elastalert

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: 2timeframe: 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ị timeframenum_event chỉ có tác dụng frequency type

Malformed data in ES

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

  • Set timestamp thành kiểu dữ liệu 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.

Logstash consumer_id with Kafka

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_idgroup_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ụ:

  • Có 1 topic trong kafka lưu log
  • Có 2 agent logstash lấy log từ topic trên và đổ ra 2 output khác nhau, ở đây là file và ES.

Nếu ở đây ta đặt trùng consumer_idgroup_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_idgroup_id khác nhau

vim tricks

Some tricks for beginner

  • ggdG for deleting all file
  • gg=G for autoindent
  • < and > for tab

Median (trung vị)

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

  • Sắp xếp tập dữ liệu có thứ tự
  • Lấy giá trị chính giữa chia cho 2
  • Nếu tập dữ liệu là chẵn thì lấy 2 giá trí chính giữa, cộng lại chia đôi

Ví dụ với tập dữ liệu trên ta có median = (21.2 + 23.0)/2 = 22.1

Storage Driver in Docker

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 ...

docker_storage_driver

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:

Limit connection to backend instance

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;
}

Restart a Cassandra node in cluster

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.

Rails generate model vs resourse vs scaffold

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/

logstash date filter

Ta 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ào

From document

This is useful in case the time zone cannot be extracted from the value, and is not the platform default.

Mistake of Senior

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:

  • Phán đoán tình huống, lỗi dựa trên cảm tính nhiều mà không kiểm tra lại sự thay đổi của thế giới
  • Quá tin vào kinh nghiệm của bản thân và bác bỏ các ý kiến của người ít kinh nghiêm hơn hoặc tin rằng cái mình đang làm là tốt nhất.

C10K

Bài toán C10K là bài toán liên quan đến vấn đề concurrent và blocking-io.

  • concurrent là xử lý đồng thời nhiều kết nối
  • blocking-io nghĩa là mỗi hàm liên quan tới việc xử lý IO (network, disk) sẽ phải CHỜ cho tới khi nhận được dữ liệu hay hệ điều hành trả về mã lỗi. Việc này đồng nghĩa 1 thread chỉ có thể xử lý 1 connection tại 1 thời điểm, sau khi hoàn thành thì connection tiếp theo mới được giải quyết

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

  • Tái sử dụng thread bằng thread-pool, 1 thread sau khi xử lý connection xong thì ko cần đóng mà có thể tái sử dụng.
  • Stack size mặc định của Linux là 8MB, 10K thread tương ứng 80GB :D cần tối ưu lại, ví dụ từ 64k tới 512k
  • Limit của hệ thống như open-file, max-pid, thread-max, max-map ...
  • ...

http://stackoverflow.com/questions/17593699/tcp-ip-solving-the-c10k-with-the-thread-per-client-approach

nginx lb tcp

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

Tips in Bash

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

Giả lập shitty network connections

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ư iptablestc

Optimizing for Cost in the AWS Cloud

  • Report cost từng resource (cái nào tốn nhiều thì optimizing trước)
  • Xem xét thiết kế hệ thống hỗ trợ auto-scale
  • Xóa các bản snapshot quá cũ (mongodb, migrate system, bla..bla)
  • Với S3 dùng làm backup, xóa các bản ghi quá cũ (ví dụ db backup hơn 1 năm)
  • Nén data backup trước khi đẩy lên S3
  • Xem xét tần xuất lấy data backup từ S3 → sử dụng S3 Infrequent Access
  • Làm gì thì làm, phải có số liệu trước sau để đánh giá mức độ hiệu quả
  • Reserved pricing aws
  • Pick đúng type EC2

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.