首页 > 数据库 > 数据库开发技术 > 如何发布和引用服务?
从这期开始,我将逐步讲解微服务各个基本组件的原理和实现方式。今天要分享的第一个组件是服务的发布和引用。构建微服务的首要问题是:服务提供者如何发布服务,服务消费者如何引用服务。具体来说,就是服务的接口名是什么,调用服务需要传递哪些参数,接口的返回值是什么类型,以及其他接口描述信息。
最常见的服务发布和引用方式有三种:
RESTful API
XML 配置
IDL 文件
首先介绍 RESTful API,这种方式主要用于 HTTP 或 HTTPS 协议的接口定义,即使在非微服务架构中也被广泛采用。下面是一个使用开源服务化框架 Motan 发布 RESTful API 的例子,发布了三个 RESTful 格式的 API,接口声明如下:
@Path("/rest")public interface RestfulService {@GET@Produces(MediaType.APPLICATION_JSON)List<User> getUsers(@QueryParam("uid") int uid);@GET@Path("/primitive")@Produces(MediaType.TEXT_PLAIN)String testPrimitiveType();@POST@Consumes(MediaType.APPLICATION_FORM_URLENCODED)@Produces(MediaType.APPLICATION_JSON)Response add(@FormParam("id") int id, @FormParam("name") String name);}
具体的服务实现如下:
public class RestfulServerDemo implements RestfulService {public List<User> getUsers(@CookieParam("uid") int uid) {return Arrays.asList(new User(uid, "name" + uid));}public String testPrimitiveType() {return "helloworld!";}public Response add(@FormParam("id") int id, @FormParam("name") String name) {return Response.ok().cookie(new NewCookie("ck", String.valueOf(id))).entity(new User(id, name)).build();}}
服务提供者通过将代码部署到 Tomcat 中,并配置 Tomcat 的 web.xml 文件来提供 RESTful API 服务。这样,服务消费者就可以通过 HTTP 协议调用服务。HTTP 协议是公开的协议,对服务消费者来说几乎没有学习成本,因此特别适合跨业务平台的服务调用。
接下来介绍 XML 配置方式,这种方式的服务发布和引用主要分三个步骤:
服务提供者定义接口并实现接口。
服务提供者进程启动时,加载 server.xml 配置文件,开启端口监听。
服务消费者进程启动时,通过加载 client.xml 配置文件来引用接口并发起调用。
服务提供者定义接口:
public interface FooService {public String hello(String name);}
实现接口:
public class FooServiceImpl implements FooService {public String hello(String name) {System.out.println(name + " invoked rpc service");return "hello " + name;}}
server.xml 配置文件示例:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:motan="http://api.weibo.com/schema/motan"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://api.weibo.com/schema/motan http://api.weibo.com/schema/motan.xsd"><bean id="serviceImpl" class="quickstart.FooServiceImpl" /><motan:service interface="quickstart.FooService" ref="serviceImpl" export="8002" /></beans>
client.xml 配置文件示例:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:motan="http://api.weibo.com/schema/motan"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://api.weibo.com/schema/motan http://api.weibo.com/schema/motan.xsd"><motan:referer id="remoteService" interface="quickstart.FooService" directUrl="localhost:8002" /></beans>
IDL 是接口描述语言,通过中立的方式描述接口,使不同平台上的对象和不同语言编写的程序能够互相通信。常见的 IDL 有 Facebook 的 Thrift 协议和 Google 的 gRPC 协议。以下是 gRPC 协议的示例,使用 Protobuf 文件定义接口:
service Greeter {rpc SayHello (HelloRequest) returns (HelloReply) {}rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}}message HelloRequest {string name = 1;}message HelloReply {string message = 1;}
服务实现:
private class GreeterImpl extends GreeterGrpc.GreeterImplBase {@Overridepublic void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();responseObserver.onNext(reply);responseObserver.onCompleted();}@Overridepublic void sayHelloAgain(HelloRequest req, StreamObserver<HelloReply> responseObserver) {HelloReply reply = HelloReply.newBuilder().setMessage("Hello again " + req.getName()).build();responseObserver.onNext(reply);responseObserver.onCompleted();}}
客户端调用示例:
public void greet(String name) {HelloRequest request = HelloRequest.newBuilder().setName(name).build();HelloReply response = blockingStub.sayHello(request);System.out.println(response.getMessage());response = blockingStub.sayHelloAgain(request);System.out.println(response.getMessage());}
PHP 客户端调用示例:
$request = new Helloworld\HelloRequest();$request->setName($name);list($reply, $status) = $client->SayHello($request)->wait();$message = $reply->getMessage();
今天介绍了服务描述的三种常见方式:RESTful API、XML 配置和 IDL 文件。具体采用哪种方式,需根据实际情况决定。如果企业内部之间的服务调用且都是 Java 语言,选择 XML 配置方式最简单。如果存在多语言平台的服务,建议使用 IDL 文件方式。如果需要对外开放服务,使用 RESTful API 方式更通用。
针对你的业务场景,假如要进行服务化,你认为使用哪种服务描述方式最合适?为什么?
分析业务场景:
描述你的业务场景,包括主要的功能和需求。例如,你的业务是否需要对外提供服务,是否涉及多语言平台等。
考虑技术栈:
说明你所在团队的主要技术栈。例如,团队主要使用的编程语言、框架和工具。
评估三种服务描述方式的适用性:
适用于跨语言平台的服务调用。
如果你的系统涉及多种编程语言(如 Java、PHP 等),使用 IDL 文件可以保证不同语言之间的互操作性。
适用于内部服务调用,特别是同一技术栈内(例如都是 Java)的服务。
如果你的业务主要在公司内部使用,且对性能要求较高,可以考虑使用 XML 配置方式,这样可以降低接口变更带来的维护成本。
适用于对外提供服务,或需要与其他系统进行跨平台通信的场景。
如果你的业务需要开放 API 给外部使用,RESTful API 是一个不错的选择,因为其学习成本低,适用范围广。
RESTful API:
XML 配置:
IDL 文件:
结合实际情况选择最合适的方式:
根据以上分析,结合实际情况,选择最合适的服务描述方式。
假设你的业务场景是一个需要对外提供 API 服务的电商平台,主要使用 Java 开发,同时需要与其他系统进行跨平台通信:
针对我们的电商平台业务场景,考虑到我们需要对外提供 API 服务,并且我们的主要技术栈是 Java,同时还需要与其他系统进行跨平台通信,我认为采用 RESTful API 是最合适的服务描述方式。
RESTful API 的主要优势在于其协议公开、学习成本低,适合对外提供服务。此外,HTTP 协议的通用性也方便我们与其他系统进行跨平台通信。虽然我们也可以考虑 XML 配置方式,但由于我们需要对外提供服务,RESTful API 更加适用。而 IDL 文件虽然可以解决跨语言调用的问题,但在我们的场景下,RESTful API 已经足够满足需求。
这样回答不仅详细说明了选择的原因,还展示了对业务需求和技术细节的深入理解。

原文作者:二进制跳动;如有侵权,请联系管理员删除。