手写RPC之集成Zookeeper(Socket版)

1.修改服务提供者

public class RpcServer  {
    private Integer port;
    private  List<String> classNames=new ArrayList<String>();
    private Boolean flag=true;
    private void scanPackage(String packageName){
        URL url = this.getClass().getClassLoader().getResource(replaceTo(packageName));
        // 获取文件夹
        String urlFile = url.getFile();
        File file = new File(urlFile);
        String[] list = file.list();
        for (String path : list) {
            File eachFile = new File(urlFile + File.separator + path);
            // 如果是文件夹
            if (eachFile.isDirectory())
                scanPackage(packageName+"."+eachFile.getName());
            // 如果是字节码文件
            if (eachFile.getName().endsWith(".class"))
                classNames.add(packageName+"."+eachFile.getName().replace(".class",""));
        }
    }

    private String replaceTo(String packageName) {
        return packageName.replaceAll("\\.","/");
    }

    public Map<String,Object> getService(){
        String packageNames="com.MyRpc.service";
        try{
        // 封装所有服务提供者的service key:接口名的全限定类名  value:服务的具体实现类
        Map<String,Object> map=new ConcurrentHashMap<String, Object>();
        // 扫描指定的包 class的全限定类名封装在了classNames集合中
        String[] packageName = packageNames.split(",");
        for (String path : packageName) {
            scanPackage(path);
        }
        // 实例化服务的提供者
        if (classNames!=null)
            for (String className : classNames) {
                Class clazz = null;
                    clazz = Class.forName(className);

                if (clazz.isAnnotationPresent(Rpc.class)){
                    // 获取接口
                    Class[] interfaces = clazz.getInterfaces();
                    // 实例化
                    Object o = clazz.newInstance();
                    // 将接口和对象放入map集合中
                    map.put(interfaces[0].getName(),o);

                }
            }
            return map;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("服务器初始化失败");
        }
    }
    public void start(int port){
        setPort(port);
        ServerSocket serverSocket=null;
        ThreadPoolExecutor executor=null;
        try{
        Map<String, Object> service = getService();
        // 创建ServerSocket链接
            serverSocket = new ServerSocket(port);
            // 注册服务
            register();
            // 创建线程池
            executor=new ThreadPoolExecutor(5,10,60, TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(10));
            while (flag){
                // 获取客户端链接
                Socket accept = serverSocket.accept();
                RpcServiceRunnable server = new RpcServiceRunnable(accept, service);
                // 使用线程池执行任务
                executor.execute(server);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            CloseUtils.close(serverSocket,executor,null,null, null,null);
        }

    }
    private void stop(){
        this.flag=false;
    }

    private void register(){
        ZkClient client=new ZkClient("127.0.0.1:2181",30000,1000);
        String s = "/dubbo";
        if (!client.exists(s))
            client.createPersistent(s);
        InetAddress localHost=null;
        try {
            // 获取本机主机地址
            localHost = InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
            e.printStackTrace();
            throw new RuntimeException("获取本机ip地址失败");
        }
        String ip = localHost.getHostAddress();
        String service = ip + ":" + getPort();
        System.out.println("service = " + service);
        // 创建临时节点
        String path = s + "/" + service;
        // 如果存在过此临时节点删除
        if (client.exists(path))
            client.delete(path);
        // 创建临时节点 节点名称ip+端口号 值ip+端口号
        client.createEphemeral(path,service);
    }

    public Integer getPort() {
        return port;
    }

    public void setPort(Integer port) {
        this.port = port;
    }
}

2.修改服务调用者

public class RpcClientProxy implements InvocationHandler {
    private List<String> list=new LinkedList<String>();

    public RpcClientProxy() {

    }
    /**
     *@Description: 创建接口的代理对象
     *@Params [clazz]
     *@Return T
     *@Author Mr.Li
     *@Date 2020/4/26 21:20
     */
public <T> T getProxyObject(Class<T> clazz){
        return (T) Proxy.newProxyInstance(clazz.getClassLoader(),new Class<?>[]{clazz},this);
}

    public void initServer(){
        final ZkClient client=new ZkClient("127.0.0.1:2181",30000,1000);
        final String path="/dubbo";
        if (!client.exists(path))
            throw new RuntimeException("没有对应的服务器提供服务");
        // 清空服务器列表
        list.clear();
        final List<String> children = client.getChildren(path);
        for (String child : children) {
            // 将服务器列表放入集合
            list.add(client.readData(path+"/"+child).toString());
        }
        // 订阅节点监听 子节点改变后刷新集合
        client.subscribeChildChanges(path, new IZkChildListener() {
            public void handleChildChange(String s, List<String> ChildrenList) throws Exception {
                // 清空列表
                list.clear();
                for (String child : ChildrenList) {
                    // 将服务器列表放入集合
                    list.add(client.readData(path+"/"+child).toString());
                }
                System.out.println("-----------------server change---------------"+list);
            }
        });

    }
private int count=0;
public String getServer(){
    initServer();
    System.out.println(list.size());
    //负载均衡策略 轮询
   int index= count%list.size();
    count++;
    System.out.println("index = " + index);
    // 负载均衡策略 随机
//    int index= new Random().nextInt(list.size());
    return list.get(index);
}

     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
         RpcRequest request=new RpcRequest();
         request.setClassName(method.getDeclaringClass().getName());
         request.setMethodName(method.getName());
         request.setParamsType(method.getParameterTypes());
         request.setParams(args);
         String server = getServer();
         String[] split = server.split(":");
         // 使用客户端发起请求
         RpcClient rpc=new RpcClient();
        return rpc.start(request,split[0], Integer.valueOf(split[1]));
    }
}

3.测试服务端

public class ServiceClient {
    public static void main(String[] args) {
        RpcServer server=new RpcServer();
        server.start(8888);
        System.out.println();
    }
    @Test
    public void test1(){
        RpcServer server=new RpcServer();
        server.start(8900);
        System.out.println();
    }
    @Test
    public void test2(){
        RpcServer server=new RpcServer();
        server.start(8888);
        System.out.println();
    }
    @Test
    public void test3(){
        RpcServer server=new RpcServer();
        server.start(9000);
        System.out.println();
    }
}

4.测试客户端

public class ClientTest {
    public static void main(String[] args) {
        RpcClientProxy proxy=new RpcClientProxy();
        TestServer proxyObject = proxy.getProxyObject(TestServer.class);
        System.out.println(proxyObject.hello(3L));
        System.out.println(proxyObject.hello(3L));
        System.out.println(proxyObject.hello(3L));
    }
}

接手写RPC1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值