基于netty的简易RPC框架

基于netty的简易RPC框架

一、基础设计

1、服务注册和发现

   rpc远程框架我们要实现的客户端使用功能是,远程调用接口的提供者producer使用@server注解,将此service注解的服务类信息,服务地址(本机ip+netty设置的服务端口),注册到注册中心上,注册中心采用zookeeper。调用接口端consumer在调用类的服务字段上使用@inject,即可调用远端producer,这个是使用服务发现类zookeeperDiscovery实现的,即在zookpeer找到对应服务名的临时节点信息,利用loadBalance进行本地轮询,返回单个服务。

   服务注册代码:

 

public void register(ServiceObject so) throws Exception {
		// 注册到本地
		super.register(so);
		MyService service = new MyService();
		String host = InetAddress.getLocalHost().getHostAddress();
		String address = host + ":" + port;
		service.setAddress(address);
		service.setName(so.getClazz().getName());
		service.setWeight(this.weight);
		this.exportService(service);
	}
	
	/**
	 * 暴露服务到zookeeper中
	 */
	private void exportService(MyService serviceResource) {
		String serviceName = serviceResource.getName();
		String uri = JSON.toJSONString(serviceResource);
		try {
			uri = URLEncoder.encode(uri, RpcConstant.UTF_8);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		String servicePath = RpcConstant.ZK_SERVICE_PATH + RpcConstant.PATH_DELIMITER + serviceName + "/service";
		if (!zkClient.exists(servicePath)) {
			zkClient.createPersistent(servicePath, true);
		}
		String uriPath = servicePath + RpcConstant.PATH_DELIMITER + uri;
		if (zkClient.exists(uriPath)) {
			zkClient.delete(uriPath);
		}
		zkClient.createEphemeral(uriPath);
	}

 服务发现代码:

public class ZookeeperServerDiscovery implements ServerDiscovery{
	
	private ZkClient zkClient;

	public ZookeeperServerDiscovery(String zkAddress) {
		zkClient = new ZkClient(zkAddress);
		zkClient.setZkSerializer(new ZookeeperSerializer());
	}

	@Override
	public List<MyService> findServiceList(String name) {
		String servicePath = RpcConstant.ZK_SERVICE_PATH + RpcConstant.PATH_DELIMITER + name + "/service";
		List<String> children = zkClient.getChildren(servicePath);
		return Optional.ofNullable(children).orElse(new ArrayList<>()).stream().map(str -> {
			String deCh = null;
			try {
				deCh = URLDecoder.decode(str, RpcConstant.UTF_8);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
			return JSON.parseObject(deCh, MyService.class);
		}).collect(Collectors.toList());
	}

	public ZkClient getZkClient() {
		return zkClient;
	}

}

2、初始化启动

初始化启动采用spring的ApplicationListener<ContextRefreshedEvent>的监听器方式,即在spring启动时,就要对@service注解的bean,进行服务注册,对@inject注解的字段,基于字段类型进行创建代理类。( 代理类的功能就是基于服务发现,用netty创建一个client端,调用远程服务提供者的方法。)

public class DefaultRpcProcessor implements ApplicationListener<ContextRefreshedEvent> {

    private static Logger logger = LoggerFactory.getLogger(DefaultRpcProcessor.class);

    private ClientProxyFactory clientProxyFactory;

    private ServerRegister serverRegister;

    private RpcServer rpcServer;

    public DefaultRpcProcessor(ClientProxyFactory clientProxyFactory, ServerRegister serverRegister, RpcServer rpcServer) {
        this.clientProxyFactory = clientProxyFactory;
        this.serverRegister = serverRegister;
        this.rpcServer = rpcServer;
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        // Spring启动完毕过后会收到一个事件通知
        if (Objects.isNull(event.getApplicationContext().getParent())){
            ApplicationContext context = event.getApplicationContext();
            // 开启服务
            startServer(context);
            // 注入Service
            injectService(context);
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值