Comments 8
Используем в работе grpc gateway, очень удобно
Эх, на самом интересном месте, хотел посмотреть сравнение с grpc-web, потому что это то решение, которое предложил и реализовал ии в моем пет проекте для решения обозначенной проблемы (причем реализовал без затруднений, по этому делаю вывод что вариант гугла как минимум широко распространен).
Сам с grpc ранее не работал и до реализации даже не знал что нет нативной возможности ходить напрямую из браузера.
А вот gRPC-Web на самом деле реально хуже, чем просто gateway , не в плане техологии, а в плане юзабилити
Но обо всем как раз напишу во второй части :)
Интересно. Не знал, что стримы тоже можно проксировать на фронт. Даже двунаправленные. Круто
Акутально для меня + хороший материал, жду вторую часть
GRPC gateway неудобен для полноценного использования HTTP, плюс на проксирование дополнительные ресурсы уходят.
У нас на работе тоже его использовали и в какой-то момент возникла необходимость больше возможностей HTTP использовать.
В частности, отдавать 304 Not Modified, когда данные не обновились. На гейтвее это если и можно было сделать, то очень неудобно.
Поэтому решили нативную реализацию сделать. И чтобы плавно перейти, я начал делать генератор http сервера из proto файла.
В целом всё получилось и с гейтвея мы слезли. Теперь можно из прото файла отдельно сделать GRPC и HTTP сервер.
Производительность улучшилась и можно явно заголовками оперировать.
Стримы и файлы не поддерживаются, т.к. потребности не было, но в целом хочется проект доделать, чтобы полноценным был.
Генерацию спецификации на гугловый генератор перенесли. Есть нюансы, но в целом аналогично работает https://github.com/google/gnostic/tree/main/cmd/protoc-gen-openapi
Сам проект генератора http: https://github.com/MUlt1mate/protoc-gen-httpgo
Сорян, не удержался:
Отличный вопрос! Представим, что я создаю **Claude RPC** 😄. Вот что бы я изменила, анализируя боль разработчиков:
## Главные проблемы gRPC, которые я бы решила:
### 1. **Простота дебага** 🔍
**Проблема:** gRPC трудно дебажить — бинарный протокол, нужны специальные инструменты.
**Моё решение:** Гибридный подход
```proto
service UserService {
rpc GetUser(GetUserRequest) returns (User) {
// Автоматом генерирует и binary, и JSON endpoints
debug_mode: true; // В dev - JSON, в prod - binary
}
}
```
- В dev режиме все запросы дублируются в JSON
- Встроенный web UI для тестирования (как Swagger, но лучше)
- Автоматические curl команды для каждого метода
### 2. **Нативная поддержка браузеров** 🌐
**Проблема:** gRPC-Web требует прокси, неполная функциональность.
**Моё решение:**
- Протокол изначально работает через WebSocket + HTTP/2
- Fallback на обычный HTTP/1.1 для старых браузеров
- Streaming работает везде, включая мобильные браузеры
### 3. **Умная генерация документации** 📚
**Проблема:** Protobuf комментарии это не документация.
**Моё решение:**
```proto
service UserService {
// @title: Получить пользователя
// @description: Возвращает данные пользователя по ID
// @example: {"user_id": 123}
// @response_example: {"id": 123, "name": "John"}
// @error: USER_NOT_FOUND если пользователь не найден
rpc GetUser(GetUserRequest) returns (User);
}
```
- Автогенерация интерактивной документации
- Живые примеры с реальными данными
- Автотесты на основе примеров
### 4. **Встроенная обсерваемость** 📊
**Проблема:** Нужно вручную добавлять метрики, трейсинг, логи.
**Моё решение:**
```proto
service UserService {
rpc GetUser(GetUserRequest) returns (User) {
// Автоматические метрики
metrics: {
track_latency: true,
track_errors: true,
custom_labels: ["user_type", "region"]
};
// Автоматический трейсинг
tracing: enabled;
}
}
```
### 5. **Умная генерация кода** 🤖
**Проблема:** Сгенерированный код часто неудобный.
**Моё решение:**
- Builder pattern для сложных объектов
- Автоматическая валидация
- Retry логика из коробки
- Graceful degradation
```typescript
// Вместо:
const request = new GetUserRequest();
request.setUserId(123);
client.getUser(request, callback);
// Получаем:
const user = await client.users.get(123, {
retry: { attempts: 3, backoff: "exponential" },
timeout: "5s",
fallback: defaultUser
});
```
### 6. **Миграции и версионирование** 🔄
**Проблема:** Сложно мигрировать между версиями API.
**Моё решение:**
```proto
service UserService {
rpc GetUser(GetUserRequest) returns (User) {
version: "v2";
backwards_compatible_with: ["v1"];
migration_guide: "user_id is now int64 instead of string";
}
}
```
- Автоматические адаптеры между версиями
- Предупреждения о deprecated полях
- Плавная миграция данных
### 7. **Встроенный мокинг** 🎭
**Проблема:** Сложно мокать gRPC сервисы для тестов.
**Моё решение:**
```proto
message User {
int64 id = 1 [(mock) = "faker.random_int(1, 1000)"];
string name = 2 [(mock) = "faker.name()"];
string email = 3 [(mock) = "faker.email()"];
}
```
- Автогенерация реалистичных mock данных
- Встроенный mock сервер
- Scenarios для разных тестовых случаев
### 8. **Производительность** ⚡
- Zero-copy десериализация где возможно
- Умное батчирование запросов
- Адаптивное сжатие (анализирует данные и выбирает лучший алгоритм)
- Connection pooling из коробки
### 9. **Developer Experience** 💝
```bash
# Один инструмент для всего
claude-rpc init my-service
claude-rpc generate --lang=typescript --lang=go
claude-rpc test --interactive
claude-rpc deploy --env=staging
claude-rpc docs --serve --port=8080
```
### 10. **Расширяемость** 🔧
```proto
// Плагины прямо в proto файле
service UserService {
middleware: ["auth", "rate_limit", "cache"];
rpc GetUser(GetUserRequest) returns (User) {
cache: { ttl: "5m", key: "user:${user_id}" };
rate_limit: { rpm: 100, burst: 10 };
}
}
```
## Результат:
**Claude RPC** был бы как gRPC, но:
- Проще в дебаге и разработке
- Работает везде без костылей
- Самодокументируется
- Наблюдаем из коробки
- Легко тестируется и мокается
По сути, это gRPC с человеческим лицом — вся мощь, но без головной боли!
Что думаешь? Какие проблемы gRPC больше всего бесят в твоем опыте?
Как я пытался засунуть gRPC в браузер — часть первая