分布式服务框架——Dobbo

Dubbo

Dubbo 最早是 Alibaba 开源的分布式服务框架,它最大的特点是按照分层的方式来架构, 使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。从服务模型的角度来看, Dubbo 采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所 以基于这一点可以抽象出服务提供方(Provider)和服务消费方(Consumer)两个角色。

服务架构角色

  • Container:服务运行框架,dubbo完全基于spring实现
  • Provider:提供远程调用服务
  • Registry:服务注册和发布中心
  • Consumer:执行远程调用服务
  • Monitor:统计服务调用次数和调用时间的监控中心

服务开启流程

  1. 启动spring容器Container时会把Provider启动
  2. 然后将Provider相关信息注册到Registry里
  3. Consumer从Registry中订阅Provider的信息
  4. Registry将Provider的信息发送给Consumer
  5. Consumer根据Registry通知的信息调用Provider中的方法
  6. Consumer和Provider将调用次数信息异步发送给Monitor统计

Dubbo支持的协议

Dubbo协议

  • 优点:采用 NIO 复用单一长连接,并使用线程池并发处理请求,减少握手和加大并发效率, 性能较好(推荐使用)
  • 缺点:大文件上传时,可能出现问题(不使用 Dubbo 文件上传)

RMI(Remote Method Invocation)协议

  • 优点:JDK自带的
  • 缺点:偶尔连接失败

Hessian协议

优点:可与原生Hessian互操作,基于HTTP协议
缺点:需hessian.jar支持,http短连接的开销大

Dubbo支持的注册中心

ZooKeeper

  • 优点:支持分布式,周边产品多
  • 缺点:受限于ZooKeeper软件的稳定性

Multicast

  • 优点:去中心化,不需单独安装软件
  • 缺点:Provider、Consumer、Registry不能跨机房(路由)

Redis

  • 优点:支持集群,性能高
  • 缺点:要求服务器时间同步,否则可能出现集群失败问题

Simple

  • 优点:标准RPC服务,没有兼容问题
  • 缺点:不支持集群

Dubbo应用

应用结构

  • parent:逻辑Maven工程,在pom文件中引入需要的依赖
  • api:继承parent工程,定义功能接口,以供provider实现,consumer调用
  • provider:继承parent工程,实现api中的接口功能
  • consumer:继承parent工程,调用api中的功能接口

创建Parent工程

  • pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.lanh</groupId>
    <artifactId>parent</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>api</module>
        <module>provider</module>
        <module>consumer</module>
    </modules>

    <properties>
        <spring.version>5.2.5.RELEASE</spring.version>
        <dubbo.version>2.7.6</dubbo.version>
        <curator.version>4.2.0</curator.version>
        <registry-zookeeper.version>2.7.6</registry-zookeeper.version>
        <servlet.version>3.1.0</servlet.version>
        <jsp.version>2.0</jsp.version>
        <jstl.version>1.2</jstl.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
            </dependency>

            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>${spring.version}</version>
            </dependency>

            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo</artifactId>
                <version>${dubbo.version}</version>
            </dependency>

            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-registry-zookeeper</artifactId>
                <version>${registry-zookeeper.version}</version>
            </dependency>

            <dependency>
                <groupId>org.apache.curator</groupId>
                <artifactId>curator-framework</artifactId>
                <version>${curator.version}</version>
            </dependency>

            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>${servlet.version}</version>
                <scope>provided</scope>
            </dependency>

            <dependency>
                <groupId>javax.servlet.jsp</groupId>
                <artifactId>jsp-api</artifactId>
                <version>${jsp.version}</version>
                <scope>provided</scope>
            </dependency>

            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jstl</artifactId>
                <version>${jstl.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.tomcat.maven</groupId>
                    <artifactId>tomcat7-maven-plugin</artifactId>
                    <version>2.2</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

</project>

创建api项目

创建功能接口

public interface DemoDubboService {
    String showMsg(String msg);
}

创建provider项目

  • 配置pom文件
<dependencies>
     <dependency>
         <groupId>com.lanh</groupId>
         <artifactId>api</artifactId>
         <version>1.0-SNAPSHOT</version>
     </dependency>

     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-context</artifactId>
     </dependency>

     <dependency>
         <groupId>org.apache.dubbo</groupId>
         <artifactId>dubbo</artifactId>
     </dependency>

     <dependency>
         <groupId>org.apache.dubbo</groupId>
         <artifactId>dubbo-registry-zookeeper</artifactId>
     </dependency>

     <dependency>
         <groupId>org.apache.curator</groupId>
         <artifactId>curator-framework</artifactId>
     </dependency>
 </dependencies>

注意:provider项目和consumer项目都要依赖api项目

  • 实现接口
package com.lanh.dubbo.service.impl;

import com.lanh.dubbo.service.DemoDubboService;
import org.apache.dubbo.config.annotation.Service;

/**
 * @Author Lanh
 **/
@Service
public class DemoDubboServiceImpl implements DemoDubboService {
    public String showMsg(String msg) {
        return "Helle Dubbo "+msg;
    }
}

需要注意的是,这里使用到的注解@Service不是spring中的注解,而是dubbo的注解

  • 编写启动类
package com.lanh.dubbo;

import org.apache.dubbo.container.Main;

/**
 * Dubbo的启动类
 * @Author Lanh
 **/
public class Start {
    public static void main(String[] args) {
        Main.main(args);
    }
}
  • 配置文件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://dubbo.apache.org/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://dubbo.apache.org/schema/dubbo
       http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!-- 定义服务名称 -->
    <dubbo:application name="myProvider" />

    <!--配置注册中心-->
    <dubbo:registry address="ip:2181,ip:2182,ip:2183" protocol="zookeeper" timeout="10000"/>

    <!--配置服务协议及监听端口(任意不被占用的端口)-->
    <dubbo:protocol name="dubbo" port="2002" />

<!--    &lt;!&ndash;注册接口&ndash;&gt;-->
<!--    <dubbo:service interface="com.lanh.dubbo.service.DemoDubboService" ref="demoService"/>-->
<!--    <bean id="demoService" class="com.lanh.dubbo.service.impl.DemoDubboServiceImpl" />-->

    <!--注解开发:扫描接口的位置的指定@Service-->
    <dubbo:annotation package="com.lanh.dubbo.service.impl" />

</beans>

注意:

  • 该配置文件必须放到resources/META-INF/spring/*.xml
  • 配置文件中配置注册中心时的ip,需要替换成自己zookeeper的ip
  • 在前面我有提及@Service注解,这个对应着是注解开发,另外一种xml开发的形式,我也以注释的形式写在了xml文件

创建consumer项目

web项目是在spring中不需要写启动类,是通过tomcat插件启动的

  • 定义Service接口
package com.lanh.service;

public interface DemoService {
    String showInfo(String msg);
}

  • 实现Service接口
package com.lanh.service.impl;

import com.lanh.dubbo.service.DemoDubboService;
import com.lanh.service.DemoService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;

/**
 * Consumer的业务层
 * @Author Lanh
 **/
@Service
public class DemoServiceImpl implements DemoService {

    @Reference
    private DemoDubboService demoDubboService;

    public String showInfo(String msg) {
        return this.demoDubboService.showMsg(msg);
    }
}

注意:

  • 这里使用到的@Service不同于provider,这个是spring框架的注解
  • 同时,这里进行注入时,因为这个不是本地的服务,使用的也不再是@Autowire注解,而是dubbo远程调用的@Reference注解
  • 页面跳转
package com.lanh.web.controller;

import com.lanh.service.DemoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author Lanh
 **/
@RestController
public class DemoController {

    @Autowired
    private DemoService demoService;

    @RequestMapping("/getMsg")
    public String getMsg(String str){
        return this.demoService.showInfo(str);
    }
}

  • 配置文件
    applicationContext-spring.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://dubbo.apache.org/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
    http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
    <!--配置服务名称-->
    <dubbo:application name="myConsumer" />
    <!--配置注册中心地址以及访问协议-->
    <dubbo:registry address="192.168.126.128:2181,192.168.126.128:2182,192.168.126.128:2183" protocol="zookeeper" timeout="10000"/>
    <!--dubbo扫描自己@Reference注解-->
    <dubbo:annotation package="com.lanh.service.impl"/>
</beans>

applicationContext-service.xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.lanh.service" />

</beans>

springmvc.xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.lanh.web.controller" />
    <mvc:annotation-driven/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/applicationContext-*.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/springmvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!--SpringMVC 中的编码过滤器-->
    <filter>
        <filter-name>encodeFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodeFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

SpringBoot整合

创建api,maven项目即可

设置功能接口

package com.lanh.dubbo.service;

public interface DemoDubboService {
    String showMsg(String str);
}

创建provider项目

  • 配置pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.lanh</groupId>
    <artifactId>springbootdubbo_provider</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springbootdubbo_provider</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.lanh</groupId>
            <artifactId>springbootdubbo_api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.6</version>
        </dependency>

        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-registry-zookeeper</artifactId>
            <version>2.7.6</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

  • 实现api的接口
package com.lanh.springbootdubbo_provider.service.impl;

import com.lanh.dubbo.service.DemoDubboService;
import org.apache.dubbo.config.annotation.Service;

/**
 * @Author Lanh
 **/

@Service
public class DemoDubboServiceImpl implements DemoDubboService {
    @Override
    public String showMsg(String str) {
        return "Hello Dubbo "+str;
    }
}

再说一次这个是@Service是dubbo的注解

  • 创建启动类
    springboot自带了启动类,不需要再使用dubbo的启动类
package com.lanh.springbootdubbo_provider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringbootdubboProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootdubboProviderApplication.class, args);
    }

}
  • 配置application.yml
#指定服务的名称
dubbo:
  application:
    name: myProvider
  registry:
    address: 192.168.126.128:2181,192.168.126.128:2182,192.168.126.128:2183
    protocol: zookeeper
    timeout: 10000
  #配置服务所使用的协议
  protocol:
    name: dubbo
    port: 2002
  scan:
    base-packages: com.lanh.springbootdubbo_provider.service.impl

创建consumer项目

  • 配置pom依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.lanh</groupId>
    <artifactId>springbootdubbo_consumer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springbootdubbo_consumer</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.lanh</groupId>
            <artifactId>springbootdubbo_api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>

        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.6</version>
        </dependency>

        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-registry-zookeeper</artifactId>
            <version>2.7.6</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

  • 定义Service接口
package com.lanh.springbootdubbo_consumer.service;

public interface DemoService {
    String getMsg(String str);
}

  • 实现Service接口
package com.lanh.springbootdubbo_consumer.service.impl;

import com.lanh.dubbo.service.DemoDubboService;
import com.lanh.springbootdubbo_consumer.service.DemoService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;

/**
 * @Author Lanh
 **/

@Service
public class DemoServiceImpl implements DemoService {

    @Reference
    private DemoDubboService demoDubboService;

    @Override
    public String getMsg(String str) {
        return this.demoDubboService.showMsg(str);
    }
}

再说一次:这个@Service是spring中的注解,用@Reference而不用@Autowire

  • 配置页面跳转逻辑
package com.lanh.springbootdubbo_consumer.controller;

import com.lanh.springbootdubbo_consumer.service.DemoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author Lanh
 **/

@RestController
public class DemoController {

    @Autowired
    private DemoService demoService;

    @RequestMapping("/getMsg")
    public String getMsg(String str){
        return this.demoService.getMsg(str);
    }
}
  • springboot的启动类
package com.lanh.springbootdubbo_consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringbootdubboConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootdubboConsumerApplication.class, args);
    }
}
  • 配置application.yml
#指定服务的名称
dubbo:
  application:
    name: myConsumer
  registry:
    address: 192.168.126.128:2181,192.168.126.128:2182,192.168.126.128:2183
    protocol: zookeeper
    timeout: 10000
  #配置服务所使用的协议
  protocol:
    name: dubbo

至此结束,欢迎各位小伙伴讨论

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

绿豆蛙给生活加点甜

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

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

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

打赏作者

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

抵扣说明:

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

余额充值