Jump to content
View in the app

A better way to browse. Learn more.

T.M.I IThub

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Резервное копирование в Linux: стратегии и инструменты

Правило 3-2-1

Любая стратегия резервного копирования должна начинаться с правила 3-2-1:

  • 3 копии данных

  • 2 разных типа носителей

  • 1 копия вне офиса

Rsync: умное инкрементальное копирование

#!/usr/bin/env bash
# Скрипт резервного копирования с ротацией

BACKUP_SOURCE="/var/www"
BACKUP_DEST="/mnt/backup"
RETAIN_DAYS=30
DATE=$(date +%Y%m%d_%H%M%S)

# Создаём снэпшот через hard links (не дублируем неизменённые файлы)
rsync -avz --delete \
    --link-dest="$BACKUP_DEST/latest" \
    --exclude="*.log" \
    --exclude="cache/" \
    --exclude="tmp/" \
    "$BACKUP_SOURCE/" \
    "$BACKUP_DEST/$DATE/"

# Обновляем симлинк на последний бэкап
ln -sfn "$BACKUP_DEST/$DATE" "$BACKUP_DEST/latest"

# Удаляем старые бэкапы
find "$BACKUP_DEST" -maxdepth 1 -type d -mtime +$RETAIN_DAYS -exec rm -rf {} +

echo "Backup completed: $BACKUP_DEST/$DATE"
du -sh "$BACKUP_DEST/$DATE"

Borg: дедупликация и шифрование

Borg — продвинутый инструмент с дедупликацией (одинаковые блоки хранятся один раз):

# Установка
apt install borgbackup

# Инициализация репозитория с шифрованием
borg init --encryption=repokey-blake2 user@backup-server:/backups/myserver

# Создание бэкапа
borg create \
    --verbose \
    --filter AME \
    --list \
    --stats \
    --show-rc \
    --compression lz4 \
    --exclude-caches \
    --exclude '/home/*/.cache/*' \
    --exclude '/var/cache/*' \
    --exclude '/var/tmp/*' \
    user@backup-server:/backups/myserver::myserver-$(date +%Y%m%d_%H%M) \
    /etc \
    /var/www \
    /home \
    /var/lib/mysql  # осторожно с активной БД!

# Список архивов
borg list user@backup-server:/backups/myserver

# Проверка целостности
borg check user@backup-server:/backups/myserver

# Восстановление
cd /tmp/restore
borg extract user@backup-server:/backups/myserver::myserver-20240115_0300 \
    var/www/myapp/public  # только конкретная директория

# Ротация (хранить: 7 ежедневных, 4 недельных, 12 ежемесячных)
borg prune \
    --keep-daily=7 \
    --keep-weekly=4 \
    --keep-monthly=12 \
    user@backup-server:/backups/myserver

Бэкап MySQL без блокировок

#!/usr/bin/env bash
# Бэкап MySQL с минимальным влиянием на продакшн

DB_USER="backup"
DB_PASS="backup_password"
BACKUP_DIR="/var/backups/mysql"
DATE=$(date +%Y%m%d_%H%M)

mkdir -p "$BACKUP_DIR"

# Создаём пользователя для бэкапа (только необходимые права)
# GRANT SELECT, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER, PROCESS ON *.* TO 'backup'@'localhost';

# Бэкап всех баз
mysqldump \
    --user="$DB_USER" \
    --password="$DB_PASS" \
    --single-transaction \
    --routines \
    --triggers \
    --events \
    --all-databases \
    --master-data=2 \
    | gzip > "$BACKUP_DIR/full-$DATE.sql.gz"

# Проверяем что файл не пустой
size=$(stat -c%s "$BACKUP_DIR/full-$DATE.sql.gz")
if [[ $size -lt 1000 ]]; then
    echo "ERROR: Backup file too small ($size bytes)" >&2
    rm "$BACKUP_DIR/full-$DATE.sql.gz"
    exit 1
fi

echo "Backup created: $BACKUP_DIR/full-$DATE.sql.gz ($size bytes)"

# Ротация — удаляем старше 7 дней
find "$BACKUP_DIR" -name "full-*.sql.gz" -mtime +7 -delete

# XtraBackup для горячего бэкапа InnoDB (без --single-transaction ограничений)
# apt install percona-xtrabackup-80
# xtrabackup --backup --user="$DB_USER" --password="$DB_PASS" \
#     --target-dir="$BACKUP_DIR/xtrabackup-$DATE"

Проверка восстановления — самое важное

Бэкап без проверки восстановления — не бэкап. Автоматизируйте:

#!/usr/bin/env bash
# Тест восстановления MySQL (запускать еженедельно)

BACKUP_FILE=$(ls -t /var/backups/mysql/full-*.sql.gz | head -1)
TEST_DB="restore_test_$(date +%s)"

echo "Testing restore of $BACKUP_FILE"

# Создаём тестовую базу
mysql -e "CREATE DATABASE $TEST_DB"

# Восстанавливаем
zcat "$BACKUP_FILE" | mysql "$TEST_DB"

# Проверяем количество таблиц
table_count=$(mysql -sN -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='$TEST_DB'")
echo "Tables restored: $table_count"

# Удаляем тестовую базу
mysql -e "DROP DATABASE $TEST_DB"

if [[ $table_count -gt 0 ]]; then
    echo "Restore test PASSED"
else
    echo "Restore test FAILED!" >&2
    exit 1
fi

Nginx: тюнинг и продвинутая конфигурация

Производительность nginx

# /etc/nginx/nginx.conf

user www-data;
# Одни worker per CPU core
worker_processes auto;
# Привязываем к ядрам (снижаем context switch)
worker_cpu_affinity auto;

# Максимум соединений = worker_processes * worker_connections
events {
    worker_connections 4096;
    use epoll;           # лучший I/O multiplexer для Linux
    multi_accept on;     # принимаем все соединения за один раз
}

http {
    # Базовые оптимизации
    sendfile on;
    tcp_nopush on;       # отправлять заголовки и начало файла вместе
    tcp_nodelay on;      # отключить Nagle для активных соединений

    # Таймауты
    keepalive_timeout 65;
    keepalive_requests 1000;
    client_header_timeout 15;
    client_body_timeout 15;
    send_timeout 15;

    # Буферы
    client_body_buffer_size 128k;
    client_max_body_size 50M;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 16k;

    # Сжатие
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_comp_level 5;
    gzip_types
        text/plain
        text/css
        text/javascript
        application/javascript
        application/json
        application/xml
        image/svg+xml;

    # Кэширование статики
    open_file_cache max=10000 inactive=20s;
    open_file_cache_valid 30s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;

    # Безопасность
    server_tokens off;
    more_clear_headers Server;  # если установлен nginx-extras

    # Rate limiting
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
    limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
    limit_conn_zone $binary_remote_addr zone=perip:10m;
}

Virtual host для PHP-приложения

# /etc/nginx/sites-available/myapp.conf

# Upstream pool с health checks
upstream php_fpm {
    least_conn;  # балансировка по наименее загруженному
    server 127.0.0.1:9000 weight=5 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:9001 weight=5 max_fails=3 fail_timeout=30s;
    keepalive 32;  # постоянные соединения к FPM
}

# Кэш для FastCGI ответов
fastcgi_cache_path /var/cache/nginx/fastcgi
    levels=1:2
    keys_zone=php_cache:100m
    max_size=2g
    inactive=60m
    use_temp_path=off;

server {
    listen 80;
    server_name myapp.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name myapp.example.com;
    root /var/www/myapp/public;
    index index.php;

    # SSL
    ssl_certificate /etc/letsencrypt/live/myapp.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/myapp.example.com/privkey.pem;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    ssl_stapling on;
    ssl_stapling_verify on;

    # Безопасность
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # Логи
    access_log /var/log/nginx/myapp-access.log combined buffer=512k flush=1m;
    error_log /var/log/nginx/myapp-error.log warn;

    # Ограничения
    limit_conn perip 20;

    # Статика с долгим кешированием
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        log_not_found off;
        access_log off;
    }

    # API с rate limiting
    location /api/ {
        limit_req zone=api burst=20 nodelay;
        try_files $uri $uri/ /index.php?$query_string;
    }

    location /api/auth {
        limit_req zone=login burst=5 nodelay;
        try_files $uri $uri/ /index.php?$query_string;
    }

    # PHP-FPM
    location ~ \.php$ {
        fastcgi_pass php_fpm;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;

        # Кеширование (осторожно — только для некэшируемого поставьте X-Cache-Bypass)
        fastcgi_cache php_cache;
        fastcgi_cache_key "$scheme$request_method$host$request_uri";
        fastcgi_cache_valid 200 302 60m;
        fastcgi_cache_valid 404 1m;
        fastcgi_cache_bypass $http_pragma $http_authorization $cookie_PHPSESSID;
        fastcgi_no_cache $http_pragma $http_authorization;
        add_header X-Cache-Status $upstream_cache_status;

        # Буферизация
        fastcgi_buffer_size 128k;
        fastcgi_buffers 4 256k;
        fastcgi_busy_buffers_size 256k;

        # Таймаут для долгих запросов
        fastcgi_read_timeout 300;
    }

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # Запрещаем служебные файлы
    location ~ /\.(ht|git|env) {
        deny all;
        return 404;
    }
}

Централизованное логирование: rsyslog, loki, ELK

rsyslog: маршрутизация логов

# /etc/rsyslog.conf — продвинутая конфигурация

# Шаблоны
template(name="FileFormat" type="string"
    string="%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n"
)

# JSON формат для Logstash/Loki
template(name="JSONFormat" type="list") {
    constant(value="{")
    constant(value="\"timestamp\":\"")
    property(name="timereported" dateFormat="rfc3339")
    constant(value="\",\"host\":\"")
    property(name="hostname")
    constant(value="\",\"severity\":\"")
    property(name="syslogseverity-text")
    constant(value="\",\"facility\":\"")
    property(name="syslogfacility-text")
    constant(value="\",\"program\":\"")
    property(name="programname")
    constant(value="\",\"pid\":\"")
    property(name="procid")
    constant(value="\",\"message\":\"")
    property(name="msg" format="json")
    constant(value="\"}\n")
}

# Маршрутизация по приоритету
*.emerg  :omusrmsg:*                    # все терминалы при критической ошибке
auth,authpriv.*  /var/log/auth.log
mail.*   -/var/log/mail.log             # дефис = буферизованная запись
cron.*   /var/log/cron.log
*.warn   /var/log/warnings.log

# Отдельный файл для nginx
if $programname == 'nginx' then {
    action(type="omfile" file="/var/log/nginx/error.log" template="FileFormat")
    stop
}

# Пересылка на центральный сервер
*.* action(type="omfwd"
    target="log-server.internal"
    port="514"
    protocol="tcp"
    template="JSONFormat"
    action.resumeRetryCount="-1"
    queue.type="linkedList"
    queue.size="50000"
    queue.filename="rsyslog_queue"
    queue.saveonshutdown="on"
)

Loki + Promtail: современный стек

Loki — это "Prometheus для логов", хранит логи как метрики с метками:

# /etc/promtail/promtail-config.yaml
server:
  http_listen_port: 9080

positions:
  filename: /var/log/positions.yaml

clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
  - job_name: nginx
    static_configs:
      - targets: [localhost]
        labels:
          job: nginx
          env: production
          __path__: /var/log/nginx/access.log
    
    pipeline_stages:
      - regex:
          expression: '^(?P<remote_addr>\S+) - (?P<remote_user>\S+) \[(?P<time>[^\]]+)\] "(?P<method>\S+) (?P<path>[^\s"]+)[^"]*" (?P<status>\d+) (?P<body_bytes>\d+)'
      
      - labels:
          method:
          status:
      
      - metrics:
          http_requests_total:
            type: Counter
            description: "Total HTTP requests"
            source: status
            config:
              action: inc

  - job_name: php-app
    static_configs:
      - targets: [localhost]
        labels:
          job: php-app
          __path__: /var/www/myapp/storage/logs/*.log
    
    pipeline_stages:
      - multiline:
          firstline: '^\[\d{4}-\d{2}-\d{2}'
          max_wait_time: 3s
      
      - regex:
          expression: '^\[(?P<time>[^\]]+)\] (?P<env>\w+)\.(?P<level>[A-Z]+): (?P<message>.+)'
      
      - labels:
          level:
          env:

Запросы LogQL (язык Loki)

# Все ошибки nginx
{job="nginx"} |= "error"

# HTTP 500 ошибки за последний час
{job="nginx"} | regex `status=(?P<status>\d+)` | status="500"

# Медленные запросы (>1 секунды)
{job="nginx"} | regex `request_time=(?P<rt>[0-9.]+)` | rt > 1.0

# Топ URL по количеству запросов
topk(10, sum by (path) (rate({job="nginx"} | json [5m])))

# Уровень ошибок в приложении
sum(rate({job="php-app", level="ERROR"}[5m])) by (level)

Ansible: управление конфигурациями Linux-серверов

Структура Ansible-проекта

ansible/
├── ansible.cfg
├── inventory/
│   ├── production/
│   │   ├── hosts.yml
│   │   └── group_vars/
│   │       ├── all.yml
│   │       ├── web.yml
│   │       └── db.yml
│   └── staging/
│       └── hosts.yml
├── roles/
│   ├── common/
│   ├── nginx/
│   ├── php/
│   └── mysql/
└── playbooks/
    ├── site.yml
    ├── deploy.yml
    └── update.yml

ansible.cfg

[defaults]
inventory = inventory/production
remote_user = deploy
private_key_file = ~/.ssh/id_ed25519
host_key_checking = False
retry_files_enabled = False
stdout_callback = yaml
callback_whitelist = timer, profile_tasks
forks = 20

[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=60s

Роль для hardening

# roles/common/tasks/main.yml
---
- name: Update and upgrade apt packages
  apt:
    upgrade: dist
    update_cache: yes
    cache_valid_time: 3600

- name: Install required packages
  apt:
    name:
      - ufw
      - fail2ban
      - unattended-upgrades
      - logrotate
      - htop
      - curl
      - git
    state: present

- name: Configure sysctl security settings
  sysctl:
    name: "{{ item.key }}"
    value: "{{ item.value }}"
    state: present
    reload: yes
  loop: "{{ sysctl_settings }}"

- name: Configure UFW
  ufw:
    state: enabled
    policy: deny
    direction: incoming

- name: Allow SSH
  ufw:
    rule: allow
    port: "{{ ssh_port }}"
    proto: tcp

- name: Configure fail2ban
  template:
    src: jail.local.j2
    dest: /etc/fail2ban/jail.local
    owner: root
    group: root
    mode: '0644'
  notify: restart fail2ban

- name: Configure SSH
  template:
    src: sshd_config.j2
    dest: /etc/ssh/sshd_config
    validate: 'sshd -t -f %s'
    owner: root
    group: root
    mode: '0600'
  notify: restart sshd

Идемпотентность: делаем правильно

# Создание пользователя (идемпотентно)
- name: Create deploy user
  user:
    name: deploy
    groups: www-data
    shell: /bin/bash
    create_home: yes
    state: present

# Копируем SSH ключ
- name: Set authorized keys
  authorized_key:
    user: deploy
    state: present
    key: "{{ lookup('file', 'files/deploy_key.pub') }}"
    exclusive: yes  # удалить другие ключи

# Изменение конфига только если нужно
- name: Configure PHP-FPM
  template:
    src: php-fpm-pool.conf.j2
    dest: /etc/php/8.2/fpm/pool.d/www.conf
    owner: root
    group: root
    mode: '0644'
  notify: reload php-fpm

# Handlers (выполняются только если что-то изменилось)
# roles/php/handlers/main.yml
- name: reload php-fpm
  service:
    name: php8.2-fpm
    state: reloaded

- name: restart php-fpm
  service:
    name: php8.2-fpm
    state: restarted

Деплой приложения через Ansible

# playbooks/deploy.yml
---
- name: Deploy MyApp
  hosts: web
  serial: "30%"  # Rolling update: 30% серверов одновременно
  vars:
    app_dir: /var/www/myapp
    git_repo: git@github.com:company/myapp.git
    git_branch: "{{ branch | default('main') }}"

  tasks:
    - name: Pull latest code
      git:
        repo: "{{ git_repo }}"
        dest: "{{ app_dir }}"
        version: "{{ git_branch }}"
        force: yes

    - name: Install Composer dependencies
      composer:
        command: install
        working_dir: "{{ app_dir }}"
        no_dev: yes
        optimize_autoloader: yes

    - name: Run migrations
      command: php spark migrate --all
      args:
        chdir: "{{ app_dir }}"
      run_once: true  # только на одном сервере

    - name: Clear application cache
      command: php spark cache:clear
      args:
        chdir: "{{ app_dir }}"

    - name: Reload PHP-FPM (graceful)
      service:
        name: php8.2-fpm
        state: reloaded

    - name: Warm up cache
      uri:
        url: "https://{{ inventory_hostname }}/health"
        status_code: 200
      retries: 5
      delay: 2

Диагностика Linux: алгоритм поиска проблем

Методология USE

USE Method (Brendan Gregg): для каждого ресурса проверяем:

  • Utilization — использование (в %)

  • Saturation — насыщение (очереди, ожидание)

  • Errors — ошибки

# CPU Utilization
mpstat -P ALL 1 3

# CPU Saturation (очередь на выполнение)
vmstat 1 | awk '{print $1}'  # r - run queue

# Memory Utilization
free -h

# Memory Saturation (swapping)
vmstat 1 | awk '{print $7, $8}'  # si/so - swap in/out

# Disk Utilization
iostat -xz 1 | grep -E "Device|sd|nvme"

# Disk Saturation (await > service time)
iostat -xz 1 | awk 'NR>3 {print $1, $16}'  # %util

# Network Utilization
sar -n DEV 1 5

60-секундный анализ сервера

# Быстрый обзор за 60 секунд (по Brendan Gregg)

uptime                    # load average
dmesg -T | tail -5        # ошибки ядра
vmstat -SM 1 3            # VM, CPU, I/O обзор
mpstat -P ALL 1 3         # CPU по ядрам
pidstat 1 3               # процессы
iostat -xz 1 3            # I/O дисков
free -m                   # память
sar -n DEV 1 3            # сеть
sar -n TCP,ETCP 1 3       # TCP метрики
top                       # интерактивно

Диагностика "сервер завис"

# 1. Можем ли мы что-то делать?
# Если не отвечает по SSH - физический доступ или IPMI/iLO

# 2. Что не отвечает?
ping server-ip             # сеть живая?
nc -zv server-ip 22        # SSH порт открыт?
nc -zv server-ip 80        # HTTP открыт?

# 3. Загрузка
uptime
# load: 0.5 — норма
# load: = CPU cores — занят
# load: > CPU cores * 2 — перегружен

# 4. Кто виноват?
top -bn1 | head -20
ps auxwf | head -30

# 5. Есть ли OOM?
dmesg | grep -i "oom\|killed process"
journalctl -k --since "1 hour ago" | grep -i oom

# 6. Диск переполнен?
df -h
du -sh /var /tmp /home    # кто занял место

# 7. Иноды кончились?
df -i

# 8. Что происходит с сетью?
ss -s                      # статистика сокетов
ss -tnp state time-wait | wc -l  # TIME_WAIT
netstat -i                 # ошибки на интерфейсах

# 9. Дисковые проблемы
dmesg | grep -i "error\|fail\|i/o"
smartctl -H /dev/sda       # здоровье диска

# 10. Полная картина за последний час
sar -A 1 10               # всё что собрал sar

strace и ltrace: что делает процесс

# Что делает процесс прямо сейчас
strace -p $(pgrep nginx | head -1)

# Только конкретные системные вызовы
strace -e trace=open,read,write,network -p PID

# Статистика системных вызовов за 5 секунд
strace -c -p PID -e trace=all &
sleep 5
kill %1

# ltrace — вызовы библиотечных функций
ltrace -p PID

# Запустить и трейсить
strace -e trace=network curl google.com 2>&1 | grep connect

# Дочерние процессы тоже
strace -f -p PID -o /tmp/strace.log

Анализ производительности с perf

# Профиль за 10 секунд (нужен linux-tools-generic)
perf record -F 99 -g -p $(pgrep php-fpm | head -1) -- sleep 10
perf report --stdio | head -50

# Hotspot функции
perf top -K -p $(pgrep nginx | head -1)

# Счётчики производительности
perf stat -p PID -- sleep 5
# cache-misses, branch-misses, context-switches

# Flame graph (установить FlameGraph от Brendan Gregg)
perf record -F 99 -ag -- sleep 10
perf script | stackcollapse-perf.pl | flamegraph.pl > flame.svg

Диагностика сетевых задержек

# Измеряем задержки на разных уровнях
# 1. ICMP (сеть)
ping -c 100 server-ip | tail -3

# 2. TCP handshake (OS + сеть)
hping3 -S -c 100 -p 80 server-ip | tail -5

# 3. HTTP time_to_first_byte (приложение)
curl -o /dev/null -s -w "
dns:      %{time_namelookup}s
connect:  %{time_connect}s
tls:      %{time_appconnect}s
ttfb:     %{time_starttransfer}s
total:    %{time_total}s
" https://myapp.example.com

# 4. Детальная трассировка HTTP
curl -v --trace-time https://myapp.example.com 2>&1 | head -50

# 5. Tcpdump для анализа конкретного запроса
tcpdump -i eth0 -w request.pcap host client-ip and port 443
# Открываем в Wireshark для детального анализа

# 6. Статистика задержки на уровне сокета
ss -ti  # socket timing info

Инструменты для экстренной диагностики: шпаргалка

# Процессы
ps auxwf               # дерево процессов
pstree -pu             # красивое дерево
pgrep -a nginx         # найти процессы
lsof -p PID            # файлы процесса
lsof -i :80            # кто слушает порт 80
fuser -n tcp 80        # pid процесса на порту

# Файловая система
lsof +D /var/log       # кто держит файлы в директории
inotifywait -m /etc/passwd  # слежка за изменениями
find / -newer /tmp/stamp -type f 2>/dev/null  # что изменилось с timestamp

# Сеть
tcpdump -i any port 80 -nn -q
conntrack -L | wc -l   # количество трекируемых соединений
nmap -sV localhost     # сканируем себя

# История команд в случае инцидента
history | grep -i "rm\|mv\|chmod\|dd" | tail -20
last | head -20        # последние логины
lastb | head -10       # неудачные логины
who                    # кто сейчас залогинен
w                      # что они делают

Диагностика — это смесь знаний, методологии и опыта. Самые ценные навыки: не паниковать, следовать методологии USE, измерять прежде чем делать выводы, и помнить что 90% проблем с производительностью — это диск, память или сеть, а не код.

User Feedback

Create an account or sign in to leave a review

There are no reviews to display.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.