dubbo基础知识+实战demo(代码片段)

尚墨1111 尚墨1111     2022-12-31     562

关键词:

1. RPC

1.1 是什么

RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。比如两个不同的服务 A、B 部署在两台不同的机器上,那么服务 A 如果想要调用服务 B 中的某个方法该怎么办呢?使用 HTTP请求 当然可以,但是可能会比较慢而且一些优化做的并不好。

最终解决的问题:**让分布式或者微服务系统中不同服务之间的调用像本地调用一样简单。**是一种通过网络从远程计算机程序上请求服务

1.2 常用的 RPC 框架

  • Dubbo: Dubbo 是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。
  • gRPC :gRPC 是可以在任何环境中运行的现源高性能RPC框架。
  • Hessian: 采用的是二进制 RPC协议,因为采用的是二进制协议,所以它很适合于发送二进制数据。

1.3 实现原理:

// Client端 
// Student student = Call(ServerAddr, addAge, student)
1. 将这个调用映射为Call ID。
2.Call ID,student(params)序列化,以二进制形式打包
3.2中得到的数据包发送给ServerAddr,这需要使用网络传输层
4. 等待服务器返回结果
5. 如果服务器调用成功,那么就将结果反序列化,并赋给student,年龄更新

// Server端
1. 在本地维护一个Call ID到函数指针的映射call_id_map,可以用Map<String, Method> callIdMap
2. 等待客户端请求
3. 得到一个请求后,将其数据包反序列化,得到Call ID
4. 通过在callIdMap中查找,得到相应的函数指针
5. 将student(params)反序列化后,在本地调用addAge()函数,得到结果
6. 将student结果序列化后通过网络返回给Client
  • 服务端通过字符串解析出该字符串代表的接口的一切信息,需要用到反射技术

  • 客户端和服务端之间进行通信调用,需要用到socket技术

  • 服务端根据客户端不同请求返回不同的接口类型,此时客户端就要接收不同的接口类型,需要在客户端用到动态代理技术。

1.3.1 生成调用方法的请求:动态代理

基于动态代理生成代理对象,当调用代理对象的方法时,由代理进行相关信息(方法、参数等)的组装并发送到服务器进行远程调用,并由代理接收调用结果并返回

使用 JDK 动态代理类基本步骤:

1、编写需要被代理的类和接口

2、编写代理类,需要实现 InvocationHandler 接口,重写 invoke() 方法;

3、使用Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)动态创建代理类对象,通过代理类对象调用业务方法。

interface DemoInterface 
    String hello(String msg);


class DemoImpl implements DemoInterface 
    @Override
    public String hello(String msg) 
        System.out.println("msg = " + msg);
        return "hello";
    


class DemoProxy implements InvocationHandler 

    private DemoInterface service;

    public DemoProxy(DemoInterface service) 
        this.service = service;
    

    @Override
    public Object invoke(Object obj, Method method, Object[] args) throws Throwable 
        System.out.println("调用方法前...");
        Object returnValue = method.invoke(service, args);
        System.out.println("调用方法后...");
        return returnValue;
    



public class Solution 
    public static void main(String[] args) 
        DemoProxy proxy = new DemoProxy(new DemoImpl());
        DemoInterface service = Proxy.newInstance(
            DemoInterface.class.getClassLoader(),
            new Class<?>[]DemoInterface.class,
            proxy
        );
        System.out.println(service.hello("呀哈喽!"));
    

1.3.2 传输使用序列化

RPC 是一种设计,就是为了解决不同服务之间的调用问题,完整的 RPC 实现一般会包含有 传输协议序列化协议 这两个。

而 HTTP 是一种传输协议,RPC 框架完全可以使用 HTTP 作为传输协议,也可以直接使用 TCP,使用不同的协议一般也是为了适应不同的场景。

使用 TCP 和使用 HTTP 各有优势:

传输效率

  • TCP,通常自定义上层协议,可以让请求报文体积更小
  • HTTP:如果是基于HTTP 1.1 的协议,请求中会包含很多无用的内容

性能消耗,主要在于序列化和反序列化的耗时

  • TCP,可以基于各种序列化框架进行,效率比较高
  • HTTP,大部分是通过 json 来实现的,字节大小和序列化耗时都要更消耗性能

跨平台

  • TCP:通常要求客户端和服务器为统一平台
  • HTTP:可以在各种异构系统上运行

总结
  RPC 的 TCP 方式主要用于公司内部的服务调用,性能消耗低,传输效率高。HTTP主要用于对外的异构环境,浏览器接口调用,APP接口调用,第三方接口调用等。

2 Dubbo:远程过程调用

Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。

Remoting: 网络通信框架,实现了 sync-over-async 和request-response 消息机制.

RPC: 一个远程过程调用的抽象,支持负载均衡容灾集群功能

Registry: 服务目录框架用于服务的注册和服务事件发布和订阅

2.1 Dubbo框架结构

调用关系说明

  • Container负责启动,加载,运行服务提供者。

  • Provider在启动时,向注册中心注册自己提供的服务。

  • Consumer在启动时,向注册中心订阅自己所需的服务。

  • Register返回Provider地址列表给Consumer,如果有变更,注册中心将基于长连接推送变更数据给消费者。

  • Consumer从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

要启用服务发现,需要为 Dubbo 增加注册中心配置:在启动服务提供者项目之前要先启动zookeeper,因为我们需要把服务提供方注册到zookeeper中,然后才能被服务消费方发现并调用。

2.3 项目构建的相关

① 有关项目构建的相关内容

  • archetype 的作用是帮你生成某一种项目的通用文件布局,比如常用的maven-archetype-webapp
  • GroupID 对应Java包结构,在项目中看到的是main目录里java的目录结构。
  • ArtifactID 就是idea中工程的名字
  • version 对应项目的版本号,SNAPSHOT表示快照,即不稳定的意思
<groupId>com.test.gmall</groupId>        表示项目源码中java目录下的包结构
<artifactId>gmall-interface</artifactId> 表示项目的名称
<version>1.0-SNAPSHOT</version>          版本号

② 服务化最佳实践

  • 分包:建议将服务接口、服务模型、服务异常等均放在 API 包中,因为服务模型和异常也是 API 的一部分,这样做也符合分包原则:重用发布等价原则(REP),共同重用原则(CRP)。

  • 服务接口建议以业务场景为单位划分,并对相近业务做抽象,防止接口数量爆炸。

  • 每个服务方法应代表一个功能,而不是某功能的一个步骤,否则将面临分布式事务问题

2.4 环境搭建

  • 参考上节,下载并部署zookeeper
  • 下载dubbo admin ,作为监视器的可视化界面
    • 启动 zookeeper 的 zkServicer.cmd 服务
    • 进入dubbo下的 dubbo-admin-distribution/target 文件夹,启动cmd
    • 输入 java -jar dubbo-admin-0.3.0-SNAPSHOT.jar
    • 访问 http://localhost:8080

详情参考:dubbo admin

2.5 Demo 搭建

2.5.1 公共接口项目 gmall-interface

将公共的服务接口放在同一个工程gmall-interface下,将这个项目进行打包成jar包,并加入到本地maven仓库中

IDEA在本项目中 打开Terminal中输入 mvn package,将项目打包

将打包的jar包导入本地Maven仓库中,里面的Id分别对应pom.xml中的Id

在要导入的项目中执行,不是在打包的项目中执行。参考:如何在IDEA Maven项目中导入本地jar包的步骤

mvn install:install-file -DgroupId=com.test.gmall -DartifactId=gmall-interface -Dversion=1.0.0 -Dpackaging=jar -Dfile=D:\\MyApp\\JavaProject\\gmall-interface\\target\\gmall-interface-1.0.0.jar
public class UserAddress 
    private Integer id;
    private String userAddress;
    private String userId;
    private String consignee;//收货人
    private String phoneNum;
    private String isDefault;


//
public interface OrderService 
    void initOrder(String userId);

//服务提供方,获取用户地址
public interface UserService 
    List<UserAddress> getUserAddressList(String userId);

2.5.2 服务方:gmall-Provider

服务的提供方是UserService,提供用户的·收货地址

public class UserServiceImpl implements UserService 
    public List<UserAddress> getUserAddressList(String s) 
        UserAddress userAddress1 = new UserAddress(1,"广东省","001111","Dim","12345678"
                                                   ,"null");
        UserAddress userAddress2 = new UserAddress(2,"广西省","001111","Tom","12345612"
                                                   ,"null");
        return Arrays.asList(userAddress1,userAddress2);
    

1、将服务提供者注册到注册中心(暴露服务)

导入dubbo依赖,操作zookeeper的·客户端(curator)

<dependencies>        
    <dependency>            
        <groupId>com.test.gmall</groupId>            
        <artifactId>gmall-interface</artifactId>            
        <version>1.0.0</version>        
    </dependency>        <!--将服务注册到注册中心,需要导入dubbo依赖-->
    <dependency>            
        <groupId>com.alibaba</groupId>            
        <artifactId>dubbo</artifactId>            
        <version>2.6.2</version>        
    </dependency>        <!-- 导入操作注册中心zookeeper的客户端 --> 
    <dependency>            
        <groupId>org.apache.curator</groupId>            
        <artifactId>curator-framework</artifactId>            
        <version>2.12.0</version>        
    </dependency>    
</dependencies>

2、配置服务方,用 Spring 配置声明暴露服务

其实我们不需要注册中心也可以让消费者直接连接服务者(注册中心相当于中介),此时需要制定消费者和服务者之间的通信协议,也就是<dubbo:protocol name="dubbo" port="20880"/>这句话

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"     
       xsi:schemaLocation="http://www.springframework.org/schema/beans                           
                           http://www.springframework.org/schema/beans/spring-beans.xsd 
                           http://code.alibabatech.com/schema/dubbo
                           http://code.alibabatech.com/schema/dubbo/dubbo.xsd"><!--    当前应用的名字-->    
    <dubbo:application name="gmall-Provider"></dubbo:application><!--    指定注册中心的地址-->    
    <dubbo:registry address="zookeepe://127.0.0.1:2181" protocol="zookeeper" timeout="20000" /><!--使用dubbo协议,将服务暴露在20880端口-->    
    <dubbo:protocol name="dubbo" port="20880"/><!--    指定需要暴露的服务-->    
    <dubbo:service interface="com.test.gmall.service.UserService" ref="userService"/>    
    <bean name="userService" class="com.test.gmall.service.Impl.UserServiceImpl"></bean>
</beans>

3、测试是否已经将服务注册到了zookeeper中

开启zookeeper服务,注意!

zkService.cmd

zkcli.cmd

运行dubbo.admin,打开的cmd不要关闭

新建测试类,运行,此时如果在dubbo.admin中能够看到服务信息,即表示注册服务成功

public class Provider 
    public static void main(String[] args) throws IOException 
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Provider.xml");
        context.start();//启动服务
        System.in.read();//阻塞
    

2.5.3 消费者: gmall- Consumer

gmall-Consumer工程中创建OrderService的实现类,里面远程调用到了UserService.getUserList方法

/**
 * @author:liuliping * @date:2021/7/7 11:28
 *///注意此时使用的是dubbo的service注解
@Servicepublic
class OrderServiceImpl implements OrderService 
    @Autowired
    UserService userService;

    public void initOrder(String userId) 
        List<UserAddress> userList = userService.getUserAddressList(userId);
        for (UserAddress user : userList) 
            System.out.println(user.getUserAddress() + user.getUserId());
        
    


配置消费者从注册中心订阅服务

1、导入依赖

<dependencies>
    <dependency>
        <groupId>com.test.gmall</groupId>
        <artifactId>gmall-interface</artifactId>
        <version>1.0.0</version>
    </dependency>        <!--将服务注册到注册中心,需要导入dubbo依赖-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo</artifactId>
        <version>2.6.2</version>
    </dependency>        <!-- 导入操作注册中心zookeeper的客户端 -->
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-framework</artifactId>
        <version>2.12.0</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>1.7.25</version>
        <scope>compile</scope>
    </dependency>
</dependencies>

2、配置consumer.xml设置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans                           http://www.springframework.org/schema/beans/spring-beans.xsd                           http://code.alibabatech.com/schema/dubbo                           http://code.alibabatech.com/schema/dubbo/dubbo.xsd                           http://www.springframework.org/schema/context                  http://www.springframework.org/schema/context/spring-context-4.2.xsd">    
    <!--为了使注解生效,所以需要开启包扫描-->
    <context:component-scan base-package="com.test.gmall.service.Impl"></context:component-scan>
    <!--设置应用名称-->
    <dubbo:application name="gmall-Consumer"></dubbo:application>
    <!-- 指定注册中心地址   -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
    <!--生成远程服务UserService的代理,可以和本地一样调用service-->
    <!--userService在容器里面,所以可以直接用spring注解注入-->
    <dubbo:reference interface="com.test.gmall.service.UserService" id="userService"></dubbo:reference>
    <bean name="orderService" class="com.test.gmall.service.Impl.OrderServiceImpl"></bean>

3、创建测试类

public class Consumer 
    public static void main(String[] args) throws IOException 
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Consumer.xml");
        OrderService orderService = context.getBean(OrderService.class);        //实现输出结果,说明远程调用实现
        orderService.initOrder("1");
        System.out.println("调用完成.....");
        System.in.read();
    

dubbo实战---noprovideravailablefortheservice(代码片段)

问题: java.lang.IllegalStateException:Failedtocheckthestatusoftheservicecom.alibaba.dubbo.demo.consumer.HelloService.Noprovideravailablefortheservicecom.alibaba.dubbo.demo.consumer.HelloServicefromtheurlzookeeper://*.*.*.*:2181/com.alibaba.dubbo.registry.RegistryService?anyhost=true&amp;a... 查看详情

vue框架-08-基础实战demo(代码片段)

Vue框架-08-基础实战demo前面介绍了有7篇了,都是小实例,没有相对完整的应用,虽然有些功能挺实用,但还是有的不常用的,今天记录一篇关于前几篇基础内容的实战demo,也是对Vue基础的简单应用。来看截图:源代码html文件:&... 查看详情

dubbo+zk+springboot分布式实战(代码片段)

Dubbo的官网:https://dubbo.apache.org/zh/项目结构dubbo-demo作为外层父项目。dubbo-api:作为公共模块,暴露接口,服务提供者与服务生产者模块依赖于它;dubbo-provider:服务提供者,用于实现接口;dubbo-consu... 查看详情

windows搭建dubbo服务demo(代码片段)

1.安装zookeeper。  将/conf目录下的zoo_sample.cfg文件改名为zoo.cfg,修改scf.cfg文件,添加dataDir,dataLogDir。 进入bin/zkService.cmd启动(单机)2.创建一个dubbo-demo项目(spring项目),建立三个moudle:dubbo-api、dubbo-consumer、dubbo-pr 查看详情

springboot知识体系+vue3实战wiki知识库系统笔记demo6_vue(代码片段)

集成antdesignnpminstallant-design-vue@next--save引入main.jsimportcreateAppfrom'vue'importAppfrom'./App.vue'importrouterfrom'./router'importstorefrom'./store'importAntdf 查看详情

springboot知识体系+vue3实战wiki知识库系统笔记demo3_commonresp(代码片段)

SpringBoot知识体系+Vue3实战WIKI知识库系统笔记注:可以点击提交的log来查看每次提交完成的功能,这是非常好的学习方式。设置一个CommonResp的类。packagecom.roc.wiki.resp;publicclassCommonResp<T>privatebooleansuccess=true;privateSt... 查看详情

springboot知识体系+vue3实战wiki知识库系统笔记demo4_mybatis_example(代码片段)

SpringBoot知识体系+Vue3实战WIKI知识库系统笔记前端将参数传到后台。这里接收参数可以不加修饰的@,参数会自动绑定到同名的属性上。这里也可以使用对象。前端传来的参数可以自定绑定到对象的属性里面。要保证名字... 查看详情

springboot知识体系+vue3实战wiki知识库系统笔记demo7_axios_cross(代码片段)

安装:npminstallaxios使用:<script>//@isanaliasto/srcimportHelloWorldfrom'@/components/HelloWorld.vue'importaxiosfrom'axios'exportdefaultname:'Home',compo 查看详情

dubbo基础知识——dubbo的分层结构和执行流程,以及和springcloud的区别。(代码片段)

RPC简单实现一个RPC框架我们这是Demo,目的是突出RPC框架重点功能-实现远程调用。所以啥七七八八的都没,并且我用伪代码来展示,其实也就是删除了一些保护性和约束性的代码,因为看起来太多了不太直观,... 查看详情

springboot知识体系+vue3实战wiki知识库系统笔记demo1_mybatis_generator(代码片段)

SpringBoot知识体系+Vue3实战WIKI知识库系统笔记**注:**可以点击提交的log来查看每次提交完成的功能,这是非常好的学习方式。pom引入插件<build><plugins><plugin><groupId>org.springframework.boot</groupId><ar 查看详情

基于url发布无注册中心dubbo服务demo(代码片段)

1:创建dubbo-servermaven工程2:分别在dubbo-server下创建2个模块server-api(定义接口)和server-provider(实现接口)  server-api:packagecom.cn.dubbo;publicinterfaceIGpHelloStringsayHello(Stringmsg);server-provider:packa 查看详情

从一个demo说起dubbo3(代码片段)

简介2017年的9月份,阿里宣布重启Dubbo的开发维护,并且后续又将Dubbo捐献给了Apache,经过多年的发展已经发布到3.X版本了,Dubbo重启维护之后是否有值得我们期待的功能呢,下面就来看看吧。ApacheDubbo是一款微服务框架,为大规... 查看详情

dubbo框架demo之dubbo-admin管理平台和zookeeper注册中心搭建(代码片段)

dubbo框架Demo之dubbo-admin管理平台和zookeeper注册中心搭建一、安装环境系统软件环境单机系统Centos7.3java:jdk1.8.0_181maven:apache-maven-3.5.4tomcat:apache-tomcat-8.5.30zookeeper:zookeeper-3.4.13Dubbo-admin:dubbo-admin-2.5.10.war环境简介 查看详情

springboot知识体系+vue3实战wiki知识库系统笔记demo8_filter_interceptor_aop(代码片段)

Filter&Interceptor&aop这三个选一个用即可.Filter使用一个链来调用方法把请求传回过滤链.packagecom.roc.wiki.filter;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.stereotype.Component;importja 查看详情

dubbo入门--搭建一个最简单的demo框架(代码片段)

来源自:https://blog.csdn.net/noaman_wgs/article/details/70214612Dubbo背景和简介Dubbo开始于电商系统,因此在这里先从电商系统的演变讲起。单一应用框架(ORM) 当网站流量很小时,只需一个应用,将所有功能如下单支付等都部署在一起,... 查看详情

dubbo快速入门demo(代码片段)

参考文章 https://blog.csdn.net/abcwanglinyong/article/details/81906027该demo包含三个项目,分别是:服务提供端项目:provider服务消费端项目:consumer共用服务接口项目:api1、新建maven项目api注意将其pom.xml中的打包方式改为jar然后在com.dubb... 查看详情

springboot知识体系+vue3实战wiki知识库系统笔记demo5_req&resp(代码片段)

请求和返回值的封装。一般情况下请求类不用封装。这个项目用到了,就按照它的写。返回值封装时可以有的。一般我们查询用户,返回值的字段和数据库的字段并不是一一对应的,比如说用户的密码我们就不能返回... 查看详情

springboot知识体系+vue3实战wiki知识库系统笔记demo3_commonresp(代码片段)

SpringBoot知识体系+Vue3实战WIKI知识库系统笔记注:可以点击提交的log来查看每次提交完成的功能,这是非常好的学习方式。设置一个CommonResp的类。packagecom.roc.wiki.resp;publicclassCommonResp<T>privatebooleansuccess=true;privateSt... 查看详情