教自己学Dubbo

image

本文章中的Demo案例已经同步至gitee,供各位参考。

Demo地址:https://gitee.com/lemon_ant/dubbo-demo.git

zookeeper&dubbo简介

架构

image

节点角色说明

节点 角色说明
Provider 暴露服务的服务提供方
Consumer 调用远程服务的服务消费方
Registry 服务注册与发现的注册中心
Monitor 统计服务的调用次数和调用时间的监控中心
Container 服务运行容器

调用关系说明

  1. 服务容器负责启动,加载,运行服务提供者。
  2. 服务提供者在启动时,向注册中心注册自己提供的服务。
  3. 服务消费者在启动时,向注册中心订阅自己所需的服务。
  4. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
  5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
  6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

Dubbo 架构具有以下几个特点,分别是连通性、健壮性、伸缩性、以及向未来架构的升级性。

zookeeper安装

下载zookeeper.tar.gz

https://www.apache.org/dyn/closer.lua/zookeeper/zookeeper-3.6.2/apache-zookeeper-3.6.2-bin.tar.gz

上传到centos上、

解压使用命令解压在/usr/local目录下

tar -zxvf zookeeper.tar.gz  -C /usr/local   

zookeeper目录下创建data文件夹存放数据,修改配置conf下的zoo_sample.cfg名为zoo.cfg(默认加载zoo.cfg)。

修改zoo.cfgdataDir参数为刚才创建的目录,保存退出。

zookeeper启动

启动的前提是需要安装jdk

作者:疯子加天才

标题:centos安装jdk1.8的三种方法

文章链接:https://www.cnblogs.com/telwanggs/p/11546751.html

在zookeeper目录下使用 ./zkServer.sh start 启动

./zkServer.sh status 查看运行状态 standalone 代表单机版

./zkServer.sh stop 停止

dubbo-admin可视化界面

dubbo-admin:https://github.com/apache/incubator-dubbo/releases/tag/dubbo-2.6.0

安装dubbo-admin.war放在本机tomcat中的wabapps目录,启动tomcat,待dubbo-admin.war解压后,进入目录dubbo-admin-2.6.0\WEB-INF\找到dubbo.properties配置文件,修改配置为zookeeper的IP地址,重新启动tomcat。

浏览器访问地址:http://127.0.0.1:8080/dubbo-admin-2.6.0 账号信息:root root

里面就是所有信息home > governance > applications能够看到注册上去的接口信息。

Dubbo服务提供方

创建一个空的maven项目,新建modul作为服务提供方。dubbo_provider。

导入pom文件



  4.0.0
  com.hkrt
  dubbo_provider
  1.0-SNAPSHOT
  war
  dubbo Maven Webapp
  http://www.example.com
  
    UTF-8
    1.8
    1.8
      5.0.5.RELEASE
  

  
    
      junit
      junit
      4.11
      test
    
    
      org.apache.curator
      curator-framework
      2.8.0
    
    
      org.apache.curator
      curator-recipes
      2.8.0
    
      
          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}
      
      
          com.alibaba
          dubbo
          2.6.2
      
      
          org.apache.zookeeper
          zookeeper
          3.4.9
      
      
          com.github.sgroschupf
          zkclient
          0.1
      
      
          com.alibaba
          fastjson
          1.2.47
      
  

  
    dubbo
      
        
          maven-clean-plugin
          3.1.0
        
        
          maven-resources-plugin
          3.0.2
        
        
          maven-compiler-plugin
          3.8.0
        
        
          maven-surefire-plugin
          2.22.1
        
        
          maven-war-plugin
          3.2.2
        
        
          maven-install-plugin
          2.5.2
        
        
          maven-deploy-plugin
          2.8.2
        
          
              org.apache.tomcat.maven
              tomcat7-maven-plugin
              
                  8081
                  /
              
          
      
  


创建service层接口和实现类

import com.alibaba.dubbo.config.annotation.Service;
@Service //发布服务必须使用Dubbo提供的service注解
public class HelloServiceImpl implements HelloService {

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

web.xml


  Archetype Created Web Application

  
    contextConfigLocation
    classpath:applicationContext*.xml
  

  
    org.springframework.web.context.ContextLoaderListener
  

applicationContext-service.xml



    
    

    
    

    
    
    
    
    
    

通过maven插件启动服务provider,查看dubbo-admin发现已经存在HelloService的相关信息。

Dubbo服务消费方

新建modul作为服务提供方。dubbo_consumer

同样和provider相同的pom文件依赖。

创建一个和服务提供方相同的包package,创建controller

import com.alibaba.dubbo.config.annotation.Reference;

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

    @Reference   //订阅zookeeper,查找相关服务
    private HelloService helloService;

    @ResponseBody
    @RequestMapping("/say")
    public String sayHello(String name){
        System.out.println("响应成功");
        return helloService.sayHello(name);
    }
}

HelloService.class

public interface HelloService {
    public String sayHello(String name);
}

web.xml


  
    dispatcherServlet
    org.springframework.web.servlet.DispatcherServlet
    
      contextConfigLocation
      classpath*:springmvc-servlet.xml
    
    1
  

  
    dispatcherServlet
    /
  

springmvc-servlet.xml




    
    

    
    

    
    

    
    

    
    

    
    

通过maven插件启动服务consumer,查看dubbo-admin发现已经存在HelloService的相关信息。

案例回顾

需要在impl类上添加注解@service

注意这里的service已经是 spring提供的 现在要使用Dubbo提供的service注解

import com.alibaba.dubbo.config.annotation.Service

问题:案例中服务提供方和服务消费方里面都会存在HelloService接口,这样做是否合理?有没有更好的方法?

:这种做法不好,同一个接口复制了两份,放于两个服务中,不利于维护,更好的方式是单独创建一个maven工程,将接口全部放到这个maven工程中,需要依赖此接口的工程只需要在自己的pom.xml中引入坐标即可。

问题:在服务的消费方里面只是引用了HelloService接口,并没有实现类,那么Dubbo是如何实现远程调用的?

:Dubbo底层是基于代理技术为HelloService接口创建代理对象,远程调用时通过此代理对象完成的,可以通过开发工具的Debug功能查看此代理对象的内部结构,另外,Dubbo实现网络传输是基于Netty框架完成的。

问题:使用zookeeper作为服务的注册中心,默认单机版运行,如何防止zookeeper单点故障呢?

:zookeeper支持集群模式,可以配置zookeeper集群来达到zookeeper服务的高可用,防止单点故障的发生。

加入log4j日志

创建log4j.properties文件放于resources下,spring自动加载

### 设置###
log4j.rootLogger = debug, stdout

### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Threshold = DEBUG
log4j.appender.stdout.Target = System.err
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = C:/Users/Surpass/Desktop/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG 
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log 
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR 
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

Dubbo相关配置

包扫描


表示包扫描,作用是扫描改包下的所有了类,存在相关的注解。

如果不使用包扫描,可以通过配置的方式进行注册发布服务。

服务提供方:








服务消费方:







配置的方式只能进行单一的接口配置,如果有多个服务,那么就很繁琐了。

协议


相关协议的介绍请移步博客

作者:xiaojin21cen

名称:dubbo 支持的9种协议

文章地址:https://blog.csdn.net/xiaojin21cen/article/details/79834222

启动时检查


这个配置主要是用在服务的消费端,如果不配置则默认为true,Dubbo缺省会在启动的时候检查依赖的服务是否可用,不可用是会抛出异常,阻止Spring进行初始化完成,以便上线时,及时发现问题,可以通过将check的值修改为false关闭检查。

待上线时设置为true

负载均衡

Dubbo内置了4种负载均衡策略:

  1. RandomLoadBalance:随机负载均衡。随机的选择一个。是Dubbo的默认负载均衡策略。
  2. RoundRobinLoadBalance:轮询负载均衡。轮询选择一个。
  3. LeastActiveLoadBalance:最少活跃调用数,相同活跃数的随机。活跃数指调用前后计数差。使慢的 Provider 收到更少请求,因为越慢的 Provider 的调用前后计数差会越大。
  4. ConsistentHashLoadBalance:一致性哈希负载均衡。相同参数的请求总是落在同一台机器上。
//在服务消费方配置负载均衡
@Reference(check=false,loadbalance="random")
private HelloService helloService;

@ResponseBody
@RequestMapping("/say")
public String sayHello(String name){
    System.out.println("响应成功");
    return helloService.sayHello(name);
}

//在服务提供者配置负载均衡
@Service(loadbalance = "random")   //发布服务必须使用Dubbo提供的service注解
public class HelloServiceImpl implements HelloService {

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

更多负载均衡,请移步Dubbo官方文档:

http://dubbo.apache.org/zh-cn/blog/dubbo-loadbalance.html

这个案例里面,修改端口号来模拟多台并行的服务提供方,启动服务provider和consumer,访问consumer。

解决Dubbo无法发布被事务代理的service问题

如果在服务提供者注册的类上面添加事务注解@Transactinal事务控制后,发现服务就发布不成功了,原因是因为事务控制的底层原理是为服务提供者类创建代理对象,而默认情况下Spring是基于JDK动态代理方式创建代理对象,而代理对象的完成类名为com.sunproxy.$Proxy--(后面是数字),导致Dubbo在发布服务的时候进行包匹配匹配不到。

问题展示

使用dubbo坐标版本


    com.alibaba
    dubbo
    2.6.0


    com.alibaba
    druid
    1.1.9


    org.mybatis
    mybatis-spring
    2.0.4


     mysql
     mysql-connector-java
     5.1.40

在applicationContext-service.xml中添加事务管理器和连接池相关配置



    
    
    
    




    

    

然后在HelloServiceImpl类添加@Transactinal,完成后启动provider,在dubbo-admin中发现并没有服务提供者进行注册,只有一个服务消费者。

如果修改成cglib动态代理,回事什么样子?

修改配置applicationContext-service.xml


这样子就使用的是cglib代理。那么启动provider看到有注册信息。

但是它的注册信息是这样的。

org.springframework.aop.SpringProxy

这样子还是访问不到的。

解决方案

在之前的基础上,需要在注册服务类上添加注解参数。

@Service(interfaceClass = HelloService.class)   //发布服务必须使用Dubbo提供的service注解
@Transactional
public class HelloServiceImpl implements HelloService {

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

明确该服务实现的是HelloService.class的这个类,然后启动,查看dubbo-admin看结果,这时候发现provider注册的就是正确的接口服务了。

//服务
com.hkrt.service.HelloService
    
//服务地址
dubbo://ip:20880/com.hkrt.service.HelloService?anyhost=true&application=dubbo_provider&dubbo=2.6.0&generic=false&interface=com.hkrt.service.HelloService&methods=sayHello&pid=24892&side=provider×tamp=1603959532358

另述

前面到在问题展示那里,我指定了dubbo坐标的版本号是2.6.0,博主在这个案例中发现,2.6.0以上的版本,即使使用jdk动态代理,也是能够将被事务管理的服务接口注册到zookeeper上去,并且能够成功访问。

尾言

您的支持和鼓励是我最大的动力,麻烦动动您高贵的小手,点赞,评论和收藏,感谢!

你可能感兴趣的:(教自己学Dubbo)