Mastering API Design: Principles, Protobuf, RESTful, Swagger, and gRPC Explained
This article outlines essential API design principles and best practices, covering simple, understandable, consistent, stable, and secure APIs, then delves into RPC mechanisms, Protobuf serialization, RESTful conventions, Swagger documentation, Spring Boot integration, HTTP/2 performance improvements, and the powerful combination of HTTP/2 with Protobuf in gRPC.
API Design Principles
Good API design should be simple (easy to understand for most users), easy to read (clear logic without exotic interactions), consistent (uniform conventions across a company), stable (avoid frequent changes, use versioning), and secure (handle authentication, rate limiting, and proper error codes).
Serialization – Protobuf
Protobuf, an open‑source serialization protocol from Google, supports multiple languages (Java, C++, Python, Go, etc.) and provides a compact binary format that is faster and smaller than JSON or XML. It is widely used for high‑performance RPC.
syntax = "proto3";
option java_package = "com.cloudnative.protobuf";
option java_outer_classname = "ProductProtos";
message Product {
int32 id = 1;
string name = 2;
string price = 3;
enum ColorType {
WHITE = 0;
RED = 1;
BLACK = 2;
}
}Typical Maven/Gradle configuration uses the protobuf-maven-plugin to generate Java classes:
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.0</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.5.1:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.8.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
</plugin>Service Communication – RPC
Remote Procedure Call (RPC) lets a client invoke a method on a remote server as if it were local. A typical RPC flow includes client stub creation, request serialization, network transmission, server stub deserialization, method execution, response serialization, and client deserialization.
// Client side
Channel channel = ManagedChannelBuilder.forAddress("localhost", 8888).usePlaintext().build();
ProductServiceGrpc.ProductServiceBlockingStub stub = ProductServiceGrpc.newBlockingStub(channel);
ProductResponse resp = stub.getProduct(ProductRequest.newBuilder().setId(111).build()); // Server side
public class ProductService extends ProductServiceGrpc.ProductServiceImplBase {
@Override
public void getProduct(ProductRequest req, StreamObserver<ProductResponse> respObs) {
ProductResponse resp = ProductResponse.newBuilder()
.setId(req.getId())
.setName("example")
.build();
respObs.onNext(resp);
respObs.onCompleted();
}
}Service Communication – RESTful
REST (Representational State Transfer) uses HTTP verbs (GET, POST, PUT, PATCH, DELETE, etc.) and resources identified by URLs. Key guidelines include using nouns for paths, versioning via URL (e.g., /v1/users), proper status codes (200 OK, 201 Created, 400 Bad Request, 401 Unauthorized, 404 Not Found, 500 Internal Server Error), and stateless interactions.
GET /v1/users/1 // Retrieve user with ID 1
POST /v1/orders // Create a new order
PUT /v1/products/5 // Replace product 5
PATCH /v1/products/5 // Partially update product 5
DELETE /v1/products/5 // Delete product 5Implementing RESTful with Swagger
Swagger (OpenAPI) allows you to write a YAML/JSON definition that can generate interactive documentation, client SDKs, and server stubs.
swagger: "2.0"
info:
version: "1.0.0"
title: "Product API"
description: "Product API for test"
schemes:
- https
host: localhost
basePath: /product
paths: {}The Swagger Editor ( http://editor2.swagger.io ) visualizes the API and lets you download the generated JSON/YAML.
Implementing RESTful with Spring Boot, Springfox, Swagger
Spring Boot combined with Springfox automatically generates Swagger documentation from controller annotations.
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfoBuilder().title("Swagger构建RESTful API").version("1.0").build())
.select()
.apis(RequestHandlerSelectors.basePackage("com.cloudnative.rest"))
.paths(PathSelectors.any())
.build();
}
} @RestController
@RequestMapping("/products")
public class ProductController {
private List<Product> productList = new ArrayList<>();
public ProductController() { /* initialize list */ }
@ApiOperation(value="获取产品列表", notes="获取产品列表")
@GetMapping
public List<Product> getProductList() { return productList; }
@ApiOperation(value="获取产品详细信息", notes="根据url的id来获取产品详细信息")
@GetMapping("/{id}")
public Product getProduct(@PathVariable Integer id) { return productList.get(id); }
}Run the application and open http://localhost:8080/swagger-ui.html to see the generated UI.
HTTP Protocol Evolution – HTTP/2
HTTP/2 introduces binary framing, header compression, and multiplexing, eliminating head‑of‑line blocking and reducing latency. Benchmarks show a typical page load dropping from 14.7 s (HTTP/1.1) to 1.61 s (HTTP/2).
浏览器
每个域名支持的最大并发连接
IE 9
6
IE 10
8
Firefox 4+
6
Opera 11+
6
Chrome 4+
6
Safari
4
HTTP/2 also supports server push, allowing the server to proactively send resources without additional client requests.
HTTP/2 and Protobuf – gRPC
gRPC is a modern RPC framework built on HTTP/2 and Protobuf. It inherits HTTP/2 features (multiplexing, flow control) and uses Protobuf for efficient binary serialization. gRPC supports four streaming patterns: unary, client‑streaming, server‑streaming, and bidirectional streaming.
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.cloudnative.grpc";
option java_outer_classname = "ProductProtos";
message ProductRequest { int32 id = 1; }
message ProductResponse { int32 id = 1; string name = 2; string price = 3; }
service ProductService { rpc GetProduct(ProductRequest) returns (ProductResponse); } // Server implementation (Java)
public class ProductService extends ProductServiceGrpc.ProductServiceImplBase {
@Override
public void getProduct(ProductRequest req, StreamObserver<ProductResponse> respObs) {
ProductResponse resp = ProductResponse.newBuilder()
.setId(req.getId())
.setName("example")
.build();
respObs.onNext(resp);
respObs.onCompleted();
}
}
public class GRPCServer {
private final Server server = ServerBuilder.forPort(8888)
.addService(new ProductService())
.build();
public void start() throws IOException { server.start(); }
public void blockUntilShutdown() throws InterruptedException { server.awaitTermination(); }
public static void main(String[] args) throws Exception {
GRPCServer s = new GRPCServer();
s.start();
s.blockUntilShutdown();
}
} // Client (Java)
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 8888)
.usePlaintext()
.build();
ProductServiceGrpc.ProductServiceBlockingStub stub = ProductServiceGrpc.newBlockingStub(channel);
ProductResponse resp = stub.getProduct(ProductRequest.newBuilder().setId(111).build());
System.out.println(resp.getName());gRPC is widely adopted in cloud‑native projects such as etcd and Kubernetes.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
21CTO
21CTO (21CTO.com) offers developers community, training, and services, making it your go‑to learning and service platform.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
