add new posts

This commit is contained in:
root
2026-04-06 16:37:26 +00:00
commit 2dce503276
13 changed files with 377 additions and 0 deletions

4
content/posts/_index.md Normal file
View File

@@ -0,0 +1,4 @@
---
title: "Статьи"
description: "Заметки об IT-индустрии и то, что лично мне кажется интересным"
---

View File

@@ -0,0 +1,27 @@
---
title: "Иерархия каталогов в Linux"
tags: ["linux", "файловые системы"]
categories: ["tech"]
---
В Linux все дерево начинается с корня - `/`. Каждая директория имеет свое строгое назначение:
### Системные и исполняемые файлы
- `/bin` и `/sbin` - содержат основные программы, необходимые для работы системы и ее восстановления. В `/sbin` лежат команды, предназначенные для системного администратора.
- `/usr` - может показаться, что является сокращением от user, однако на самом деле является аббривеатурой **Unix System Resources** - вторичная иерархия. Здесь хранятся пользовательские программы, библиотеки и документация. Современные дистрибутивы часто делают `/bin` ссылкой на `/usr/bin`
- `/lib`, '/lib64' - системные библиотеки, которые нужны программам из `/bin` и `/sbin` для запуска.
### Настройки и переменные данные
- `/etc` - здесь хранятся **конфигурационные файлы** всей системы.
- `/var` - сокращение от **Variable**. Директория для файлов, которые часто меняются. К таким, например, относятся логи (которые, кстати, находятся по пути `/var/log`), базы данных, временные файлы печати и тд.
- `/tmp` - временные файлы. Важно помнить, что во многих системах содержимое этой папки очищается при перезагрузке. Это связано с файловой системой, которая предписывает хранение файлов из /tmp в оперативной памяти.
### Пользовательские данные
- `/home` - здесь находятся личные папки пользователей. При вводе `cd ~` система переносит пользователя как раз в директорию `/home/<username>`.
- `/root` - домашний каталог суперпользователя (администратора с UID 0). Он вынесен отдельно от остальных пользователей, чтобы администратор мог войти в систему, даже если раздел `/home` не удалось примонтировать.
### Виртуальные и псевдо-файловые системы
Основная идея таких данных - что это не реальные данные на диске, а интерфейсы к ядру:
- `/proc` - виртуальная ФС, содержащая информацию о процессах и состоянии ядра. По-хорошему, можно просто прочитать файл в этой папке и узнать, например, модель процессора, который стоит на системе.
- `/sys` - информация об устройствах и драйверах.
- `/dev` - как мне изначально казалось, сокращение от developer, однако на самом деле является сокращением от **Devices** - файлы устройств. В Linux **все есть файл**, а значит, работа с жестким диском, терминалом, мышкой или любым другим устройством идет так же, как с обычным файлом.

281
content/posts/gRPS.md Normal file
View File

@@ -0,0 +1,281 @@
---
title: "Почему gRPC это лучший выбор для back-to-back взаимодействия"
tags: ["backend", "go"]
categories: ["tech"]
---
**gRPC** - это высокопроизводительный фреймворк удаленных вызовов процедур от Google, построенный на HTTP/2 и Protocol Buffers. Он быстрее REST, строго типизирован и отлично масштабируется в микросервисных архитектурах.
---
## Что такое gRPC?
Google Remote Procedure Call - это современный open-source RPC-фреймворк, позволяющий сервисам вызывать методы друг друга так, как если бы они были локальными функциями. Вместо того чтобы думать о HTTP-запросах и JSON-сериализации, разработчик просто вызывает метод на удаленном сервисе.
gRPC был разработан и открыт компанией **Google** в **2015** году. Он вырос из внутренней системы Stubby, которую Google использовал более десяти лет для связи между своими микросервисами, обрабатывающими миллиарды запросов в секунду.
Сегодня проект находится под управлением **Cloud Native Computing Foundation (CNCF)** - той же организации, что курирует Kibernetes и Prometheus. Это гарантирует его нейтральное развитие и широкую поддержку индустрии.
---
## Ключевые особенности
### Protobuf вместо JSON
gRPC использует **Protobuf** - бинарный формат сериализации данных. В отличие от текстового JSON:
- Данные занимают сильно меньше места
- Сериализация и десериализация происходят также быстрее
- Схема данных строго типизирована и версионируется через `.proto`-файлы
- Автоматическая кодогенерация клиентов и серверов на 10+ языках
### HTTP/2 под капотом
Это дает следующие возможности:
- Мультиплексирование
- Двунаправленный стриминг
- Сжатие заголовков
- Server Push
### Четыре режима взаимодействия
```
Unary RPC → клиент шлёт запрос, сервер возвращает ответ (как REST)
Server Streaming → сервер стримит поток ответов на один запрос
Client Streaming → клиент стримит данные, сервер возвращает один ответ
Bidirectional → оба шлют потоки данных друг другу одновременно
```
### Строгий контракт через .proto
`.proto`-файл — это единственный источник правды для всей коммуникации. Если один сервис меняет API, компилятор Protobuf немедленно сломает несовместимых клиентов ещё на этапе сборки.
### Встроенные инструменты
- **Deadline / Timeout** — встроенный контроль времени ожидания
- **Cancellation** — отмена запросов по цепочке вызовов
- **Load Balancing** — клиентская балансировка нагрузки из коробки
- **Health Checking** — стандартный протокол проверки готовности сервиса
- **Interceptors** — аналог middleware для аутентификации, логирования, трассировки
---
## Пример: сервис пользователей на gRPC
Разберём полный цикл: от `.proto`-контракта до рабочего клиента и сервера на Go.
### Шаг 1. Определяем контракт (`user.proto`)
```protobuf
syntax = "proto3";
package user;
option go_package = "github.com/example/user-service/proto";
// Запрос на получение пользователя
message GetUserRequest {
int64 id = 1;
}
// Ответ с данными пользователя
message GetUserResponse {
int64 id = 1;
string name = 2;
string email = 3;
string created_at = 4;
}
// Запрос на создание пользователя
message CreateUserRequest {
string name = 1;
string email = 2;
}
// Сервис с двумя методами
service UserService {
rpc GetUser (GetUserRequest) returns (GetUserResponse);
rpc CreateUser (CreateUserRequest) returns (GetUserResponse);
}
```
### Шаг 2. Генерируем код
```bash
# Устанавливаем плагины
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
# Генерируем Go-код из .proto
protoc --go_out=. --go-grpc_out=. proto/user.proto
```
После этого компилятор создаст два файла:
- `user.pb.go` — структуры данных (GetUserRequest, GetUserResponse и т.д.)
- `user_grpc.pb.go` — интерфейсы сервера и заглушки клиента
### Шаг 3. Реализуем сервер (`server/main.go`)
```go
package main
import (
"context"
"fmt"
"log"
"net"
"time"
pb "github.com/example/user-service/proto"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// userServer реализует интерфейс pb.UserServiceServer
type userServer struct {
pb.UnimplementedUserServiceServer
// В реальности здесь была бы БД
users map[int64]*pb.GetUserResponse
}
// GetUser — обработчик метода GetUser
func (s *userServer) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.GetUserResponse, error) {
user, ok := s.users[req.Id]
if !ok {
// gRPC-статус коды вместо HTTP-кодов
return nil, status.Errorf(codes.NotFound, "пользователь с id=%d не найден", req.Id)
}
return user, nil
}
// CreateUser — обработчик метода CreateUser
func (s *userServer) CreateUser(ctx context.Context, req *pb.CreateUserRequest) (*pb.GetUserResponse, error) {
if req.Email == "" {
return nil, status.Error(codes.InvalidArgument, "email обязателен")
}
newID := int64(len(s.users) + 1)
user := &pb.GetUserResponse{
Id: newID,
Name: req.Name,
Email: req.Email,
CreatedAt: time.Now().Format(time.RFC3339),
}
s.users[newID] = user
return user, nil
}
func main() {
// Слушаем порт
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("не удалось запустить listener: %v", err)
}
// Создаём gRPC-сервер
grpcServer := grpc.NewServer()
// Регистрируем наш сервис
pb.RegisterUserServiceServer(grpcServer, &userServer{
users: make(map[int64]*pb.GetUserResponse),
})
fmt.Println("gRPC-сервер запущен на :50051")
if err := grpcServer.Serve(lis); err != nil {
log.Fatalf("ошибка сервера: %v", err)
}
}
```
### Шаг 4. Пишем клиент (`client/main.go`)
```go
package main
import (
"context"
"fmt"
"log"
"time"
pb "github.com/example/user-service/proto"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func main() {
// Подключаемся к серверу
conn, err := grpc.Dial(
"localhost:50051",
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil {
log.Fatalf("не удалось подключиться: %v", err)
}
defer conn.Close()
// Создаём клиента — это та самая "магия" gRPC:
// вызов метода выглядит как локальная функция
client := pb.NewUserServiceClient(conn)
// Контекст с таймаутом — хорошая практика для каждого запроса
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// Создаём пользователя
created, err := client.CreateUser(ctx, &pb.CreateUserRequest{
Name: "Алиса",
Email: "alice@example.com",
})
if err != nil {
log.Fatalf("ошибка CreateUser: %v", err)
}
fmt.Printf("Создан пользователь: ID=%d, Name=%s\n", created.Id, created.Name)
// Получаем пользователя по ID
user, err := client.GetUser(ctx, &pb.GetUserRequest{Id: created.Id})
if err != nil {
log.Fatalf("ошибка GetUser: %v", err)
}
fmt.Printf("Получен пользователь: %s <%s>\n", user.Name, user.Email)
}
```
### Шаг 5. Запускаем
```bash
# Терминал 1: запускаем сервер
go run server/main.go
# gRPC-сервер запущен на :50051
# Терминал 2: запускаем клиент
go run client/main.go
# Создан пользователь: ID=1, Name=Алиса
# Получен пользователь: Алиса <alice@example.com>
```
---
## gRPC vs REST: когда что выбирать?
| Критерий | REST | gRPC |
|---|---|---|
| **Скорость** | Хорошая | Отличная (бинарный протокол) |
| **Типизация** | Слабая (JSON) | Строгая (Protobuf) |
| **Стриминг** | Ограниченный (SSE) | Полноценный (4 режима) |
| **Браузерная поддержка** | Нативная | Нужен gRPC-Web |
| **Отладка** | Легко (curl, Postman) | Сложнее (нужен grpcurl) |
| **Контракт API** | OpenAPI/Swagger | `.proto` (строже) |
| **Кодогенерация** | Опционально | Встроена |
**Выбирайте gRPC**, когда:
- Сервисы общаются только между собой (backend-to-backend)
- Важна производительность и объём трафика
- Нужен стриминг данных в реальном времени
- Команда большая и строгий контракт критичен
**Выбирайте REST**, когда:
- API потребляется браузером напрямую
- Важна простота и человекочитаемость
- Команда небольшая и overhead Protobuf не оправдан
---
## Итог
gRPC — это не просто «быстрый REST». Это принципиально другой подход к межсервисному взаимодействию, где строгий контракт, бинарная эффективность и встроенный стриминг делают его идеальным фундаментом для микросервисных архитектур. Google, Netflix, Cloudflare и десятки других компаний используют его в продакшне под нагрузками, которые REST с JSON попросту не выдержал бы.
Если вы строите систему из нескольких сервисов — gRPC стоит рассмотреть как первый выбор для их взаимодействия.

View File

@@ -0,0 +1 @@
HELLOW THERE!

1
content/projects/HSE.md Normal file
View File

@@ -0,0 +1 @@
# Кроме всего прочего я работаю frontend-разработчиком в Высшей Школе Экономики и занимаюсь разработкой системы Решебник