RPC框架服务注册中心核心功能

  1. 服务注册
  2. 服务反注册
  3. 服务订阅
  4. 服务反订阅
  5. 服务心跳
  6. 服务地址获取
  7. 服务信息客户端缓存
  8. 服务信息服务端缓存

表设计

t_admin(后台管理账户)
 CREATE TABLE t_admin (
id int(11) NOT NULL AUTO_INCREMENT,
user_name varchar(32) NOT NULL COMMENT ‘用户名’,
pwd varchar(64) NOT NULL COMMENT ‘密码’,
active tinyint(1) NOT NULL COMMENT ‘激活态 0 - 关闭, 1- 开启’,
create_time timestamp NULL DEFAULT NULL,
update_time timestamp NOT NULL DEFAULT NULL,
 PRIMARY KEY (id),
 UNIQUE KEY user_name_UNIQUE (user_name)
 ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;t_application(应用名)
 CREATE TABLE t_application (
id int(11) NOT NULL AUTO_INCREMENT,
app_code varchar(100) NOT NULL,
provider tinyint(1) DEFAULT NULL COMMENT ‘是否为注册方应用 0否1是’,
consumer tinyint(1) DEFAULT NULL COMMENT ‘是否为订阅方应用 0否1是’,
create_time datetime DEFAULT NULL,
update_time datetime DEFAULT NULL,
 PRIMARY KEY (id),
 UNIQUE KEY app_code_UNIQUE (app_code)
 ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT=‘应用名表’;t_server(主机)
 CREATE TABLE t_server (
id int(11) NOT NULL AUTO_INCREMENT,
host_name varchar(36) NOT NULL COMMENT ‘服务主机ip或主机名’,
port int(11) NOT NULL COMMENT '服务端口 订阅方的端口用0表示 ',
create_time datetime DEFAULT NULL,
update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 PRIMARY KEY (id),
 UNIQUE KEY idx_host_name_port (host_name,port)
 ) ENGINE=InnoDB AUTO_INCREMENT=37109 DEFAULT CHARSET=utf8 COMMENT=‘服务器表’;t_service(服务)
 CREATE TABLE t_service (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(64) COLLATE utf8_bin DEFAULT NULL COMMENT ‘服务名称简写’,
interface_name varchar(256) COLLATE utf8_bin DEFAULT NULL,
version varchar(45) COLLATE utf8_bin DEFAULT NULL COMMENT ‘版本号’,
description varchar(256) COLLATE utf8_bin NOT NULL COMMENT ‘服务描述’,
app_id int(11) DEFAULT NULL,
active tinyint(1) NOT NULL DEFAULT ‘1’ COMMENT ‘服务总开关 0 - 关闭, 1- 开启’,
create_time timestamp NULL DEFAULT NULL,
update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
methods varchar(16392) COLLATE utf8_bin DEFAULT NULL COMMENT ‘接口对应方法’,
is_delete tinyint(1) DEFAULT NULL COMMENT ‘是否删除:0否,1 是’,
 PRIMARY KEY (id),
 KEY idx_appid (app_id),
 KEY idx_name (name)
 ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT=‘服务表’;t_service_mapping(服务发布与订阅映射)
 CREATE TABLE t_service_mapping (
id int(11) NOT NULL AUTO_INCREMENT,
service_id int(11) NOT NULL COMMENT ‘服务id’,
server_id int(11) NOT NULL COMMENT ‘服务器id’,
provider_app_id int(11) DEFAULT NULL COMMENT ‘提供服务的应用ID’,
consumer_app_id int(11) DEFAULT NULL COMMENT ‘消费服务的应用ID’,
version varchar(64) DEFAULT NULL COMMENT ‘服务版本’,
active tinyint(1) NOT NULL COMMENT ‘是否激活服务 0 - 关闭, 1 - 开启’,
status tinyint(1) NOT NULL DEFAULT ‘0’ COMMENT ‘运行状态 0 - 正常, 1 - 流控中, 2 - 降级中’,
role varchar(45) DEFAULT NULL COMMENT ‘角色:provider注册服务 consumer订阅服务’,
create_time datetime DEFAULT NULL,
update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
registe_time datetime DEFAULT NULL COMMENT ‘注册时间’,
heartbeat_time datetime DEFAULT NULL COMMENT ‘心跳时间’,
is_delete tinyint(1) DEFAULT NULL COMMENT ‘是否逻辑删除 0否 1是’,
has_heartbeat tinyint(1) DEFAULT ‘是否有心跳过0否1是’,
is_forbidden tinyint(1) DEFAULT ‘0’ COMMENT ‘是否禁止访问,1:禁止访问(查找此提供方地址时,不提供此server_id,相当于临时下线),0:允许访问’,
 PRIMARY KEY (id),
 KEY idx_provider_id (provider_app_id),
 KEY idx_consumer_id (consumer_app_id),
 KEY idx_service_id (service_id),
 KEY idx_server_id (server_id),
 KEY idx_server_role (server_id,role)
 ) ENGINE=InnoDB AUTO_INCREMENT=8827075 DEFAULT CHARSET=utf8 COMMENT=‘服务映射表’;

接口设计

public interface RegisterService {
/**
 * 服务注册
 * @param url
 * @throws RegisteException
 */
void registe( URL url) throws RegisteException;

/**
 * 服务反注册
 * @param url
 * @return
 * @throwsRegisteException
 */
boolean unregiste(URL url) throws RegisteException;

/**
 * 服务订阅
 * @param url
 * @throws RegisteException
 */
void subscrible(URL url) throws RegisteException;

/**
 * 服务反订阅
 * @param url
 * @return
 */
boolean unsubscrible(URL url) throws RegisteException;

/**
 * 根据URL对象返回服务定义对象
 * @param url
 * @return
 */
List<ServiceDefinitionDO> findServiceDefinitions(URL url);

/**
 * 根据URL列表返回服务定义对象数据字典
 * @param url
 * @return
 */
Map<String,List<ServiceDefinitionDO>> queryServiceDefinitions(List<URL> urls);

/**
 * 根据URL更新注册接口的心跳时间
 * @param url
 */
void heartbeat(Map<String,Set<URL>> maps);}
 public class URL implements Serializable {private static final long serialVersionUID = -425965346788635674236789L;

/** 接口名,如 com.xx.order.OrderService */
private String interfaceName;

/** 服务名,如 orderService */
private String serviceName;

/** 版本号,如 1.0.0 */
private String version;

/** 接口方法定义*/
private String methods;

/** 应用名称 */
private String appName;

/** ip,如 192.168.1.1 */
private String host;

/** 端口,如 8080 */
private int port;}

注册中心服务下线

  1. 通过定时任务定时扫描连续三次没有心跳的服务映射,将其逻辑删除
  2. 通过定时任务,删除24小时前已逻辑删除且没有心跳的服务映射

服务注册与反注册

  1. 服务端应用在应用启动时,调用注册中心服务注册接口注册服务信息,并开启心跳线程,定时心跳
  2. 服务端关闭时,向注册中心调用反注册接口,下线此IP端口上的所有服务
  3. 服务端将所有应用名,server地址,服务名,映射信息通过定时任务存放至本地JVM,以确保免数据库宕机时,注册中心服务端高可用性
  4. 注册中心应用服务端多机布署,mysql采取主从架构

服务订阅与反订阅

  1. 客户端应用启动时,根据rpc框架配置引用的接口,去注册中心获取所有接口的服务地址
  2. 客户端开启心跳线程,定时心跳,将客户端每次心跳的md5值与注册中心作对比,如果客户端心跳的md5值为空或与注册中心的md5值不同时,调用服务中心拉取服务地址的接口,并缓存至客户端本地文件中
  3. 客户端查找服务地址时,从本地文件中去查找.
  4. md5值是根据所有订阅的接口及接口对应的服务地址信息与注册中心作对比判断(md5(客户端接口地址信息)==md5(注册中心上此应用此IP订阅接口及地址))是否相等
  5. 客户端关闭时,调用注册中心反订阅接口,下线此应用此IP上订阅的服务接口信息