Journey to providing APIs based on gRPC #141
Replies: 17 comments 18 replies
-
[gRPC-gateway vs. gRPC-web]
[Which one?] I think the gRPC-gateway is proper for providing APIs on the cb-network system. I expect that it's necessary to redesign the AdminWeb. References: |
Beta Was this translation helpful? Give feedback.
-
(Draft) cb-network system structure[To-Be] [As-Is] |
Beta Was this translation helpful? Give feedback.
-
gRPC 적용을 위한 Repository 구성 사례IDL(Interface Definition Language)을 별도 Repository에서 관리 사례사례 1
[원문]
사례 2[핵심한줄] [원문]
|
Beta Was this translation helpful? Give feedback.
-
Terms and abbreviationsInterface Description Language or Interface Definition Language (IDL) - wikipedia
Protocol Buffers (Protobuf) - wikipedia
|
Beta Was this translation helpful? Give feedback.
-
A service (i.e., an API specification based on gRPC) would be defined by Protocol Buffer (proto3). It will be described/specified in a proto file with ".proto" extension. |
Beta Was this translation helpful? Give feedback.
-
Protobuf Style Guide
|
Beta Was this translation helpful? Give feedback.
-
Worry about naming in gRPCWhile I was developing a code base for gRPC, I was confused about designing and naming services, rpcs, and messages. There were 2 reasons as follows:
Thus, I'd like to make a note. I wish it will be helpful for you to expect how the generated stub is used in the main source code. 😄 NOTE
A protobuf example from CB-Larva
|
Beta Was this translation helpful? Give feedback.
-
My personal view of gRPC and RESTful APIsI think the two are slightly different. I'd like to summarize it below. gRPC
RESTful API
|
Beta Was this translation helpful? Give feedback.
-
Issues of compiling protobuf and sort of solution for itIssues:
비고: protobuf를 buf로 compile하는 경우 - yaml 설정을 통해 googleapis를 알아서 포함하도록 할 수 있음 Method 1: the separated filesRequired Go packages
Stub generation
Generated files:
Stub and reverse proxy generation
Generated files:
Method 2: the integrated files
Required Go packages비고: 위에서 패키지를 설치한 후 진행하여 요구되는 패키지가 다를 수 있음
Stub generation
Generated files:
Stub and reverse proxy generation
Generated files:
References:
|
Beta Was this translation helpful? Give feedback.
-
Introduction to Buf repositoryWhen I saw |
Beta Was this translation helpful? Give feedback.
-
[Issue]
[Cause]
An example struct generated by // A specification of Cloud Adpative Network
type CLADNetSpecification struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
// AWS - Create Virtual Private Cloud (VPC): IPv4 CIDR block
// MS Azure - Create Virtual Network (vNet): IPv4 address space
// GCP - Create VPC Network: IPv4 address range
// Alibaba Cloud - Create VPC: IPv4 CIDR Block
Ipv4AddressSpace string `protobuf:"bytes,3,opt,name=ipv4_address_space,json=ipv4AddressSpace,proto3" json:"ipv4_address_space,omitempty"`
Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"`
} I have tried So I need to define additional struct as follows: // A specification of Cloud Adpative Network
type CLADNetSpecification struct {
Id string `json:"id"`
Name string `json:"name"`
// AWS - Create Virtual Private Cloud (VPC): IPv4 CIDR block
// MS Azure - Create Virtual Network (vNet): IPv4 address space
// GCP - Create VPC Network: IPv4 address range
// Alibaba Cloud - Create VPC: IPv4 CIDR Block
Ipv4AddressSpace string `json:"ipv4_address_space"`
Description string `json:"description"`
} |
Beta Was this translation helpful? Give feedback.
-
Serving gRPC and REST endpoints on one port (not two ports) 👍 🎉 [Tunning - one port] Link // If "Content-Type: application/grpc", use gRPC server handler,
// Otherwise, use gRPC Gateway handler (for REST API)
func allHandler(grpcServer *grpc.Server, httpHandler http.Handler) http.Handler {
return h2c.NewHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.ProtoMajor == 2 && strings.Contains(r.Header.Get("Content-Type"), "application/grpc") {
grpcServer.ServeHTTP(w, r)
} else {
httpHandler.ServeHTTP(w, r)
}
}), &http2.Server{})
}
func main() {
// gRPC section
// Create a gRPC server object
grpcServer := grpc.NewServer()
// Attach the CloudAdaptiveNetwork service to the server
pb.RegisterCloudAdaptiveNetworkServer(grpcServer, &server{})
// gRPC Gateway section
// Create a gRPC Gateway mux object
gwmux := runtime.NewServeMux()
// Register CloudAdaptiveNetwork handler to gwmux
addr := fmt.Sprintf(":%s", config.GRPC.ServerPort)
err = pb.RegisterCloudAdaptiveNetworkHandlerFromEndpoint(context.Background(), gwmux, addr, []grpc.DialOption{grpc.WithInsecure()})
if err != nil {
CBLogger.Fatalf("Failed to register gateway: %v", err)
}
// Serve gRPC server and gRPC Gateway by "allHandler"
err = http.ListenAndServe(addr, allHandler(grpcServer, gwmux))
if err != nil {
CBLogger.Fatalf("Failed to listen and serve: %v", err)
}
} [Tutorial in official website - two ports] Link func main() {
// gRPC section
serverPort := fmt.Sprintf(":%s", config.GRPC.ServerPort)
listener, errListen := net.Listen("tcp", serverPort)
if errListen != nil {
log.Fatalf("Failed to listen: %v", errListen)
}
// Create a gRPC server object
grpcServer := grpc.NewServer()
// Attach the CloudAdaptiveNetwork service to the server
pb.RegisterCloudAdaptiveNetworkServer(grpcServer, &server{})
// Serve gRPC server
CBLogger.Infof("Serving gRPC on 0.0.0.0%v", serverPort)
go func() {
if errGRPCServer := grpcServer.Serve(listener); errGRPCServer != nil {
CBLogger.Fatalf("Failed to serve: %v", errGRPCServer)
}
}()
// gRPC Gateway section
// Create a client connection to the gRPC server we just started
// This is where the gRPC-Gateway proxies the requests
serverEndpoint := fmt.Sprintf("0.0.0.0:%s", config.GRPC.ServerPort)
conn, err := grpc.DialContext(
context.Background(),
serverEndpoint,
grpc.WithBlock(),
grpc.WithInsecure(),
)
if err != nil {
CBLogger.Fatalf("Failed to dial server: %v", err)
}
gwmux := runtime.NewServeMux()
// Register CloudAdaptiveNetwork
err = pb.RegisterCloudAdaptiveNetworkHandler(context.Background(), gwmux, conn)
if err != nil {
CBLogger.Fatalf("Failed to register gateway: %v", err)
}
gatewayPort := fmt.Sprintf(":%s", config.GRPC.GatewayPort)
gwServer := &http.Server{
Addr: gatewayPort,
Handler: gwmux,
}
gatewayEndpoint := fmt.Sprintf("0.0.0.0:%s", config.GRPC.GatewayPort)
CBLogger.Infof("Serving gRPC-Gateway on http://%v", gatewayEndpoint)
if errGWServer := gwServer.ListenAndServe(); errGWServer != nil {
CBLogger.Fatalf("Failed to serve: %v", errGWServer)
}
} |
Beta Was this translation helpful? Give feedback.
-
MemoIt was hard for me to use
Example[rpc definition] import "google/protobuf/wrappers.proto";
import "google/protobuf/empty.proto"; // Return Say Hello
rpc sayHello(google.protobuf.Empty) returns (google.protobuf.StringValue){
option (google.api.http) = {
get: "/"
};
} [gRPC server source code] import(
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
"google.golang.org/protobuf/types/known/wrapperspb"
) func (s *server) SayHello(ctx context.Context, in *emptypb.Empty) (*wrapperspb.StringValue, error) {
return &wrapperspb.StringValue{Value: "Hi, welcome to CB-Larva"}, status.New(codes.OK, "").Err()
} |
Beta Was this translation helpful? Give feedback.
-
Generating API document from protosI'd like to generate an API document from protos. RPC enables API-first development. APIs are designed strictly on protos. Thus, I think it's very meaningful to generate an API document from protos. Reference: https://github.com/pseudomuto/protoc-gen-doc (MIT License) [Installation]go get -u github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc [API document generation command] on CB-Larva repoprotoc -I ./proto \
--doc_out=./gen/doc --doc_opt=markdown,cloud-adaptive-network-service.md \
./proto/cbnetwork/cloud_adaptive_network.proto |
Beta Was this translation helpful? Give feedback.
-
Which Go packages are included in the following 2 cases?Case 1: copy and paste proto buffers to a projectResult: gRPC packages are added. Scenario
Note - proto buffers in CB-Larva
1. Copy and paste the proto buffers to
|
Beta Was this translation helpful? Give feedback.
-
An issue to integrate the Cloud Adaptive Network with CB-TumblebugIt seems to be related to different gRPC versions. Error message on building CB-TumblgbugBuild CB-Tumblebuggo build -mod=mod -o cb-tumblebug # github.com/cloud-barista/cb-larva/poc-cb-net/pkg/api/gen/go/cbnetwork
/home/ubuntu/go/pkg/mod/github.com/cloud-barista/[email protected]/poc-cb-net/pkg/api/gen/go/cbnetwork/cloud_adaptive_network_grpc.pb.go:17:11: undefined: grpc.SupportPackageIsVersion7
/home/ubuntu/go/pkg/mod/github.com/cloud-barista/[email protected]/poc-cb-net/pkg/api/gen/go/cbnetwork/cloud_adaptive_network_grpc.pb.go:54:5: undefined: grpc.ClientConnInterface
/home/ubuntu/go/pkg/mod/github.com/cloud-barista/[email protected]/poc-cb-net/pkg/api/gen/go/cbnetwork/cloud_adaptive_network_grpc.pb.go:57:46: undefined: grpc.ClientConnInterface
/home/ubuntu/go/pkg/mod/github.com/cloud-barista/[email protected]/poc-cb-net/pkg/api/gen/go/cbnetwork/cloud_adaptive_network_grpc.pb.go:194:50: undefined: grpc.ServiceRegistrar Check gRPC versionsCB-Larva
|
Beta Was this translation helpful? Give feedback.
-
I have a plan to provide APIs for Cloud Adaptive Network (CLADNet), such as
createCLADNet
,readCLADNet
,updateCLADNet
,deleteCLADNet
.I expect that it is possible to provide APIs for both users (i.e., RESTful APIs) and systems (APIs for Go, Java, and so on) based on gRPC. I also consider integrating Swagger.
I'm studying for this.
I'd like to share progress, thoughts, information, and etc., and discuss those with you.
Beta Was this translation helpful? Give feedback.
All reactions