Dubbo 源码学习系列 优化篇《工厂模式在Dubbo中的应用》
Posted Dream_it_possible!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dubbo 源码学习系列 优化篇《工厂模式在Dubbo中的应用》相关的知识,希望对你有一定的参考价值。
前言
前四篇实现了基于zookeeper和Netty的远程调用的流程,我们可以继续对代码进行优化,利用简单工厂模式使其支持两种协议,代码会更加简洁、有层次感。可以将共有方法抽离出来成一个接口,我在用Http实现的时候,服务端使用了start(URL url)方法,客户端实现了send(URL url,Invocation invocation)方法,同样使用netty时,用Start()方法启动nettyServer, 用nettyClient去发送Invocation对象。
Protocol 接口:
package com.example.dubbo.framework;
public interface Protocol {
void start(URL url);
Object send(URL url, Invocation invocation);
}
添加DubboProtocol和HttpProtocol实现类, 将之前的client的send()方法和server的start()方法迁移到实现类里。
DubboProtocol
package com.example.dubbo.protocol.dubbo;
import com.example.dubbo.framework.Invocation;
import com.example.dubbo.framework.URL;
import com.example.dubbo.framework.Protocol;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NiosocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import java.util.concurrent.*;
public class DubboProtocol implements Protocol {
public NettyClientHandler client = null;
private URL url;
// 使用线程池开启线程
private static ExecutorService executorService = Executors.newCachedThreadPool();
@Override
public void start(URL url) {
client = new NettyClientHandler();
final Bootstrap bootstrap = new Bootstrap();
bootstrap.group(new NioEventLoopGroup())
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast("decoder", new ObjectDecoder(ClassResolvers.weakCachingConcurrentResolver(this.getClass().getClassLoader())));
pipeline.addLast("encoder", new ObjectEncoder());
pipeline.addLast("handler", client);
}
});
// 连接socket
try {
bootstrap.connect(url.getHost(), url.getPort()).sync();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 通过线程来发送信息给Server
@Override
public Object send(URL url, Invocation invocation) {
this.url = url;
if (client == null) {
start(url);
}
client.setInvocation(invocation);
try {
Object obj = null;
try {
obj = executorService.submit(client).get(3L, TimeUnit.SECONDS);
} catch (TimeoutException e) {
e.printStackTrace();
}
return obj;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return null;
}
}
HttpProtocol
package com.example.dubbo.protocol.http;
import com.alibaba.fastjson.JSONObject;
import com.example.dubbo.framework.Invocation;
import com.example.dubbo.framework.URL;
import com.example.dubbo.framework.Protocol;
import com.example.dubbo.utils.HttpUtils;
public class HttpProtocol implements Protocol {
@Override
public void start(URL url) {
HttpServer server = new HttpServer();
server.start(url);
}
@Override
public Object send(URL url, Invocation invocation) {
try {
return HttpUtils.doPostData(url.getHost() + ":" + url.getPort(), JSONObject.toJSONString(invocation));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
1. 工厂模式
用泛型定义简单工厂,此方式适用于对象少,数量不复杂的情况。
package com.example.dubbo.framework;
import com.example.dubbo.protocol.http.HttpProtocol;
import java.lang.reflect.Proxy;
/**
* 协议工厂
*/
public class ProtocolFactory {
public static Protocol getProtocol(Class<? extends Protocol> clazz) {
if (null != clazz) {
try {
return clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return null;
}
}
2. 整合工厂模式
服务端:
消费端:
在proxyFactory的getProxy()方法里修改为
重新启动后观察结果,依然可以达到RPC的目的!
如果要使用dubbo协议,那么用getProtocol(DubboProtocol.class)即可!
3. 总结
工厂模式的优点:
1) 可扩展性强,易于维护,再来一个协议也不怕。
2) 减少重复代码,通过工厂来统一管理创建实例。
利用接口将共有的行为给抽象出来,让代码更有层次感!
以上是关于Dubbo 源码学习系列 优化篇《工厂模式在Dubbo中的应用》的主要内容,如果未能解决你的问题,请参考以下文章
《跟二师兄学Nacos吧》EXT-01篇 看看Nacos是怎么活学活用简单工厂模式的!