Criação de microsserviços de alto desempenho com gRPC, Ballerina e Go

Olá, Habr. Convidamos futuros alunos do curso "Arquiteto de Software" a participarem do webinar aberto sobre o tema "Idempotência e comutabilidade de API em filas e HTTP" .



Também compartilhamos a tradução de material útil.














Dentro da estrutura de uma arquitetura de microsserviço moderna, podemos dividir microsserviços em dois grupos principais, dependendo de seu relacionamento e interação. O primeiro grupo representa microsserviços externos que são diretamente acessíveis aos usuários. São principalmente APIs baseadas em HTTP que usam mensagens de texto simples (JSON, XML, etc.), otimizadas para uso por desenvolvedores terceirizados, usando Representative State Transfer (REST) ​​como tecnologia de comunicação. 





REST . OpenAPI , , REST API. API API, , , -. REST API HTTP GraphQL, .





— , . . , . REST API HTTP, . , , gRPC, .





gRPC?

gRPC — API (Remote procedure call — RPC) . RPC, , . , Thrift Avro, gRPC (interface description language — IDL). gRPC HTTP/2 — , gRPC REST HTTP/1.1. 





gRPC Protocol Buffers, , . , , () Protocol Buffers, .





gRPC

Figura 1. Segmento de arquitetura de microsserviços de uma loja de varejo online
1. -

, , . 1 - , Ballerina Golang, , -. gRPC , , . 









syntax="proto3";
 
package retail_shop;
 
service OrderService {
   rpc UpdateOrder(Item) returns (Order);
}  
message Item {
   string itemNumber = 1;
   int32 quantity = 2;
}
message Order {
   string itemNumber = 1;
   int32 totalQuantity = 2;
   float subTotal = 3;
      
      



1. Order (order.proto)





Order . gRPC Ballerina gRPC / . 





$ ballerina grpc --mode service --input proto/order.proto --output gen_code
      
      







import ballerina/grpc;
listener grpc:Listener ep = new (9090);
 
service OrderService on ep {
   resource function UpdateOrder(grpc:Caller caller, Item value) {
       // Implementation goes here.
 
       // You should return an Order
   }
}
public type Order record {|
   string itemNumber = "";
   int totalQuantity = 0;
   float subTotal = 0.0;
  
|};
public type Item record {|
   string itemNumber = "";
   int quantity = 0;
  
|}; 
      
      



2. (OrderServicesampleservice.bal).





gRPC ​​ service



Ballerina, gRPC rpc ​​ resource function



Ballerina, gRPC — record







Order Ballerina OrderService gRPC





OrderService Cart. Ballerina.





$ ballerina grpc --mode client --input proto/order.proto --output gen_code
      
      



, . , gRPC gRPC.





public remote function UpdateOrder(Item req, grpc:Headers? headers = ()) returns ([Order, grpc:Headers]|grpc:Error) {
      
       var payload = check self.grpcClient->blockingExecute("retail_shop.OrderService/UpdateOrder", req, headers);
       grpc:Headers resHeaders = new;
       anydata result = ();
       [result, resHeaders] = payload;
       return [<Order>result, resHeaders];
   }
};
      
      



3.





Ballerina gRPC, , UpdateOrder



.





Checkout , , Cart. stream Order



.





syntax="proto3";
package retail_shop;
 
service CheckoutService {
   rpc Checkout(stream Order) returns (FinalBill) {}
}
message Order {
   string itemNumber = 1;
   int32 totalQuantity = 2;
   float subTotal = 3;
}
message FinalBill {
   float total = 1;
}
      
      



4. Checkout (checkout.proto)





checkout.proto



, ballerina grpc



.





$ ballerina grpc --mode service --input proto/checkout.proto --output gencode





gRPC

Cart () , , , . :





service CheckoutService on ep {
   resource function Checkout(grpc:Caller caller, stream<Order,error> clientStream) {
       float totalBill = 0;
 
       //Iterating through streamed messages here
       error? e = clientStream.forEach(function(Order order) {
           totalBill += order.subTotal;           
       });
       //Once the client completes stream, a grpc:EOS error is returned to indicate it
       if (e is grpc:EOS) {
           FinalBill finalBill = {
               total:totalBill
           };
           //Sending the total bill to the client
           grpc:Error? result = caller->send(finalBill);
           if (result is grpc:Error) {
               log:printError("Error occurred when sending the Finalbill: " + 
result.message() + " - " + <string>result.detail()["message"]);
           } else {
               log:printInfo ("Sending Final Bill Total: " + 
finalBill.total.toString());
           }
           result = caller->complete();
           if (result is grpc:Error) {
               log:printError("Error occurred when closing the connection: " + 
result.message() +" - " + <string>result.detail()["message"]);
           }
       }
       //If the client sends an error instead it can be handled here
       else if (e is grpc:Error) {
           log:printError("An unexpected error occured: " + e.message() + " - " +
                                                   <string>e.detail()["message"]);
       }   
   }
}
      
      



5. Service   CheckoutService



(CheckoutServicesampleservice.bal)





grpc:EOS



, , ( ) caller object



.





CheckoutService :





$ ballerina grpc --mode client --input proto/checkout.proto --output gencode
      
      



Cart. Cart REST API: , — . , gRPC Order . Checkout , , Checkout gRPC . Ballerina Stream Client Object



gRPC. 2 , Ballerina.





Figura 2. Cliente gRPC Ballerina de streaming 
2. gRPC Ballerina 

CheckoutService resource function checkout Cart. , gRPC Stock, Golang, , .





syntax="proto3";
package retail_shop;
option go_package = "../stock;gen";
import "google/api/annotations.proto";
 
service StockService {
   rpc UpdateStock(UpdateStockRequest) returns (Stock) {
       option (google.api.http) = {
           // Route to this method from POST requests to /api/v1/stock
           put: "/api/v1/stock"
           body: "*"
       };
   }
}
message UpdateStockRequest {
   string itemNumber = 1;
   int32 quantity = 2;
}
message Stock {
   string itemNumber = 1;
   int32 quantity = 2;
      
      



6. Stock (stock.proto)





UpdateStock REST API API, gRPC . grpc-gateway — protoc, gRPC -, RESTful JSON API gRPC. 





 





Figura 3: grpc-gateway
3: grpc-gateway

grpc-gateway API- gRPC REST.





gRPC Golang:





protoc -I/usr/local/include -I. \
-I$GOROOT/src \
-I$GOROOT/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--go_out=plugins=grpc:. \
stock.proto
      
      



grpc-gateway Golang:





protoc -I/usr/local/include -I. \
-I$GOROOT/src \
-I$GOROOT/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--grpc-gateway_out=logtostderr=true:. \
stock.proto
      
      



stock.swagger.json:





protoc -I/usr/local/include -I. \
-I$GOROOT/src \
-I$GOROOT/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
-I$GOROOT/src \
--swagger_out=logtostderr=true:../stock/gen/. \
./stock.proto
      
      



git microservices-with-grpc README.md.





gRPC , . gRPC , , . , gRPC , REST API, , grpc-gateway. , , gRPC, Deadlines, Cancellation, Channels xDS, .





Ballerina gRPC, :





  • Unary Blocking





  • Unary Non-Blocking





  • Server Streaming





  • Client Streaming





  • Bidirectional Streaming





Golang gRPC, , , , Interceptor, Deadlines, Cancellation, Channels gRPC , . git grpc-go, .





:





  • Generating Unified APIs with Protocol Buffers and gRPC





  • Writing REST Services for the gRPC curious





  • Using gRPC for Long-lived and Streaming RPCs






"Software Architect".



" API HTTP".












All Articles