Kontentga o‘tish

Grpc ​

Kirish ​

Grpc moduli facades.Grpc() orqali boshqarilishi mumkin. Goravel gRPC xizmatlarini yaratish va ulardan foydalanishning nafis usulini taqdim etadi, ham server, ham mijoz tomonlarini qo'llab-quvvatlaydi.

Konfiguratsiya ​

config/grpc.go faylida Grpc modulini sozlashingiz mumkin, bu yerda grpc.host server domen nomini, grpc.servers esa mijoz ulanadigan serverlarni sozlaydi.

Kontrollerlar ​

Kontrollerlar app/grpc/controllers katalogida aniqlanishi mumkin.

go
// app/grpc/controllers/user_controller.go
package controllers

import (
  "context"
  "net/http"

  proto "github.com/goravel/example-proto"
)

type UserController struct {}

func NewUserController() *UserController {
  return &UserController{}
}

func (r *UserController) GetUser(ctx context.Context, req *proto.UserRequest) (*proto.UserResponse, error) {
  return &proto.UserResponse{
    Code: http.StatusOK,
    Data: &proto.User{
      Id:    1,
      Name:  "Goravel",
      Token: req.GetToken(),
    },
  }, nil
}

Marshrutlashni aniqlash ​

Barcha marshrutlash fayllari routes katalogida, masalan routes/grpc.go kabi aniqlanishi mumkin.

go
// routes/grpc.go
package routes

import (
  proto "github.com/goravel/example-proto"

  "goravel/app/facades"
  "goravel/app/grpc/controllers"
)

func Grpc() {
  proto.RegisterUserServiceServer(facades.Grpc().Server(), controllers.NewUserController())
}

Marshrutlashni ro'yxatdan o'tkazish ​

Marshrutlash aniqlangandan so'ng, uni bootstrap/app.go::WithRouting funksiyasida ro'yxatdan o'tkazing.

go
func Boot() contractsfoundation.Application {
	return foundation.Setup().
		WithRouting(func() {
      routes.Grpc()
    }).
		WithConfig(config.Boot).
		Create()
}

Interceptor ​

Interceptorlar gRPC so'rovlari va javoblarini to'xtatish va o'zgartirish imkoniyatini beradi. Ular jurnalga yozish, autentifikatsiya, metrikalar va boshqalar uchun ishlatilishi mumkin.

Interceptorlarni aniqlash ​

Interceptorlar app/grpc/interceptors papkasida aniqlanishi mumkin.

Server Interceptor misoli:

go
// app/grpc/interceptors/test_server.go
package interceptors

import (
  "context"

  "google.golang.org/grpc"
)

func TestServer(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {
  // So'rov boshqarilishidan oldin mantiqingizni qo'shing
  // Masalan: jurnalga yozish, autentifikatsiya va hokazo.
  
  return handler(ctx, req)
}

Mijoz Interceptor misoli:

go
// app/grpc/interceptors/test_client.go
package interceptors

import (
  "context"

  "google.golang.org/grpc"
)

func TestClient(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
  // So'rov yuborilishidan oldin mantiqingizni qo'shing
  // Masalan: jurnalga yozish, metadata qo'shish va hokazo.
  
  return invoker(ctx, method, req, reply, cc, opts...)
}

Interceptorlarni ro'yxatdan o'tkazish ​

Interceptorlarni bootstrap/app.go faylida WithGrpcServerInterceptors, WithGrpcClientInterceptors, WithGrpcServerStatsHandlers va WithGrpcClientStatsHandlers funksiyalari yordamida ro'yxatdan o'tkazing.

go
import (
  "github.com/goravel/framework/contracts/foundation"
  "google.golang.org/grpc"
  "google.golang.org/grpc/stats"
  
  "goravel/app/grpc/interceptors"
)

func Boot() foundation.Application {
  return foundation.Setup().
    WithGrpcServerInterceptors(func() []grpc.UnaryServerInterceptor {
      return []grpc.UnaryServerInterceptor{
        interceptors.TestServer,
      }
    }).
    WithGrpcClientInterceptors(func() map[string][]grpc.UnaryClientInterceptor {
      return map[string][]grpc.UnaryClientInterceptor{
        "default": {
          interceptors.TestClient,
        },
      }
    }).
    WithGrpcServerStatsHandlers(func() []stats.Handler {
      return []stats.Handler{}
    }).
    WithGrpcClientStatsHandlers(func() map[string][]stats.Handler {
      return map[string][]stats.Handler{}
    }).
    Create()
}

Interceptorlarni Serverlarga qo'llash ​

Yuqoridagi misoldagi default - bu grpc.servers.interceptors konfiguratsiya bandiga qo'llanilishi mumkin bo'lgan guruh nomi. Shu tarzda, mijoz guruh ostidagi barcha interceptorlarga qo'llaniladi.

go
package config

import (
  "goravel/app/facades"
)

func init() {
  config := facades.Config()
  config.Add("grpc", map[string]any{
    "host": config.Env("GRPC_HOST", ""),
    "port": config.Env("GRPC_PORT", ""),
    
    "servers": map[string]any{
      "user": map[string]any{
        "host":           config.Env("GRPC_USER_HOST", ""),
        "port":           config.Env("GRPC_USER_PORT", ""),
        "interceptors":   []string{"default"},
        "stats_handlers": []string{},
      },
    },
  })
}

Stats Handlers ​

Stats handlerlar RPC chaqiruvlarini monitoring qilish va metrikalarni yig'ish uchun gRPC mexanizmidir. Ular ham mijoz, ham server RPC'larining hayot tsikliga kirish imkoniyatini beradi, bu ularni quyidagilar uchun ideal qiladi:

  • So'rov/javob monitoringi
  • Ishlash metrikalarini yig'ish
  • Maxsus kuzatish integratsiyalari
  • Jurnalga yozish va tuzatish

Stats Handlerlarni ro'yxatdan o'tkazish ​

Stats handlerlar bootstrap/app.go faylida WithGrpcServerStatsHandlers va WithGrpcClientStatsHandlers funksiyalari yordamida ro'yxatdan o'tkazilishi mumkin.

Server Stats Handler misoli:

go
// app/grpc/stats/server_handler.go
package stats

import (
  "context"
  
  "google.golang.org/grpc/stats"
)

type ServerStatsHandler struct{}

func NewServerStatsHandler() stats.Handler {
  return &ServerStatsHandler{}
}

func (h *ServerStatsHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context {
  // Har bir RPC boshida chaqiriladi
  return ctx
}

func (h *ServerStatsHandler) HandleRPC(ctx context.Context, s stats.RPCStats) {
  // Har bir RPC hodisasi uchun chaqiriladi
}

func (h *ServerStatsHandler) TagConn(ctx context.Context, info *stats.ConnTagInfo) context.Context {
  // Ulanish o'rnatilganda chaqiriladi
  return ctx
}

func (h *ServerStatsHandler) HandleConn(ctx context.Context, s stats.ConnStats) {
  // Ulanish hodisalari uchun chaqiriladi
}

Mijoz Stats Handler misoli:

go
// app/grpc/stats/client_handler.go
package stats

import (
  "context"
  
  "google.golang.org/grpc/stats"
)

type ClientStatsHandler struct{}

func NewClientStatsHandler() stats.Handler {
  return &ClientStatsHandler{}
}

func (h *ClientStatsHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context {
  return ctx
}

func (h *ClientStatsHandler) HandleRPC(ctx context.Context, s stats.RPCStats) {
  // Begin, End, InPayload, OutPayload kabi RPC hodisalarini boshqaring
}

func (h *ClientStatsHandler) TagConn(ctx context.Context, info *stats.ConnTagInfo) context.Context {
  return ctx
}

func (h *ClientStatsHandler) HandleConn(ctx context.Context, s stats.ConnStats) {
  // Ulanish hodisalarini boshqaring
}

Bootstrap'da ro'yxatdan o'tkazish ​

Stats handlerlaringizni bootstrap/app.go faylida ro'yxatdan o'tkazing:

go
import (
  "google.golang.org/grpc/stats"
  
  grpcstats "goravel/app/grpc/stats"
)

func Boot() foundation.Application {
  return foundation.Setup().
    WithGrpcServerStatsHandlers(func() []stats.Handler {
      return []stats.Handler{
        grpcstats.NewServerStatsHandler(),
      }
    }).
    WithGrpcClientStatsHandlers(func() map[string][]stats.Handler {
      return map[string][]stats.Handler{
        "user": {
          grpcstats.NewClientStatsHandler(),
        },
      }
    }).
    Create()
}

Stats Handlerlarni Mijozlarga qo'llash ​

Guruh nomi (masalan, "user") config/grpc.go faylida mijozning stats_handlers massivida ko'rsatilishi kerak:

go
package config

import (
  "goravel/app/facades"
)

func init() {
  config := facades.Config()
  config.Add("grpc", map[string]any{
    "host": config.Env("GRPC_HOST", ""),
    "port": config.Env("GRPC_PORT", ""),
    
    "servers": map[string]any{
      "user": map[string]any{
        "host":           config.Env("GRPC_USER_HOST", ""),
        "port":           config.Env("GRPC_USER_PORT", ""),
        "interceptors":   []string{"default"},
        "stats_handlers": []string{"user"}, // "user" stats handler guruhini qo'llash
      },
    },
  })
}

gRPC Mijozi ​

Goravel gRPC xizmatlaridan foydalanish uchun gRPC mijozlarini yaratishning oson usulini taqdim etadi.

gRPC Serveriga ulanish ​

Siz facades.Grpc().Connect() usuli yordamida gRPC serveriga ulanishingiz mumkin. Ulanish nomi config/grpc.go faylida aniqlangan kalitga mos kelishi kerak.

go
// app/http/controllers/grpc_controller.go
package controllers

import (
  "fmt"

  proto "github.com/goravel/example-proto"
  "github.com/goravel/framework/contracts/http"

  "goravel/app/facades"
)

type GrpcController struct {
  userService proto.UserServiceClient
}

func NewGrpcController() *GrpcController {
  // Initsializatsiya jarayoni app/services/*.go fayliga ko‘chirilishi mumkin
  client, err := facades.Grpc().Connect("user")
  if err != nil {
    facades.Log().Error(fmt.Sprintf("foydalanuvchi serveriga ulanish muvaffaqiyatsiz: %+v", err))
  }

  return &GrpcController{
    userService: proto.NewUserServiceClient(client),
  }
}

func (r *GrpcController) User(ctx http.Context) http.Response {
  resp, err := r.userService.GetUser(ctx, &proto.UserRequest{
    Token: ctx.Request().Input("token"),
  })
  if err != nil {
    return ctx.Response().String(http.StatusInternalServerError, fmt.Sprintf("UserService.GetUser chaqiruvi xatosi: %+v", err))
  }
  if resp.Code != http.StatusOK {
    return ctx.Response().String(http.StatusInternalServerError, fmt.Sprintf("foydalanuvchi xizmati xatoni qaytardi, kod: %d, xabar: %s", resp.Code, resp.Message))
  }

  return ctx.Response().Success().Json(resp.GetData())
}

MIT litsenziyasi ostida chiqarilgan