שימוש ב-gRPC

בדף הזה מופיעים פרטים ספציפיים ל-Cloud Run שמיועדים למפתחים שרוצים להשתמש ב-gRPC כדי לחבר שירות Cloud Run לשירותים אחרים, למשל כדי לספק תקשורת פשוטה ומהירה בין מיקרו-שירותים פנימיים. אתם יכולים להשתמש ב-Cloud Run עם כל סוגי ה-gRPC, סטרימינג או unary.

תרחישי שימוש אפשריים:

  • תקשורת בין מיקרו-שירותים פנימיים.
  • עומסי נתונים גבוהים (פרוטוקול gRPC משתמש במאגרי פרוטוקולים, שהם עד פי שבעה יותר מהירים מקריאות REST).
  • צריך רק הגדרת שירות פשוטה, לא צריך לכתוב ספריית לקוח מלאה.
  • אפשר להשתמש ב-gRPCs להזרמה בשרת gRPC כדי לבנות אפליקציות וממשקי API עם תגובה מהירה יותר.

כדי לשלב את השירות עם gRPC:

  • אם אתם משתמשים ב-gRPC Streaming, אתם צריכים להגדיר את השירות כך שישתמש ב-HTTP/2. ‫HTTP/2 היא שיטת התעבורה לסטרימינג של gRPC.
  • מגדירים את הודעות הבקשה והתשובות בקובץ proto ומקמפלים אותן.
  • יוצרים שרת gRPC לטיפול בבקשות ולהחזרת תשובות: השרת צריך להאזין למשתנה הסביבה PORT.
  • יוצרים לקוח ששולח בקשות ומטפל בתגובות משרת gRPC.
  • אפשר גם להוסיף אימות.
  • מפתחים ופורסים את השירות.

הגדרת השירות לשימוש ב-HTTP/2

אם אתם משתמשים ב-gRPC עם Cloud Run, מומלץ להגדיר את השירות כך שישתמש ב-HTTP/2. למרות שחלק מהתכונות הפשוטות של gRPC פועלות בלי להשתמש ב-HTTP/2, הרבה תכונות של gRPC, כמו סטרימינג ומטא-נתונים, דורשות HTTP/2.

הגדרה והידור של הודעות בקובץ proto

אין הגדרות נוספות או הגדרות ספציפיות ל-Cloud Run שצריך להוסיף להגדרות הפרוטו. בדיוק כמו בכל שימוש אחר ב-gRPC, משתמשים בgRPC protocol buffers להגדרות של שירותים ולסריאליזציה של נתונים.

יצירת לקוח gRPC

אין צורך להוסיף דברים מיוחדים או ספציפיים ל-Cloud Run ללקוח שמשתמש ב-gRPC: צריך לפעול לפי ההוראות במסמכי gRPC בנושא שימוש בהגדרות שירות בקוד לקוח, ולעיין בלקוחות לדוגמה שמופיעים במדריכי gRPC הספציפיים לשפה.

התאמה אוטומטית לעומס ואיזון עומסים

‫Cloud Run משתמש במאזני עומסים שמנוהלים על ידי Google, ששומרים על חיבורים נפרדים בין לקוחות לבין מכונות Cloud Run. ב-gRPC, התאמה אוטומטית לעומס מתנהגת באופן הבא:

  • חיבורי gRPC מלקוחות מסתיימים במאזן העומסים של קצה הרשת. שינוי ההגדרות של KeepAlive משפיע רק על החיבור למאזן העומסים, ולא על המופעים של Cloud Run. הלקוח לא מזהה מקרים שבהם מופסקת פעולה של מופע.
  • במהלך הקטנת הקיבולת, מאזן העומסים סוגר את החיבורים על ידי שליחת הודעות GOAWAY למופעי ה-Backend כשהם מושבתים.
  • במהלך הרחבת הקיבולת, מאזן העומסים יוצר חיבורים חדשים למופעי ה-Backend. כל הפעולות האלה שקופות ללקוחות.
  • במהלך התאמה אוטומטית לעומס, הרבה מופעים יכולים להתחיל ולבצע multiplexing לחיבור יחיד בין הלקוח לבין מאזן העומסים של ה-proxy.
  • המספר המרבי של בקשות בו-זמנית נקבע לפי המספר המקסימלי של בקשות בו-זמנית לכל מופע של הודעות. בסטרימינג, כל סטרימינג נספר פעם אחת מתוך מספר הבקשות המקסימלי בו-זמנית.

האזנה לבקשות gRPC בשירות Cloud Run

הדרישה המיוחדת היחידה לשרת gRPC שפועל ב-Cloud Run היא להאזין ליציאה שצוינה במשתנה הסביבה PORT, כפי שמוצג בקוד הבא:

Go

func main() {
	log.Printf("grpc-ping: starting server...")

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
		log.Printf("Defaulting to port %s", port)
	}

	listener, err := net.Listen("tcp", ":"+port)
	if err != nil {
		log.Fatalf("net.Listen: %v", err)
	}

	grpcServer := grpc.NewServer()
	pb.RegisterPingServiceServer(grpcServer, &pingService{})
	if err = grpcServer.Serve(listener); err != nil {
		log.Fatal(err)
	}
}

פתיחת חיבור gRPC לשירות

כדי לפתוח חיבור gRPC לשירות כדי לשלוח הודעות gRPC, צריך לציין את דומיין המארח, שהוא כתובת ה-URL של שירות Cloud Run או הדומיין המותאם אישית שמופה לשירות הזה, יחד עם יציאה 443, שהיא היציאה ש-gRPC אמור להשתמש בה.

Go


import (
	"crypto/tls"
	"crypto/x509"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
)

// NewConn creates a new gRPC connection.
// host should be of the form domain:port, e.g., example.com:443
func NewConn(host string, insecure bool) (*grpc.ClientConn, error) {
	var opts []grpc.DialOption
	if host != "" {
		opts = append(opts, grpc.WithAuthority(host))
	}

	if insecure {
		opts = append(opts, grpc.WithInsecure())
	} else {
		// Note: On the Windows platform, use of x509.SystemCertPool() requires
		// Go version 1.18 or higher.
		systemRoots, err := x509.SystemCertPool()
		if err != nil {
			return nil, err
		}
		cred := credentials.NewTLS(&tls.Config{
			RootCAs: systemRoots,
		})
		opts = append(opts, grpc.WithTransportCredentials(cred))
	}

	return grpc.Dial(host, opts...)
}

שליחת בקשות gRPC ללא אימות

בדוגמה הבאה אפשר לראות איך שולחים בקשה ללא אימות, באמצעות חיבור gRPC שהוגדר כמו שצוין קודם.

Go


import (
	"context"
	"time"

	pb "github.com/GoogleCloudPlatform/golang-samples/run/grpc-ping/pkg/api/v1"
	"google.golang.org/grpc"
)

// pingRequest sends a new gRPC ping request to the server configured in the connection.
func pingRequest(conn *grpc.ClientConn, p *pb.Request) (*pb.Response, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	client := pb.NewPingServiceClient(conn)
	return client.Send(ctx, p)
}

שליחת בקשות gRPC עם אימות

בדוגמה הבאה אפשר לראות איך משתמשים באימות בין שירותים, אם לשירות הקורא יש הרשאת הפעלה לשירות המקבל. שימו לב שהקוד הזה יוצר כותרת הרשאה עם אסימון הזהות המתאים: זה נדרש. ההרשאות הנדרשות וכותרת ההרשאה מתוארות בפירוט במאמר בנושא אימות משירות לשירות.

Go


import (
	"context"
	"fmt"
	"time"

	"google.golang.org/api/idtoken"
	"google.golang.org/grpc"
	grpcMetadata "google.golang.org/grpc/metadata"

	pb "github.com/GoogleCloudPlatform/golang-samples/run/grpc-ping/pkg/api/v1"
)

// pingRequestWithAuth mints a new Identity Token for each request.
// This token has a 1 hour expiry and should be reused.
// audience must be the auto-assigned URL of a Cloud Run service or HTTP Cloud Function without port number.
func pingRequestWithAuth(conn *grpc.ClientConn, p *pb.Request, audience string) (*pb.Response, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	// Create an identity token.
	// With a global TokenSource tokens would be reused and auto-refreshed at need.
	// A given TokenSource is specific to the audience.
	tokenSource, err := idtoken.NewTokenSource(ctx, audience)
	if err != nil {
		return nil, fmt.Errorf("idtoken.NewTokenSource: %w", err)
	}
	token, err := tokenSource.Token()
	if err != nil {
		return nil, fmt.Errorf("TokenSource.Token: %w", err)
	}

	// Add token to gRPC Request.
	ctx = grpcMetadata.AppendToOutgoingContext(ctx, "authorization", "Bearer "+token.AccessToken)

	// Send the request.
	client := pb.NewPingServiceClient(conn)
	return client.Send(ctx, p)
}

קוד לדוגמה לסטרימינג של gRPC

לקבלת קוד לדוגמה, אפשר לעיין בהטמעה בRouteGuideמדריך היסודות של gRPC בשפה הרצויה. לדוגמה, כשמשתמשים ב-Go, כדאי לעיין במאמר Implementing RouteGuide.