הפעלה באמצעות gRPC

בדף הזה מוצגים פרטים ספציפיים ל-Knative serving למפתחים שרוצים להשתמש ב-gRPC כדי לחבר שירות Knative serving לשירותים אחרים, למשל כדי לספק תקשורת פשוטה ובעלת ביצועים גבוהים בין מיקרו-שירותים פנימיים. ‫Knative Serving תומך בשיחות gRPC unary וstreaming.

gRPC Unary

בשיחת RPC אוניטרית, הלקוח שולח בקשה אחת לשרת ומקבל תגובה אחת, בדומה לבקשה להפעלת פונקציה רגילה:
rpc SayHello(HelloRequest) returns (HelloResponse);

סטרימינג ב-gRPC

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

rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);

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

rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);

‫RPCs של סטרימינג דו-כיווני שבהם הלקוח והשרת שולחים הודעות בשני סטרימינגים של קריאה וכתיבה שפועלים באופן עצמאי.

rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);

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

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

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

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

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

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

יצירת לקוח gRPC

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

האזנה לבקשות gRPC בשירות Knative serving

הדרישה המיוחדת היחידה לשרת gRPC שפועל ב-Knative serving היא להאזין ליציאה שצוינה על ידי משתנה הסביבה 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 של שירות Knative serving או הדומיין המותאם אישית שמופה לשירות הזה, יחד עם יציאה 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)
}