java程序员 && 学习Dubbo框架之前必需掌握的知识点:RPC、Zookeeper

网页右边,向下滑有目录索引,可以根据标题跳转到你想看的内容
如果右边没有就找找左边
介绍RPC之前需要先了解RFC
  1. 由互联网工程任务组(IETF)发布的文件集,文件集中每个文件都有自己的唯一编号,例如:rfc1831
  2. 目前RFC文件由互联网协会(ISOC)赞助发行
  3. RPC(注意这里不是RFC)会收集这些编号,可通过指定网址查看
RPC
  1. 在rfc 1831中收录,RPC(Remote Procedure Call)远程过程调用协议
  2. RPC协议规定允许互联网中一台主机程序调用另一台主机程序,而程序员无需对这个交互过程进行编程,在RPC协议中强调当A程序调用B程序中功能或方法时,A是不知道B中方法具体实现的。
  3. RPC是上层协议,底层可以基于TCP协议,也可以基于HTTP协议。一般我们说的RPC都是基于RPC的具体实现,如Dubbo框架
  4. 广义上讲,只要满足网络中进行通讯调用都统称为RPC,甚至HTTP协议都可以说是RPC的具体实现,但是具体分析看来RPC协议要比HTTP协议更加高效,基于RPC的框架功能更多。
  5. RPC协议是基于分布式框架而出现的,所以RPC在分布式项目中有着得天独厚的优势
  6. 总之:RPC就是让我们可以不通过http协议,比如浏览器发请求等方式,就可以远程调用其它程序,比如两个不同服务器的程序,可以互相调用,而且不会暴露代码
RPC和HTTP对比
不同点RPCHTTP
具体实现可以基于TCP协议,也可基于HTTP协议基于HTTP协议
效率自定义具体实现可以减少很多无用的报文内容,是报文体积更小HTTP1.1报文中很多内容是无用的,HTTP2.0以后和RPC相差不大,比RPC少的可能就是一些服务治理等功能
连接方式长链接支持每次连接都是3次握手
性能可以基于很多序列化方法,如:thrift主要通过JSON,序列化和反序列效率更低
注册中心一般RPC框架都带有注册中心都是直连
负载均衡绝大多数RPC框架都带有负载均衡测量一般都需要借助第三方工具,例如:nginx

一、通过HttpClient实现RPC(了解即可)

HttpClient简介
  1. 在JDK中java.net包下提供了用户Http访问的基本功能,但它缺少灵活性和许多应用所需要的功能
  2. HttpClient起初是Apache Jakarta Common的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本。2007年成为了顶级项目
  3. HttpClient可以实现使用Java代码完成标准Http请求与响应

1、服务端编写

只需要编写一个简单的spring boot工程作为服务端返回点东西就行
  1. 创建maven引入依赖
    在这里插入图片描述
  2. 创建启动类
    在这里插入图片描述
  3. 创建一个controller
    在这里插入图片描述

2、客户端通过HttpClient请求

通过get方式请求
  1. 创建maven,引入依赖
    在这里插入图片描述
  2. 编写代码
    在这里插入图片描述
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class HttpClientGetDome {
    public static void main(String[] args) {
        //1.创建一个工具(相当于浏览器工具),发送请求,解析响应
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            //2.请求路径
            URIBuilder uriBuilder = new URIBuilder("http://localhost:8080/demoController/demo?param=zhanagsan");
            //3.创建httpGet请求对象
            HttpGet httpGet = new HttpGet(uriBuilder.build());
            //4.创建响应对象
            CloseableHttpResponse response = httpClient.execute(httpGet);
            //5.因为响应体响应的是字符串,所以通过httpEntity类型转换为字符串类型,并设置字符集编码,接受响应数据
            String s = EntityUtils.toString(response.getEntity(), "utf-8");
            //输出响应结果
            System.out.println(s);
            //6.释放资源
            response.close();
            httpClient.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
通过post方式请求
  1. 服务器端创建处理Post请求的方法
    在这里插入图片描述
  2. 编写客户端代码
    在这里插入图片描述

二、RMI实现RPC

RMI
  1. RMI(Remote Method Invocation) 远程方法调用
  2. 从JDK1.2推出的功能,可以实现在一个java应用中可以像调用本地方法一样调用另一个服务器中Java应用(JVM)中的内容
  3. RMI是Java语言的远程调用,无法实现跨语言
RMI的执行流程
  1. 首先RMI提供一个RMI Registry(注册表),是一个放置所有服务器对象的命名空间,每次服务端创建一个对象,它会使用bind()或rebind()方法注册该对象,使用称为绑定名称的唯一名称注册。也就是说,RMI的注册表,记录了这些服务器对象,客户端就可以通过注册表实现远程调用
  2. 要调用远程对象,客户端需要该对象的引用,既通过服务端绑定的名称从注册表中获取对象(通过lookup()方法)
常用API
  1. Remote
    java.rmi.Remote 定义了此接口为远程调用接口。如果接口被外部调用,需要继承此接口(也就是说,如果我们想要写需要被远程调用的方法,那么需要先创建一个接口,然后这个接口继承这个Remote接口,然后通过实现类,实现你要被远程调用的方法,只有你的接口里面定义的方法,才能被远程调用,比如你接口定义了a,实现类定义了a,b,c,那么只有a方法可以被远程调用

    public interface Remote{ }

  2. RemoteException
    java.rmi.RemoteException 上面我们说,你想被远程调用需要继承Remote接口,那么继承之后,如果你的方法是允许被远程调用的,需要抛出此异常
  3. UnicastRemoteObject
    java.rmi.server.UnicastRemoteObject 此类实现了Remote接口和Serializable接口,你的自定义接口的实现类,除了实现自定义接口的方法,还需要继承此类
  4. LocateRegistry
    java.rmi.registry.LocateRegistry 可以通过LocateRegistry在本机上创建Registry,通过特定的端口就可以访问这个Registry(也就是内个注册表,客户端相应通过RMI远程调用方法,需要到这里拿对象)
  5. Naming
    java.rmi.Naming 定义了发布内容可访问RMI名称,也是通过Naming获取到指定的远程方法
编写服务端
  1. 自定义接口,继承Remote接口,声明允许远程调用的方法,并抛出RemoteException异常
    在这里插入图片描述
import java.rmi.Remote;
import java.rmi.RemoteException;

//1. 自定义接口继承Remote接口
public interface RmiDomeService extends Remote {
    //2. 允许被调用方法定义,并抛出RemoteException异常
    public String dome(String param) throws RemoteException;
}
  1. 编写实现类,继承UnicastRemoteObject类,实现接口中定义的方法
    在这里插入图片描述
import com.yzpnb.service.RmiDomeService;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

//3. 继承UnicastRemoteObject类,此时会报错,因为UnicastRemoteObject类中构造方法只允许同包下访问,需要重写构造方法
public class RmiDomeServiceImpl extends UnicastRemoteObject implements RmiDomeService{//4. 实现自定义接口

    //因为UnicastRemoteObject类中的构造方法都是protected修饰,只允许同包下访问,所以,我们需要重新定义构造方法
    //因为默认构造方法会用super()调用父类构造方法
    public RmiDomeServiceImpl() throws RemoteException{

    }

    @Override
    public String dome(String param) throws RemoteException {
        return param + " abc";
    }
}

  1. 编写注册表并启动
    在这里插入图片描述
import com.yzpnb.service.RmiDomeService;
import com.yzpnb.service.impl.RmiDomeServiceImpl;

import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;

public class DomeRegistry {
    public static void main(String[] args) {
        try {
            //1. 创建接口实例
            RmiDomeService rmiDomeService = new RmiDomeServiceImpl();
            //2. 创建注册表,指定端口号
            LocateRegistry.createRegistry(8989);
            //3. 绑定服务,注意,这里使用的是rmi协议的URI地址
            Naming.bind("rmi://localhost:8989/rmiDome",rmiDomeService);

            System.out.println("服务器启动成功");
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (AlreadyBoundException e) {
            e.printStackTrace();
        }
    }
}
客户端远程调用
  1. 定义与服务端相同的接口
    在这里插入图片描述
  2. 编写一个方法,远程调用服务端的方法
    在这里插入图片描述
import com.yzpnb.service.RmiDomeService;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

public class ClientDome {
    public static void main(String[] args) {
        try {
            //通过Naming.lookup请求指定服务器对象
            RmiDomeService rmiDome = (RmiDomeService) Naming.lookup("rmi://localhost:8989/rmiDome");
            //远程调用方法,获取返回值
            String result = rmiDome.dome("i'm client");

            System.out.println(result);
        } catch (NotBoundException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        }

    }
}

三、Zookeeper

为什么我们不用HttpClient和RMI,而借助Zookeeper实现RPC
HttpClient和RMI,代码繁杂,麻烦,两个方法调用不方便
所以我们需要一个注册中心,将这些可以远程调用的方法发布到注册中心,此时谁想调用,和注册中心要就行
而不需要专门在自己的方法中,写远程调用的逻辑,直接要过来用就行了
Zookeeper
  1. 分布式管理软件,常用它作为注册中心(依赖zookeeper的发布/订阅功能)、配置文件中心、分布式锁配置、集群管理等。
  2. zookeeper一共就有两个版本。主要使用的是java语言编写
Zookeeper的内容我都放到了这里https://blog.csdn.net/grd_java/article/details/119299318
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

殷丿grd_志鹏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值