微服务开发框架——Dubbo

微服务开发框架——Dubbo,第1张

服务开发框架——Dubbo

前言

        Apache Dubbo 是一款微服务开发框架,它提供了 RPC通信 与 微服务治理 两大关键能力。这意味着,使用 Dubbo 开发的微服务,将具备相互之间的远程发现与通信能力, 同时利用 Dubbo 提供的丰富服务治理能力,可以实现诸如服务发现、负载均衡、流量调度等服务治理诉求。同时 Dubbo 是高度可扩展的,用户几乎可以在任意功能点去定制自己的实现,以改变框架的默认行为来满足自己的业务需求。

一、Dubbo 简介

        Apache Dubbo是一款高性能的Java RPC框架。其前身是阿里巴巴公司开源的、轻量级的开源Java RPC 框架,可以和Spring框架无缝集成。

        Dubbo提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。        

        服务是 Dubbo 中的核心概念,一个服务代表一组 RPC 方法的集合,服务是面向用户编程、服务发现机制等的基本单位。Dubbo 开发的基本流程是:用户定义 RPC 服务,通过约定的配置 方式将 RPC 声明为 Dubbo 服务,然后就可以基于服务 API 进行编程了。对服务提供者来说是提供 RPC 服务的具体实现,而对服务消费者来说则是使用特定数据发起服务调用。

RPC

        RPC全称为remote procedure call,即远程过程调用。比如两台服务器A和B,A服务器上部署一个应用,B服务器上部署一个应用,A服务器上的应用想调用B服务器上的应用提供的方法,由于两个应用不在一个内存空间,不能直接调用,所以需要通过网络来表达调用的语义和传达调用的数据。 需要注意的是RPC并不是一个具体的技术,而是指整个网络远程调用过程。

二、Dubbo架构

Dubbo 基于消费端的自动服务发现能力,其基本工作原理如下图:

虚线是异步访问,实线是同步访问;蓝色色虚线:在启动时完成的功能;绿色线条是程序运行过程中的执行功能与流程;

Provider:        暴露服务的提供方

Consumer:      调用远程服务的服务消费方

Registry:          服务注册与发现的注册中心

Monitor:           统计服务的调用次数和调用时间的监控中心

Container:        服务运行的容器

调用关系说明:

        0. 服务容器负责启动,加载,运行服务提供者。

        1. 服务提供者在启动时,向注册中心注册自己提供的服务。

        2. 服务消费者在启动时,向注册中心订阅自己所需的服务。

        3. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给 消费者。

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

        5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中 心。

三、服务注册中心 Zookeeper

Dubbo官方推荐使用Zookeeper作为服务注册中心(Regitry)

Zookeeper的介绍与安装

介绍

Zookeeper 是 Apache Hadoop 的子项目,是一个树型的目录服务,支持变更推送,适合作为 Dubbo 服务的注册中心,工业强度较高,可用于生产环境,并推荐使用 。

Zookeeper的树形目录结构:

流程说明:

        服务提供者(Provider)启动时: 向 /dubbo/com.foo.BarService/providers 目录下写入自己的 URL 地址

        服务消费者(Consumer)启动时: 订阅 /dubbo/com.foo.BarService/providers 目录下的提供者 URL 地址。并向 /dubbo/com.foo.BarService/consumers 目录下写入自己的 URL 地址

        监控中心(Monitor)启动时: 订阅 /dubbo/com.foo.BarService 目录下的所有提供者和消费者 URL 地址

安装

cd conf
mv zoo_sample.cfg zoo.cfg

这里是使用的虚拟机CentOS7作为示例安装与使用。

第一步:在虚拟机上安装jdk;

第二步:将把 zookeeper 的压缩包(我们这里使用的是 zookeeper-3.4.6.tar.gz)上传到linux 系统;

第三步:解压缩包。-C参数后面跟进自己解压的路径;

 tar -zxvf zookeeper-3.4.6.tar.gz -C /tool/zookeeper

第四步:进入解压好的目录,需要创建一个data目录,作为配置文件的放置处;

mkdir data

第五步:进入解压目录下的conf目录,将把zoo_sample.cfg 复制一份并改名为zoo.cfg

cd conf
mv zoo_sample.cfg zoo.cfg

第六步:编辑复制的zoo.cfg文件,需要修改data属性,改为第四步创建的data目录下

dataDir=/tool/zookeeper/data

这样zookeeper的准备就做完了。

启动与停止zookeeper

首先我们需要进入zookeeper中,解压好的zookeeper-3.4.6目录下的bin目录下执行linux的shell命令。

相关命令:

启动服务命令

./zkServer.sh start

停止服务命令

./zkServer.sh stop

查看服务状态:

./zkServer.sh status

客户端连接

./zkCli.sh

Dubbo入门案例

        Dubbo作为一个RPC框架,其最核心的功能就是要实现跨网络的远程调用。我们的案例就简单的创建两个示范应用,一个作为服务的提供方(provider),一个作为服务的消费方(consumer)。通过Dubbo来实现服务消费方远程调用服务提供方的方法。

服务提供方开发

maven的pom.xml引入的相关依赖如下:



    4.0.0

    com.cqh
    dubbo-provider
    1.0-SNAPSHOT
    war

    
        UTF-8
        1.8
        1.8
        5.0.5.RELEASE
    
    
        
            org.springframework
            spring-context
            ${spring.version}
        
        
            org.springframework
            spring-beans
            ${spring.version}
        
        
            org.springframework
            spring-webmvc
            ${spring.version}
        
        
            org.springframework
            spring-jdbc
            ${spring.version}
        
        
            org.springframework
            spring-aspects
            ${spring.version}
        
        
            org.springframework
            spring-jms
            ${spring.version}
        
        
            org.springframework
            spring-context-support
            ${spring.version}
        
        
            mysql
            mysql-connector-java
            5.1.47
        
        
            com.alibaba
            druid
            1.1.6
        
        
        org.mybatis
        mybatis-spring
            1.3.2
        

        
        
            com.alibaba
            dubbo
            2.6.0
        
        
            org.apache.zookeeper
            zookeeper
            3.4.7
        
        
            com.github.sgroschupf
            zkclient
            0.1
        
        
            org.javassist
            javassist
            3.24.0-GA
        
        
            com.alibaba
            fastjson
            1.2.75
        
    

    
        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.8.1
                
                    1.8
                    1.8
                
            
            
                org.apache.tomcat.maven
                tomcat7-maven-plugin
                
                    8081
                    
                    /
                
            
        
    

在webapp目录下添一个web.xml文件

 web.xml配置文件:





    
        contextConfigLocation
        classpath:applicationContext*.xml
    
    
        org.springframework.web.context.ContextLoaderListener
    

之后我们在main.java目录下创建接口与实现类(作为提供服务)

接口 HelloService:

public interface HelloService {

    public String sayHello(String name);
}

创建一个实现类实现该接口 HelloServiceImpl(注意这里的@Service注解是使用的alibaba dubbbo包下的Service):

import com.alibaba.dubbo.config.annotation.Service;
import com.kkb.service.HelloService;

@Service
public class HelloServiceImpl implements HelloService {

    @Override
    public String sayHello(String name) {
        return "hello : " + name;
    }
}

我们还需要在src/main/resources下创建applicationContext-service.xml:




    
    
    
    
    
    
    
    

上面的配置文件web.xml用于指定我们上面开启的zookeeper服务IP地址、指定使用zookeeper的端口与协议、用于提供服务的包名等。这样我们tomcat开启后,就会在zookeeper上注册我们提供的服务,用于其他服务来远程调用等。

服务消费方开发

另开一个moudle,pom.xml与web.xml配置文件是答题相同的,只需要该部分内容:

pom.xml 需要将引入的tomcat插件的端口好改为 8002 

web.xml 中需要引入servlet的相关配置,需要接收url请求

添加内容:

    
    
        springmvc
        org.springframework.web.servlet.DispatcherServlet
        
            contextConfigLocation
            classpath*:applicationContext-web.xml
        
    
    
        springmvc
        /
    

我们需要沿用服务提供方中我们需要调用服务的接口 HelloService

然后我们创建一个controller用于接受请求 HelloController:

import com.alibaba.dubbo.config.annotation.Reference;
import com.cqh.service.HelloService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/dubbo")
public class HelloController {

    @Reference
    private HelloService helloService;

    @RequestMapping("/hello")
    @ResponseBody
    public String sayHello(String name) {
        //  远程调用
        String result = helloService.sayHello(name);
        System.out.println(result);
        return result;
    }

最后,在src/main/resources下创建applicationContext-web.xml:




    
    
    
    
    
    

    
    

这个配置文件中指定我们的zookeeper服务注册中心的IP地址、使用的协议端口等、指定需要远调用服务的包名。

提供者暴露服务的整体机制:

        在服务提供者初始化的时候,会通过 Config 组件中的 ServiceConfig 读取服务的配置信息。这个配置信息有三种形式,分别是 XML 文件,注解(Annoation)和属性文件(Properties 和 yml)。        在读取配置文件生成服务实体以后,会通过 ProxyFactory 将 Proxy 转换成 Invoker。        此时,Invoker 会被定义 Protocol,之后会被包装成 Exporter。        最后,Exporter 会发送到注册中心,作为服务的注册信息。

服务注册中心运作机制:

提供者(Provider)启动时,会向注册中心写入自己的元数据信息(调用方式)。消费者(Consumer)启动时,也会在注册中心写入自己的元数据信息,并且订阅服务提供者,路由和配置元数据的信息。服务管理中心(duubo-admin)启动时,会同时订阅所有消费者,提供者,路由和配置元数据的信息。当提供者离开或者新提供者加入时,注册中心发现变化会通知消费者和服务治理中心。
 

服务消费者大概机制:

服务消费者首先持有远程服务实例生成的 Invoker,然后把 Invoker 转换成用户接口的动态代理引用,服务引用的入口点在 ReferenceBean。

大致说明一下远程调用过程:

        我们在浏览器中调r的url:http://localhost:8082/dubbo/hello?name=wang,访问我们的HelloController,controller中我们沿用的服务提供方provider的HelloService接口,也就是说我们只是在服务消费方consumer调用自己的HelloService接口方法(这个接口并没有被实现),但是我们在这个引用的helloService对象上有一个Dubbo的注解@Reference,这样Dubbo就是创建该接口动态代理对象,在我们指定的zookeeper中寻找到服务提供方提供注册的服务(相当于订阅过程),然后远程服务实例生成的 Invoker,然后把 Invoker 转换成用户接口的动态代理引用;而我们的服务提供方(provider)提供的服务:HelloServiceImpl这个实现类,我们添加了@Servcice注解,这样就把我们的服务注册到了我们指定的zookeeper上,于是实现了远程服务调用。

示例图:

将provider与consumer的tomcat运行,这样会将自己注册至制zookeeper处:

可以看到我们注册的consumers于providers的相关信息:

 这样我们url调用查看:

 协议

我们在applicationContext-**.xml的配置文件中有协议与端口的配置


一般在服务提供者一方配置,可以指定使用的协议名称和端口号。

其中Dubbo支持的协议有:dubbo、rmi、hessian、http、webservice、rest、redis等。 推荐使用的是dubbo协议。 dubbo 协议采用单一长连接和 NIO 异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。不适合传送大数据量的服务,比如传文件,传视频等,除非请求 量很低。 也可以在同一个工程中配置多个协议,不同服务可以使用不同的协议。

例:







不同协议的相关区别,具体需要去官网查看对比:

RPC协议 | Apache Dubbohttps://dubbo.apache.org/zh/docs/v3.0/references/protocols/

Dubbo无法发布被事务代理的Service问题

如果我们在服务提供者provider提供的服务上添加@Transactionnal事务控制注解后,服务就发布不成功了。原因是事务控制的底层原理是为服务提供者类创建代理对象,而默认情况下Spring是基于JDK动态代理方式创建 代理对象,而此代理对象的完整类名为com.sun.proxy.$Proxy42(最后两位数字不是固定的),导致 Dubbo在发布服务前进行包匹配时无法完成匹配,进而没有进行服务的发布。

 解决方案:

1.        修改applicationContext-service.xml配置文件,开启事务控制注解支持时指定proxy-target-class 属性,值为true。其作用是使用cglib代理方式为Service类创建代理对象。

2.        修改HelloServiceImpl类,在Service注解中加入interfaceClass属性,值为HelloService.class, 作用是指定服务的接口类型。

@Service(interfaceClass = HelloService.class)
@Transactional
public class HelloServiceImpl implements HelloService {
public String sayHello(String name) {
return "hello " + name;
}
}

此处也是必须要修改的,否则会导致发布的服务接口为SpringProxy,而不是HelloService接口。

 

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5711467.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存