IDL文件
接口描述语言(interface description language),通过一种中立的方式来描述接口,使得在不同的平台上运行的对象和不同语言编写的程序可以相互通信交流。比如你用Java语言实现提供的一个服务,也能被PHP语言调用。
也就是说IDL主要是用作跨语言平台的服务之间的调用,有两种最常用的IDL
- Facebook开源的Thrift协议
- Google开源的gRPC协议
以gRPC协议为例使用IDL文件方式来描述接口。
gRPC协议使用Protobuf简称proto文件来定义接口名、调用参数以及返回值类型。
比如文件helloword.proto定义了一个接口SayHello方法,它的请求参数是HelloRequest,它的返回值是HelloReply。
// The greeter service definition. service Greeter { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloReply) {} rpc SayHelloAgain (HelloRequest) returns (HelloReply) {} } // The request message containing the user's name. message HelloRequest { string name = 1; } // The response message containing the greetings message HelloReply { string message = 1; }
假如服务提供者使用的是Java语言,那么利用protoc插件即可自动生成Server端的Java代码。
private class GreeterImpl extends GreeterGrpc.GreeterImplBase { @Override public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) { HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build(); responseObserver.onNext(reply); responseObserver.onCompleted(); } @Override public void sayHelloAgain(HelloRequest req, StreamObserver<HelloReply> responseObserver) { HelloReply reply = HelloReply.newBuilder().setMessage("Hello again " + req.getName()).build(); responseObserver.onNext(reply); responseObserver.onCompleted(); } }
假如服务消费者使用的也是Java语言,那么利用protoc插件即可自动生成Client端的Java代码。
public void greet(String name) { logger.info("Will try to greet " + name + " ..."); HelloRequest request = HelloRequest.newBuilder().setName(name).build(); HelloReply response; try { response = blockingStub.sayHello(request); } catch (StatusRuntimeException e) { logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus()); return; } logger.info("Greeting: " + response.getMessage()); try { response = blockingStub.sayHelloAgain(request); } catch (StatusRuntimeException e) { logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus()); return; } logger.info("Greeting: " + response.getMessage()); }
gRPC协议的服务描述是通过proto文件来定义接口,然后再使用protoc来生成不同语言平台的客户端和服务端代码,从而跨语言服务调用。
在描述接口定义时,IDL文件需要对接口返回值进行详细定义。如果接口返回值的字段比较多,并且经常变化时,采用IDL文件方式的接口定义就不太合适了。一方面可能会造成IDL文件过大难以维护,另一方面只要IDL文件中定义的接口返回值有变更,都需要同步所有的服务消费者都更新,管理成本太高。
总结
通常情况下,如果只是企业内部之间的服务调用,并且都是Java,选择XML配置最简单。
如果企业内部存在多个服务,并且服务采用的是不同语言平台,建议使用IDL文件方式进行描述服务。
如果还存在对外开放服务调用的情形的话,使用RESTful API方式则更加通用。