gRPC هو إطار عمل RPC عالي الأداء من Google يعمل فوق HTTP/2 ويصبح معياراً فعلياً للتفاعل بين الخدمات. ولكن بمجرد أن تحاول تمرير حركة gRPC عبر وكيل، تظهر المشاكل على الفور: معظم خوادم الوكلاء التقليدية لا تعرف كيفية التعامل مع HTTP/2 والاتصالات المستمرة طويلة الأمد. في هذه المقالة، سنستعرض كيفية إعداد gRPC بشكل صحيح عبر الوكيل — من اختيار البنية إلى تكوينات Nginx وEnvoy وHAProxy المحددة.
لماذا gRPC لا يعمل بشكل جيد مع الوكلاء العاديين
لفهم المشكلة، يجب أن نفهم كيف يعمل gRPC تحت الغطاء. يستخدم البروتوكول HTTP/2 كطبقة نقل، وهذا يميزه جذرياً عن REST المعتاد فوق HTTP/1.1. تم تصميم معظم الوكلاء المؤسسيين، وجدران الحماية، وموازني الحمل في عصر HTTP/1.1 ولا يعرفون ببساطة كيفية معالجة تدفقات HTTP/2 المتعددة.
إليك المشاكل المحددة التي ستواجهها عند محاولة تمرير gRPC عبر وكيل HTTP التقليدي:
- الخفض إلى HTTP/1.1. العديد من الوكلاء يقومون تلقائياً بخفض إصدار البروتوكول. يتطلب gRPC HTTP/2 — بدون ذلك، لن يتم إنشاء الاتصال، وسيتلقى العميل خطأ
UNAVAILABLE. - قطع الاتصالات طويلة الأمد. يستخدم gRPC بشكل نشط البث من الخادم والاتصالات ثنائية الاتجاه. الوكلاء الذين لديهم مهلات عدوانية (خاصة AWS ELB Classic، وبعض إصدارات Squid) يقطعون الاتصالات التي لا تنقل البيانات لأكثر من 60 ثانية.
- مشاكل مع Content-Type. يستخدم gRPC رأس
Content-Type: application/grpc. قد يرفض الوكيل الذي لا يعرف هذا النوع الطلب أو يقوم بتخزين الجسم بشكل غير صحيح. - Trailers (تريلرز). يستخدم gRPC تريلرز HTTP/2 لنقل حالة انتهاء الاستدعاء. لا تدعم الوكلاء HTTP/1.1 التريلرز — ستفقد معلومات الحالة.
- تخزين الجسم. يقوم بعض الوكلاء بتخزين الجسم بالكامل من الاستجابة قبل إرساله إلى العميل. بالنسبة لاستدعاءات gRPC المتدفقة، يعني هذا أن العميل لن يتلقى أي رسالة حتى ينتهي البث.
الاستنتاج الرئيسي:
لعمل gRPC عبر الوكيل، تحتاج إلى وكيل يدعم HTTP/2 من النهاية إلى النهاية أو وضع نفق خاص. الوكيل التقليدي HTTP بدون تعديل التكوين لن يكون مناسباً.
نفق HTTP/2: كيف يعمل
هناك نهجان مختلفان تماماً لتمرير حركة gRPC، ومن المهم فهم الفرق بينهما لاختيار الحل الصحيح لبنيتك.
النهج 1: HTTP/2 من النهاية إلى النهاية (موصى به)
يفهم الوكيل HTTP/2 ويقوم بإنشاء اتصال HTTP/2 مع كل من العميل والواجهة الخلفية. يمكنه تحليل التدفقات الفردية، وتطبيق التوازن على مستوى الطلبات، وإضافة الرؤوس، وتنفيذ إنهاء TLS. هذه هي الخيار الأكثر وظيفية — هكذا تعمل Envoy وNginx (بدءاً من الإصدار 1.13.10) وموازني الحمل الذين يدعمون gRPC في مزودي السحابة.
النهج 2: نفق TCP (CONNECT)
لا يقوم الوكيل بتحليل حركة HTTP/2، بل يقوم ببساطة بإنشاء نفق TCP شفاف عبر طريقة CONNECT. يقوم العميل بإنشاء اتصال TLS مباشرة مع الواجهة الخلفية عبر النفق. يرى الوكيل فقط تدفق بايت مشفر. هذه الطريقة أسهل في الإعداد، لكنها تحرمك من إمكانيات التوازن على مستوى طلبات gRPC وإضافة الرؤوس.
| الميزة | HTTP/2 من النهاية إلى النهاية | نفق TCP CONNECT |
|---|---|---|
| توازن الحمل حسب الطلبات | ✅ نعم | ❌ لا (فقط عبر TCP) |
| إنهاء TLS على الوكيل | ✅ نعم | ❌ لا |
| إضافة الرؤوس | ✅ نعم | ❌ لا |
| صعوبة الإعداد | متوسطة | منخفضة |
| دعم البث | ✅ كامل | ✅ كامل |
| الرصد (المقاييس) | ✅ مفصل | ❌ فقط TCP |
إعداد Nginx كوكيل gRPC
يدعم Nginx تمرير gRPC بدءاً من الإصدار 1.13.10 (فبراير 2018). يتطلب الأمر وحدة ngx_http_grpc_module، التي تأتي في التوزيعة القياسية. من المهم: يدعم Nginx HTTP/2 على جانب العميل (الواجهة الأمامية)، ولكنه يستخدم HTTP/2 فقط لـ gRPC على جانب الواجهة الخلفية — يعمل HTTP upstream العادي عبر HTTP/1.1.
التكوين الأساسي لوكيل gRPC على Nginx
server {
listen 443 ssl http2;
server_name grpc.example.com;
# شهادات TLS
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
# معلمات TLS الحديثة
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
# توجيه grpc_pass بدلاً من proxy_pass
grpc_pass grpc://grpc_backend;
# مهلات للتدفقات طويلة الأمد
grpc_read_timeout 3600s;
grpc_send_timeout 3600s;
grpc_connect_timeout 5s;
# تمرير عنوان IP الحقيقي للعميل
grpc_set_header X-Real-IP $remote_addr;
grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
upstream grpc_backend {
server backend-1:50051;
server backend-2:50051;
server backend-3:50051;
# Keepalive لاتصالات HTTP/2
keepalive 32;
}
لاحظ بعض التفاصيل الحرجة. أولاً، يتم استخدام توجيه grpc_pass، وليس proxy_pass — هذه وحدات مختلفة بسلوك مختلف. ثانياً، تم تعيين المهلات grpc_read_timeout وgrpc_send_timeout إلى 3600 ثانية (1 ساعة) — هذا مهم للتدفقات الخدمية التي قد تعمل لفترة طويلة دون نقل البيانات. ثالثاً، keepalive 32 في upstream يسمح بإعادة استخدام اتصالات HTTP/2 مع الواجهات الخلفية.
تكوين لـ gRPC غير المشفر (grpc://)
server {
listen 80 http2;
server_name grpc-internal.example.com;
location / {
grpc_pass grpc://127.0.0.1:50051;
# معالجة أخطاء gRPC
error_page 502 = /error502grpc;
}
location = /error502grpc {
internal;
default_type application/grpc;
add_header grpc-status 14;
add_header content-length 0;
return 204;
}
}
كتلة error502grpc — تفصيل مهم: عند عدم توفر الواجهة الخلفية، تعيد الحالة الصحيحة لـ gRPC UNAVAILABLE (14) بدلاً من HTTP 502، الذي لن يتمكن عميل gRPC من معالجته بشكل صحيح.
Envoy Proxy: الخيار الأفضل لـ gRPC في الميكروسيرفيسات
تم إنشاء Envoy بواسطة Lyft خصيصاً لبنية الميكروسيرفيس، ودعم gRPC فيه تم تنفيذه على أعمق مستوى. إنه يفهم Protocol Buffers، ويستطيع تحويل gRPC إلى REST، ويجمع مقاييس مفصلة لكل طريقة RPC، ويعد أساساً لحلول service mesh — Istio وAWS App Mesh وغيرها. إذا كنت تبني بنية ميكروسيرفيس جادة، فإن Envoy هو معيار الصناعة.
التكوين الأساسي لـ Envoy لـ gRPC
static_resources:
listeners:
- name: grpc_listener
address:
socket_address:
address: 0.0.0.0
port_value: 8080
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: grpc_proxy
codec_type: HTTP2
route_config:
name: grpc_routes
virtual_hosts:
- name: grpc_services
domains: ["*"]
routes:
- match:
prefix: "/com.example.UserService"
route:
cluster: user_service
timeout: 30s
retry_policy:
retry_on: "reset,connect-failure,retriable-status-codes"
num_retries: 3
retriable_status_codes: [14]
- match:
prefix: "/com.example.OrderService"
route:
cluster: order_service
timeout: 60s
http_filters:
- name: envoy.filters.http.grpc_stats
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.grpc_stats.v3.FilterConfig
emit_filter_state: true
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: user_service
connect_timeout: 5s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
http2_protocol_options: {}
load_assignment:
cluster_name: user_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: user-service
port_value: 50051
المزايا الرئيسية لهذا التكوين: التوجيه حسب خدمات gRPC (يجب أن يتطابق بادئة المسار مع الاسم الكامل للخدمة بتنسيق package.ServiceName)، وإعادة المحاولة التلقائية عند الحالة UNAVAILABLE وجمع مقاييس gRPC عبر فلتر grpc_stats.
تحويل gRPC-Web في Envoy
واحدة من الميزات القاتلة لـ Envoy هي المحول المدمج gRPC-Web. لا تدعم المتصفحات gRPC مباشرة (بسبب قيود Fetch API على تريلرز HTTP/2)، لذلك يتم استخدام بروتوكول gRPC-Web. يمكن لـ Envoy تحويل طلبات gRPC-Web من المتصفح تلقائياً إلى gRPC العادي للواجهة الخلفية:
http_filters:
- name: envoy.filters.http.grpc_web
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb
- name: envoy.filters.http.cors
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.CorsPolicy
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
HAProxy و gRPC: تكوين مع توازن الحمل
يدعم HAProxy gRPC بدءاً من الإصدار 1.9.2. يعمل على مستوى TCP أو HTTP/2، ويستطيع توازن حركة gRPC وإجراء فحوصات الصحة. HAProxy هو خيار جيد إذا كنت تستخدمه بالفعل في البنية التحتية الخاصة بك وتريد إضافة دعم gRPC دون إدخال مكون جديد.
global
maxconn 50000
log stdout format raw local0
defaults
log global
timeout connect 5s
timeout client 3600s
timeout server 3600s
frontend grpc_frontend
bind *:443 ssl crt /etc/haproxy/certs/server.pem alpn h2,http/1.1
mode http
option http-use-htx
default_backend grpc_servers
backend grpc_servers
mode http
balance leastconn
option http-use-htx
# فحص الصحة عبر بروتوكول فحص صحة gRPC
option httpchk GET /grpc.health.v1.Health/Check
http-check expect status 200
server grpc1 10.0.0.1:50051 check ssl verify none
server grpc2 10.0.0.2:50051 check ssl verify none
server grpc3 10.0.0.3:50051 check ssl verify none
لاحظ بعض الإعدادات المهمة. alpn h2,http/1.1 في توجيه bind يشير إلى أن HAProxy يقبل كل من اتصالات HTTP/2 وHTTP/1.1 عبر مفاوضة TLS ALPN. timeout client 3600s وtimeout server 3600s — معلمات حرجة لتدفقات gRPC طويلة الأمد. خوارزمية leastconn تفضل roundrobin لـ gRPC، حيث أن الاتصالات المتدفقة يمكن أن تكون طويلة الأمد وتؤثر بشكل غير متساوٍ على الواجهات الخلفية.
إنهاء TLS والتشفير الشامل لـ gRPC
يفترض gRPC بشكل افتراضي استخدام TLS — هذه جزء من المواصفات. في الممارسة العملية، في بنية الميكروسيرفيس، تبرز مسألة: أين يتم تنفيذ إنهاء TLS وكيف يتم تنظيم التشفير بين المكونات؟ هناك ثلاثة أنماط أساسية.
النمط 1: إنهاء TLS على الوكيل (Edge TLS)
يستقبل الوكيل حركة مشفرة من العملاء، يفك تشفيرها وينقلها إلى الواجهات الخلفية عبر قناة غير مشفرة (أو مع TLS منفصل). هذه هي الطريقة الأكثر شيوعاً في الشبكات المؤسسية. يمكن أن تستخدم الواجهات الخلفية grpc.Insecure() لتبسيط التكوين.
النمط 2: التشفير الشامل (mTLS)
TLS المتبادل (mTLS) هو معيار لـ service mesh. كل خدمة لديها شهادة خاصة بها، وعند كل اتصال، تتحقق كلا الجانبين من شهادات بعضهما البعض. هذا يوفر مصادقة الخدمات وتشفير الحركة داخل الكلاستر. هكذا يعمل Istio مع وكيل Envoy sidecar.
# Go: خادم gRPC مع mTLS
import (
"crypto/tls"
"crypto/x509"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)
func createMTLSCredentials() credentials.TransportCredentials {
cert, _ := tls.LoadX509KeyPair("server.crt", "server.key")
caCert, _ := os.ReadFile("ca.crt")
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{cert},
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: caCertPool,
}
return credentials.NewTLS(tlsConfig)
}
// إنشاء خادم مع mTLS
creds := createMTLSCredentials()
server := grpc.NewServer(grpc.Creds(creds))
النمط 3: TLS Passthrough
يعمل الوكيل على مستوى TCP ولا يفك تشفير الحركة — يقوم ببساطة بإعادة توجيه بايت مشفرة إلى الواجهة الخلفية. هذه هي أبسط خيار من وجهة نظر الوكيل، لكنها تحرم من إمكانية تحليل حركة gRPC، إضافة الرؤوس أو تنفيذ التوازن على مستوى الطلبات.
توازن الحمل لحركة gRPC: الخصائص والحلول
توازن الحمل لـ gRPC هو مهمة غير تافهة، وإليك السبب. في HTTP/1.1، كل طلب هو اتصال TCP منفصل (أو اتصال من مجموعة)، ويقوم موازن الحمل بسهولة بتوزيع الطلبات على الواجهات الخلفية. في HTTP/2، يقوم اتصال TCP واحد بتعدد تدفقات متعددة — إذا كان موازن الحمل يعمل على مستوى TCP، فإن جميع التدفقات من اتصال واحد ستذهب إلى واجهة خلفية واحدة.
بالنسبة لـ gRPC، يعني هذا: إذا قام العميل بإنشاء اتصال HTTP/2 واحد ويرسل من خلاله 100 طلب RPC، عند توازن الحمل TCP، ستتم معالجة جميع الطلبات الـ 100 بواسطة مثيل واحد من الواجهة الخلفية. ستبقى الواجهات الخلفية الأخرى غير مستخدمة. الحل هو التوازن على مستوى تدفقات HTTP/2 (توازن L7).
خوارزميات التوازن لـ gRPC
| الخوارزمية | تناسب gRPC | تعليق |
|---|---|---|
| Round Robin | ✅ نعم | جيد لـ RPC الأحادي مع أوقات معالجة متشابهة تقريباً |
| Least Connection | ✅ الخيار الأفضل | يأخذ في الاعتبار التدفقات النشطة، ويوزع الحمل بشكل متساوٍ |
| Random | ⚠️ مشروط | يعمل عند وجود عدد كبير من الطلبات، غير متساوٍ عند القليل منها |
| IP Hash | ❌ سيء | يربط العميل بواجهة خلفية واحدة، لا معنى له عند L7 |
| Pick First (مبني في gRPC) | ❌ ليس للإنتاج | تذهب جميع الطلبات إلى أول خادم متاح |
توازن الحمل من جانب العميل في gRPC
يدعم gRPC توازن الحمل من جانب العميل — يقرر العميل بنفسه إلى أي خادم يرسل الطلب. هذا يسمح بتجاوز مشكلة تعدد TCP. يتم استخدام DNS مع سجلات A متعددة أو محللات خاصة (Consul، etcd) لاكتشاف الخدمة. مثال على إعداد توازن الحمل من جانب العميل في Go:
import (
"google.golang.org/grpc"
"google.golang.org/grpc/balancer/roundrobin"
)
// عميل مع توازن الحمل round-robin عبر DNS
conn, err := grpc.Dial(
"dns:///grpc-service.internal:50051",
grpc.WithDefaultServiceConfig(
`{"loadBalancingConfig": [{"round_robin":{}}]}`
),
grpc.WithTransportCredentials(creds),
)
// عميل مع least-connection (متاح في gRPC >= 1.58)
conn, err := grpc.Dial(
"dns:///grpc-service.internal:50051",
grpc.WithDefaultServiceConfig(
`{"loadBalancingConfig": [{"least_request":{}}]}`
),
grpc.WithTransportCredentials(creds),
)
الوكلاء الخارجيون لـ gRPC: متى ولماذا هم مطلوبون في الميكروسيرفيسات
بالإضافة إلى مكونات الوكلاء الداخلية (Nginx، Envoy، HAProxy)، في بنية الميكروسيرفيس، قد تظهر الحاجة أحياناً لاستخدام خوادم الوكلاء الخارجية — على سبيل المثال، لتوجيه الحركة عبر مناطق معينة، أو لتجاوز قيود الشبكة، أو لعزل الاتصالات الصادرة. دعنا نستعرض السيناريوهات الرئيسية.
السيناريو 1: الميكروسيرفيسات الموزعة جغرافياً
إذا كانت ميكروسيرفيساتك تقع في مناطق مختلفة (على سبيل المثال، جزء في أوروبا، وجزء في الولايات المتحدة)، وتحتاج إلى التحكم في عنوان IP الذي يتم من خلاله إنشاء اتصالات gRPC بين المناطق، يمكن أن تساعدك الوكلاء الخارجية في تنظيم التوجيه المتوقع. تناسب مثل هذه المهام وكلاء مراكز البيانات — حيث توفر عناوين IP مستقرة وسرعة اتصال عالية، وهو أمر حاسم لـ gRPC مع حساسيته للتأخيرات.
السيناريو 2: عزل الحركة الصادرة
في بعض البيئات المؤسسية، يجب أن تمر كل الحركة الصادرة عبر وكيل مؤسسي. بالنسبة لعملاء gRPC الذين يحتاجون إلى الوصول إلى خدمات gRPC الخارجية (مثل Google Cloud APIs، التي تستخدم gRPC)، فإن هذا يخلق صعوبات. الحل هو إعداد نفق CONNECT عبر الوكيل المؤسسي.
مثال على إعداد عميل gRPC للعمل عبر وكيل HTTP CONNECT في Go:
import (
"net"
"net/http"
"golang.org/x/net/proxy"
"google.golang.org/grpc"
)
// استخدام وكيل SOCKS5 لـ gRPC
proxyDialer, _ := proxy.SOCKS5(
"tcp",
"proxy.example.com:1080",
&proxy.Auth{User: "user", Password: "pass"},
proxy.Direct,
)
conn, err := grpc.Dial(
"grpc-service.example.com:443",
grpc.WithContextDialer(func(ctx context.Context, addr string) (net.Conn, error) {
return proxyDialer.Dial("tcp", addr)
}),
grpc.WithTransportCredentials(creds),
)
السيناريو 3: الاختبار والتطوير
عند تطوير الميكروسيرفيسات، غالباً ما تحتاج إلى اختبار سلوك الخدمات من بيئات شبكية مختلفة — للتحقق من كيفية استجابة الخدمة عند وجود تأخير مرتفع، أو لاختبار المنطق المعتمد على الجغرافيا. لمثل هذه المهام، تعتبر الوكلاء السكنية مريحة، حيث تسمح بمحاكاة الطلبات من مناطق معينة باستخدام عناوين IP حقيقية لمستخدمي المنازل.
الأخطاء الشائعة عند إعداد gRPC عبر الوكيل وكيفية إصلاحها
دعنا نستعرض أكثر المشاكل شيوعاً التي يواجهها المطورون عند إعداد gRPC عبر الوكيل، وطرق محددة لحلها.
الخطأ 1: "transport: received the unexpected content-type"
الأعراض:
يتلقى العميل خطأ transport: received the unexpected content-type "text/html; charset=utf-8"
السبب: أعاد الوكيل صفحة HTML تحتوي على خطأ (على سبيل المثال، 502 Bad Gateway) بدلاً من استجابة gRPC. لا يعرف عميل gRPC كيفية معالجة HTML ويصدر هذا الخطأ.
الحل: تأكد من أن الواجهة الخلفية متاحة. أضف معالجة أخطاء gRPC على مستوى الوكيل (كما هو موضح في مثال Nginx أعلاه مع كتلة error502grpc).
الخطأ 2: يتم قطع الاتصال بعد 60-120 ثانية
الأعراض:
تتقطع اتصالات gRPC المتدفقة بشكل غير متوقع مع خطأ UNAVAILABLE: transport is closing بعد فترة زمنية متشابهة تقريباً.
السبب: يقوم الوكيل بإغلاق الاتصالات غير النشطة بناءً على المهلة. القيم التقليدية: AWS ELB — 60 ثانية، Nginx بشكل افتراضي — 60 ثانية.
الحل 1: زيادة المهلات على الوكيل (كما هو موضح في الأمثلة أعلاه).
الحل 2: إعداد keepalive على جانب عميل gRPC:
import "google.golang.org/grpc/keepalive"
kaParams := keepalive.ClientParameters{
Time: 30 * time.Second, // Ping كل 30 ثانية
Timeout: 10 * time.Second, // الانتظار للحصول على استجابة 10 ثوانٍ
PermitWithoutStream: true, // Ping حتى بدون RPC نشط
}
conn, err := grpc.Dial(
"grpc-service:50051",
grpc.WithKeepaliveParams(kaParams),
grpc.WithTransportCredentials(creds),
)
الخطأ 3: HTTP/2 لا يتوافق (فشل ALPN)
الأعراض:
خطأ transport: failed to dial: context deadline exceeded أو no application protocol
السبب: لا يدعم الوكيل أو الأجهزة الوسيطة ALPN (مفاوضة بروتوكول الطبقة التطبيقية) أو لم يتم تضمين h2 في قائمة البروتوكولات المدعومة.
الحل: تأكد من أن بروتوكول h2 محدد بوضوح في تكوين TLS للوكيل: alpn h2,http/1.1 (HAProxy) أو listen 443 ssl http2 (Nginx).
الخطأ 4: يتوقف البث — لا تصل البيانات
الأعراض:
يعمل البث من الخادم على الواجهة الخلفية (يظهر في السجلات)، لكن العميل لا يتلقى رسائل حتى ينتهي البث.
السبب: يقوم الوكيل بتخزين الاستجابة ويرسلها إلى العميل فقط بعد الانتهاء. هذه مشكلة نموذجية للوكلاء الذين تم إعدادهم مع proxy_buffering on.
الحل لـ Nginx:
location / {
grpc_pass grpc://backend;
# تعطيل التخزين للتدفقات gRPC
grpc_buffer_size 0;
# أو لـ proxy_pass العادي:
proxy_buffering off;
proxy_cache off;
}
قائمة التحقق لتشخيص gRPC عبر الوكيل
✅ قائمة التحقق: تشخيص gRPC-الوكيل
- يدعم الوكيل HTTP/2 (تحقق عبر
curl --http2 -v) - ALPN h2 مفعلة في تكوينات TLS للوكيل
- تم تعيين مهلات العميل والخادم على الأقل 300 ثانية
- تم تعطيل تخزين الاستجابات لنقاط نهاية gRPC
- تم إعداد keepalive لـ gRPC على العميل (الوقت: 30 ثانية، المهلة: 10 ثوانٍ)
- تُعاد أخطاء الواجهة الخلفية كحالات gRPC، وليس كودات HTTP
- فحص الصحة يستخدم بروتوكول فحص صحة gRPC
- يعمل التوازن على L7 (تدفقات HTTP/2)، وليس L4 (TCP)
الخاتمة
يتطلب إعداد gRPC عبر الوكيل فهم الفروق الرئيسية بين HTTP/2 وHTTP/1.1: تعدد التدفقات، الاتصالات طويلة الأمد، تريلرز HTTP/2 ومفاوضة ALPN. لا تعمل الوكلاء HTTP التقليدية بدون إعداد خاص مع gRPC — تحتاج إلى إما وكيل L7 يدعم HTTP/2 (Nginx 1.13.10+، Envoy، HAProxy 1.9.2+)، أو نفق TCP CONNECT.
يُوصى باستخدام Envoy في بيئة الإنتاج — حيث تم إنشاؤه خصيصاً لبنية الميكروسيرفيس، ويحتوي على دعم أصلي لـ gRPC، ويستطيع جمع مقاييس مفصلة لكل طريقة RPC، ويعد أساساً لمعظم حلول service mesh. يعد Nginx خياراً جيداً إذا كنت تستخدمه بالفعل كـ API Gateway وترغب في إضافة دعم gRPC دون إدخال مكون جديد. يناسب HAProxy إذا كانت الأداء حاسمة وتعرف بالفعل كيفية تكوينه.
بغض النظر عن الوكيل المختار، تبقى ثلاث قواعد ثابتة: زيادة المهلات للتدفقات طويلة الأمد، تعطيل تخزين الاستجابات، وإعداد keepalive على العميل. تحل هذه الإعدادات الثلاثة 80% من مشاكل gRPC عبر الوكيل.
إذا كانت خدمات gRPC في بنيتك يجب أن تتفاعل عبر الشبكات الخارجية أو كنت بحاجة إلى توجيه الحركة عبر مناطق معينة، انتبه إلى وكلاء مراكز البيانات — حيث توفر عناوين IP مستقرة، وتأخير منخفض، وعرض نطاق ترددي عالٍ، وهو أمر مهم بشكل خاص لـ gRPC مع بروتوكوله الثنائي وحساسيته للتأخير.
```