При розробці мобільних застосунків з високою частотою запитів або real-time оновленнями REST/JSON часто виявляється вузьким місцем. Ми інтегруємо gRPC API як альтернативу — з бінарним протоколом, строгою типізацією та вбудованим стрімінгом. Наша команда має багаторічний досвід у мобільній розробці та гарантує коректну роботу gRPC на будь-яких мережевих умовах.
Чому gRPC ефективніший за REST/JSON для мобільних?
gRPC виграє у REST у трьох сценаріях: високочастотні запити з передбачуваною схемою (трекінг, телеметрія), real-time streaming (чати, оновлення) та мікросервісна архітектура, де mobile gateway вже на gRPC. JSON-over-REST простіший у налагодженні та не вимагає HTTP/2, але програє в розмірі переданих даних — бінарний Protobuf у 3-4 рази компактніший за JSON. Крім того, gRPC забезпечує типобезпеку контракту, що виключає помилки серіалізації на стороні клієнта. Підвищення продуктивності особливо помітне при великому обсязі даних: типовий REST-відповідь 8-10 КБ стискається до 1-2 КБ у gRPC.
Як проектується .proto контракт?
Контракт — єдине джерело правди. Зміна файлу .proto призводить до перегенерації клієнтів на всіх платформах:
syntax = "proto3"; package mobile.api.v1; service ProductService { rpc GetProduct (GetProductRequest) returns (Product); rpc ListProducts (ListProductsRequest) returns (stream Product); rpc WatchInventory (WatchInventoryRequest) returns (stream InventoryUpdate); } message Product { string id = 1; string name = 2; int64 price_cents = 3; repeated string image_urls = 4; } message GetProductRequest { string id = 1; } stream Product у ListProducts — server-side streaming: сервер надсилає продукти по одному в міру готовності, не чекає всіх. WatchInventory — серверний стрім для real-time оновлень. Для двонаправленого стрімінгу використовуйте rpc BiDirectionalStream(stream Request) returns (stream Response).
Як gRPC вирішує проблему серіалізації на мобільних?
Бінарний формат Protobuf не лише компактний, але й строго типізований. Клієнтська кодогенерація створює з файлу .proto класи з методами get/set, що виключає помилки в іменах полів. На Android це Kotlin-датакласи з fromProto/toProto, на iOS — структури Swift з Codable. Кодогенерація вбудовується в CI: Gradle задача generateProto і Swift Package Manager плагін swift-protobuf. Це гарантує, що версії .proto на клієнті та сервері синхронізовані.
Android: gRPC-Kotlin з Coroutines та Interceptor
На Android використовуємо OkHttp-транспорт — він легший за Netty (приріст APK ~1.5 МБ проти 3 МБ) і швидше ініціалізується.
// build.gradle implementation 'io.grpc:grpc-android:1.x.x' implementation 'io.grpc:grpc-okhttp:1.x.x' val channel = ManagedChannelBuilder .forAddress("api.example.com", 443) .useTransportSecurity() .intercept(AuthInterceptor(tokenProvider)) .build() val stub = ProductServiceGrpcKt.ProductServiceCoroutineStub(channel) // Unary виклик val product = stub.getProduct(getProductRequest { id = productId }) // Server streaming stub.listProducts(listProductsRequest { categoryId = "electronics" }) .collect { product -> /* обробляємо по мірі надходження */ } AuthInterceptor реалізує ClientInterceptor і додає метадані Authorization до кожного виклику. Deadline та keepalive налаштовуються через ManagedChannelBuilder:
.keepAliveTime(30, TimeUnit.SECONDS) .keepAliveTimeout(10, TimeUnit.SECONDS) .keepAliveWithoutCalls(false) Кожен виклик повинен мати deadline — інакше завислий запит висить вічно:
stub.withDeadlineAfter(10, TimeUnit.SECONDS).getProduct(request) iOS: gRPC-Swift з async/await
На iOS використовуємо пакет grpc-swift з TLS та Swift Concurrency:
let group = PlatformSupport.makeEventLoopGroup(loopCount: 1) let channel = try GRPCChannelPool.with( target: .host("api.example.com", port: 443), transportSecurity: .tls(.makeClientDefault(compatibleWith: group)), eventLoopGroup: group ) let client = ProductService_ProductServiceNIOClient(channel: channel) let request = ProductService_GetProductRequest.with { $0.id = productId } let response = try await client.getProduct(request).response.get() // Server streaming через AsyncStream let call = client.listProducts(listRequest) for try await product in call.responses { } Як налагоджувати gRPC трафік на мобільних?
JSON-трафік легко читається в Charles/Proxyman, а Protobuf — бінарний. Для налагодження використовуємо grpcurl (command-line), grpc-ui (web UI), Wireshark з gRPC dissector. У dev-збірці підключаємо LoggingClientInterceptor з grpc-java для логування метаданих. Також можна увімкнути reflection API на сервері та виконувати запити через grpc-cli.
Як забезпечити зворотну сумісність .proto схеми?
Зворотна сумісність — ключова перевага Protobuf. Правила:
- Нові поля додаємо з новим номером, ніколи не перевикористовуємо видалені номери.
-
requiredне використовуємо (Protobuf 3 прибрав його не випадково). - Для перейменування: додаємо нове поле, старе позначаємо
reserved.
Порушення цих правил — binary incompatibility: старі версії застосунку будуть падати при отриманні нової схеми.
Як налаштувати retry та deadline для мобільного gRPC?
На стороні клієнта конфігуруємо RetryPolicy у ServiceConfig. Приклад для Kotlin:
val serviceConfig = """ { "methodConfig": [{ "name": [{}], "retryPolicy": { "maxAttempts": 4, "initialBackoff": "1s", "maxBackoff": "10s", "backoffMultiplier": 2, "retryableStatusCodes": ["UNAVAILABLE"] } }] } """.trimIndent() val channel = ManagedChannelBuilder.forAddress("api.example.com", 443) .defaultServiceConfig(JsonParser.parseString(serviceConfig).getAsJsonObject()) .enableRetry() .build() Deadline обов'язковий для кожного виклику — ми встановлюємо 10 секунд на unary та 30 секунд на streaming. При слабкому з'єднанні використовуємо withExecutor для пулу потоків і налаштовуємо keepalive.
Що входить у роботу та терміни
Процес: аналітика → проектування .proto схеми → налаштування кодогенерації в CI → реалізація gRPC клієнта на Android/iOS з TLS, auth interceptor, deadline та retry → тестування на різних мережевих умовах → деплой.
| Характеристика | gRPC | REST/JSON |
|---|---|---|
| Розмір payload | ~1-2 КБ | ~5-10 КБ |
| Типізація | строга (protobuf) | неявна (JSON) |
| Streaming | вбудований (unary, server, client, bidirectional) | polling або WebSocket |
| Налагодження | складніше (бінарний) | простіше (JSON) |
| Підтримка HTTP/2 | обов'язкова | опціональна |
| Транспорт | Android (APK) | iOS (IPA) |
|---|---|---|
| OkHttp | +1.5 МБ | — |
| Netty | +3 МБ | — |
| C-gRPC (iOS) | — | +2 МБ |
| gRPC-Swift (iOS) | — | +1.5 МБ |
Терміни: 2–4 тижні (залежить від складності). Ми гарантуємо стабільну роботу на всіх мобільних мережах і забезпечуємо повну документацію по схемі. Зв'яжіться з нами для безкоштовної оцінки вашого проєкту — розрахуємо інтеграцію gRPC під ваші завдання. Отримайте консультацію щодо впровадження gRPC у ваш мобільний застосунок, напишіть нам.







