这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战
上一篇文章说了下RPC框架的实现,下面我们就来看下怎么使用我们自己写的RPC框架。
1. 使用 RPC 框架
RPC 框架的客户端和服务端的基本功能已经实现,下面我们使用刚刚实现的 RPC 框架 来调用一下 MyService.sayHello(String name) 这个接口
首先我们使用一个线程来启动服务端:
private static void startProduct() {
//通过一个线程启动服务端
String host = "localhost";
int port = 8878;
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("服务端启动........");
RpcProducer.produce(host, port);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
下面我们使用 刚刚实现的 RPC 框架来调用服务端的接口
private static void client() {
LocalAgent<MyService> serviceLocalAgent = new LocalAgent<>();
MyService myService = serviceLocalAgent.importer(MyServiceImpl.class,
new InetSocketAddress("localhost",8878));
System.out.println(myService.sayHello("RPC"));
}
在客户端,我们传了一个服务端实现类的类型、一个服务端的地址,然后就可以调用服务端的接口了。注意:我们并没有在客户端创建 接口的具体实现对象,而仅仅是把需要调用的 Class 通过 Socket 发送给了服务端。
2. 添加注册中心
考虑一下上面的代码,我们服务端的地址是写死在客户端和服务端的代码里的,如果服务比较多,而且每个服务的地址都不一样,直接写死是很难维护的,所以我们需要一个注册中心来管理每个服务的地址。
下面是一个最简单的注册中心:
public class RegistrationCenter {
private Map<String, InetSocketAddress> serviceMap = new HashMap<>();
public void register(String serviceName, String host, int port) {
serviceMap.put(serviceName, new InetSocketAddress(host, port));
}
public InetSocketAddress getService(String serviceName) {
return serviceMap.get(serviceName);
}
}
注册中心维护服务名称与服务地址的映射。
我们修改一下服务端的启动代码,当服务启动之后,向注册中心注册服务。
private static void startProduct(RegistrationCenter center) {
//通过一个线程启动服务端
String host = "localhost";
int port = 8878;
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("服务端启动........");
RpcProducer.produce(host, port);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
//向注册中心注册服务
center.register("MyService.sayHello", host, port);
}
修改一下客户端的调用方式,调用服务时,根据服务名从注册中心获取服务地址。:
private static void client(RegistrationCenter center) {
LocalAgent<MyService> serviceLocalAgent = new LocalAgent<>();
MyService myService = serviceLocalAgent.importer(MyServiceImpl.class,
center.getService("MyService.sayHello"));
System.out.println(myService.sayHello("RPC"));
}
3. 总结
这就是 RPC 框架的基本原理,通过 Socket 建立通信,通过序列化与反序列实现数据传输,使用反射执行具体的服务。
假设你对 RPC 还是没有什么概念,也没关系,但是你需要记住下面三个概念:
-
生产者:或者说是服务端,更具体点就是上面的
ProducerAgent类,负责解析消费者发送的参数,通过反射调用对应的服务,将结果序列化后发送给消费者。
-
消费者:就是我们的客户端,对应
LocalAgent类负责将需要调用的服务信息发送给生产者,将结果反序列化后获得实际的执行结果。
-
注册中心:提供服务的注册和发现的功能。对应
RegistrationCenter类责管理服务与地址的映射。