引言
在分布式系统中,服务注册和服务发现是实现微服务架构的重要组成部分。RPC框架作为一种常用的通信模式,为服务注册和服务发现提供了便利。本篇博客将介绍基于RPC框架的服务注册与发现的实现方式,并探讨其在构建可靠和弹性的分布式系统中的作用。
什么是服务注册与发现
服务注册与发现是指将服务提供者注册到某个中心,并使服务消费者能够发现和调用这些服务的过程。服务注册是将服务提供者的信息(如IP地址、端口号、服务接口等)注册到服务注册中心,而服务发现则是服务消费者从注册中心获取可用服务提供者的信息,以便进行远程调用。
注册中心
- 服务注册与发现的核心在于注册中心。它负责接收服务提供者的注册请求,并保存它们的信息。
- 常见的注册中心有ZooKeeper、Etcd、Consul等。这些注册中心提供了高可用、分布式的存储机制,确保服务的注册信息能够在集群中共享和同步。
- 注册中心的作用:让服务提供者将信息传入,并将其传给服务调用者,如下图:
本文文件目录
注册服务与发现的实现
- 在rpc应用的common包下创建URL类,传入服务中心的URL所携带的信息,用于生成URL对象
public class URL {
private String hostname;
private Integer port;
public URL(String hostname, Integer port) {
this.hostname = hostname;
this.port = port;
}
public String getHostname() {
return hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
}
- 在rpc应用下的register包下创建远程注册中心类
public class MapRemoteRegister {
//之所以用List存URL是因为Provider可能提供多个服务
private static Map<String, List<URL>> map=new HashMap<>();
//注册时将url加入到List中去
public static void regist(String interfaceName,URL url){
List<URL> list=map.get(interfaceName);
if(list==null){
list=new ArrayList<>();
}
list.add(url);
map.put(interfaceName,list);
}
public static List<URL> get(String interfaceName){
return map.get(interfaceName);
}
}
- 在Provider类下进行注册中心注册;由于创建URL对象,url中包含地址和接口,可以达成灵活传参,传到注册中心,这就是服务注册
public class Provider {
public static void main(String[] args) {
//希望启动时可以接收网络请求,可以用Netty、tomcat
//启动器先进行本地注册,获取接口名和实现类对象
//出现多个实现类时启动时可以指定版本号,根据不同版本执行不同的实现类方法
LocalRegister.regist(HelloService.class.getName(),"1.0",HelloServiceImpl.class);
LocalRegister.regist(HelloService.class.getName(),"2.0",HelloServiceImpl2.class);
//注册中心,服务注册
//获取URL对象
URL url=new URL("hostname",8080);
//注册中心注册
MapRemoteRegister.regist(HelloService.class.getName(),url);
//rpc框架负责启动网络
HttpServer httpServer=new HttpServer();
// httpServer.start("localhost",8080);
//获取URL对象后,start参数列表可以灵活变动
httpServer.start(url.getHostname(), url.getPort());
}
}
- 根据使用的接口名,使用map获取当前服务的ip地址和端口,这就是注册发现
public class ProxyFactory {
public static <T>T getProxy(Class interfaceClass){
//读取用户配置
//当前接口 代理逻辑
Object proxyInstance=Proxy.newProxyInstance(interfaceClass.getClassLoader(),new Class[]{interfaceClass},new InvocationHandler() {
.....
//服务发现
//根据使用的接口名,使用map获取当前服务的ip地址和端口
List<URL> list= MapRemoteRegister.get(interfaceClass.getName());
//框架的代码不能写死,如何解决动态地址和端口问题?——》注册中心
//意思::providerip地址以及传入的端口
String result=httpClient.send(....,....,invocation);
return result;
}
});
return (T) proxyInstance;
}
}
-
服务提供者注册
当服务提供者启动时,它会将自身的信息注册到注册中心。通常包括服务名称、IP地址、端口号、服务接口等信息。服务提供者可以定期向注册中心发送心跳来保证注册信息的有效性。注册中心会维护一个服务提供者的列表,并及时更新。 -
服务消费者发现
服务消费者需要从注册中心中获取可用的服务提供者列表。它可以通过订阅注册中心的通知或主动查询的方式获取服务提供者的信息。一旦获取到服务提供者列表,消费者就可以根据负载均衡策略选择合适的提供者进行远程调用。
结论
基于RPC框架的服务注册与发现在构建分布式系统中扮演着重要的角色。它可以帮助我们实现服务的动态扩展、负载均衡和故障恢复等功能。通过合理选择注册中心和实施健康检查、失败处理等策略,我们可以构建可靠、弹性的分布式系统,提高系统的可用性和稳定性。