分布式服务dubbo

15 篇文章 1 订阅
1 篇文章 0 订阅

第九章 Dubbo

1. Dubbo的发展背景

随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fExrWkHq-1602494371674)(https://ae01.alicdn.com/kf/H8d8556092f7b4d59921529a161412470O.png)]

1.1 单一应用架构

当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。 此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。使用一个web容器(如tomcat),然后使用Servlet/JSP技术,最后选择一个合适数据库管理系统来存储数据(MySQL、Oracle)。

1.2 垂直应用架构

当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,提升效率的方法之一是将应用拆成互不相干的几个应用,以提升效率。

此时,用于加速前端页面开发的Web框架(MVC)是关键。

用户系统、权限系统、商品系统、订单系统、物流系统…

特点:系统独立部署,每一个系统都有完整的前后端;

问题:各个系统无法做到完全独立,公共模块无法复用,系统之间通信比较麻烦;

1.3 分布式服务架构

作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。

分布式架构的难点

  1. 各个系统如何进行远程调用
  2. 如何进行业务拆分

1.4 流动计算架构

当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。

2.RPC

RPC(Remote Procedure Call)- 远程过程调用,它是一种通过网络从远程计算机程序上请求服务,不需要了解底层的网络技术协议。RPC假定某种传输协议的存在(如TCP),为通信程序携带数据;通俗的说,RPC可以让我们像调用本地方法一样调用远程计算机提供的服务;

2.1 RPC简单原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MiZ7OC2C-1602494371684)(https://ae01.alicdn.com/kf/Hf87aef8fc1314dd696b626b9d9a99551s.png)]

  1. 客户端以本地调用的方式调用远程服务
  2. client stub接收到调用后,将方法、参数等组装成能够进行网络传输的消息;
  3. client stub查找服务地址,找到之后,将消息发送到服务端;
  4. server stub收到消息之后,对收到的消息进行解码;
  5. server stub根据解码结果,使用反射的方式调用本地服务;
  6. 服务端执行完成之后将结果返回给Server stub;
  7. server stub将返回结果打包成消息并发送给客户端;
  8. client stub收到消息后,对结果进行解码;

3. Dubbo

Apache Dubbo是一款高性能的 Java RPC框架

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

3.1 Dubbo架构

1. 架构中的角色
  • Provider :服务提供者
  • Consumer :服务消费者
  • Registry :服务注册和发现的中心
  • Monitor :监控中心,用于统计服务调用情况
  • Container : Dubbo的容器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V6RtSRDw-1602494371688)(https://ae02.alicdn.com/kf/Ha1e1718a05e545e5bcec9f268fa807adK.png)]

2. 调用关系
  1. 容器负责启动、加载、运行服务提供者、消费者
  2. 服务提供者在启动时,向注册中心注册自己提供的服务
  3. 服务消费者在启动时,向注册中心订阅自己需要的服务
  4. 注册中心返回服务提供者的地址列表给消费者,如果有服务变更(服务的上线和下线),注册中心会基于长连接的方式推送变更过给消费者
  5. 服务这从地址列表中,基于**软件负载聚恒算法**,选择一个服务提供者进行调用,如果调用失败,可以重试其他提供者。
  6. 服务消费者和提供者,在内存中累计调用时间和调用次数,每分钟向监控中心发送一次统计数据。

4. 安装单机Zookeeper

4.1 windows 版本

  1. 解压zookeeper-3.4.12.tar.gz 到当前目录

  2. 在 zookeeper-3.4.12 目录下创建 data 目录

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xySseaGU-1602494371693)(https://ae01.alicdn.com/kf/H2265729af51e43498cd2b848e6bc545d0.png)]

  3. zookeeper-3.4.12/conf 目录下的 zoo_sample.cfg 文件重命名为 zoo.cfg[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jqI0pNVm-1602494371696)(https://ae03.alicdn.com/kf/Hebfa5db0720a4650805653e83f2a2049v.png)]

  4. 修改 zoo.cfg 文件中的 dataDir 选项

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3pC4AbTc-1602494371698)(https://ae01.alicdn.com/kf/H2b2484131b324d4caf53959d68115e53U.png)]

  5. 双击 zookeeper-3.4.12/bin/zkServer.cmd ,启动服务端

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3yFXrDCS-1602494371699)(https://ae01.alicdn.com/kf/He0fb1d817ff34bb28eefb34ca85879b5C.png)]

  1. 双击 zookeeper-3.4.12/bin/zkCli.cmd ,启动客户端

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hy4IYze9-1602494371701)(https://ae04.alicdn.com/kf/H23c84676e2e8495f83ebc63f731e9b002.png)]

4.2 Linux / Mac 版本

  1. zookeeper-3.4.12.tar.gz 上传到 /opt 目录
#在压缩包目录上 运行git bash
scp zookeeper-3.4.12.tar.gz root@ip:/opt
#解压 压缩包
cd /opt
tar -zxvf zookeeper-3.4.12.tar.gz -C /opt
#创建软连接
ln -s zookeeper-3.4.12.tar.gz zookeeper
  1. 进入zookeeper 创建data 目录
cd zookeeper
mkdir data
  1. 进入zookeeper-3.4.12.tar.gz/conf目录下,将zoo_sample.cfg修改为zoo.cfg
cd conf
mv zoo_sample.cfg zoo.cfg
  1. 编辑zoo.cfg
vim zoo.cfg
# 输入12GA 将dataDir修改为 ../data
  1. 启动zookeeper服务
cd ../bin
./zkServer.sh start
  1. 启动ZK客户端
./zkCli.sh

5. Dubbo控制台安装

  1. dubbo主要用于服务治理

  2. 可以通过控制台查看所有服务

  3. 可以设置负载均衡、权重调节、服务降级策略等

    #控制台默认访问地址
    http://localhost:7001
    #默认的用户名和密码
    root / root
    
  4. 在dubbo-admin.jar 所在的目录运行 cmd

    java -jar dubbo-admin.jar 即可
    

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-71B7loOM-1602494371703)(https://ae02.alicdn.com/kf/H8098147f09e64c52bf8b0ce501b16a0cJ.png)]

6. dubbo普通工程

6.1创建maven父工程 dubbo-hello

  1. 引入maven依赖
<dependencyManagement>
    <dependencies>
        <!-- Dubbo -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.6.5</version>

            <exclusions>
                <!-- 排除低版本(4.3.16)的spring-context -->
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- 引入高版本的spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>

        <!-- curator: zk客户端 -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.13.0</version>
        </dependency>
    </dependencies>
</dependencyManagement>

6.2 创建子工程服务接口 dubbo-hello-interface

  1. 创建服务接口
/**
 * 服务接口
 *
 * 服务提供者实现这个接口 提供服务
 * 消费者引用这个接口 消费服务
 */
public interface HelloService {
    String sayHello(String name);
}
  1. 创建本地存根,[暂时这个工程不需要]
/*
 *使用本地存根需要在服务接口的包下创建 [接口名字]Stub类
 *继承自[接口名字]类
 */
package com.etoak.service;

public class HelloServiceStub implements HelloService{
    HelloService helloService;

    public HelloServiceStub(HelloService helloService) {
        this.helloService = helloService;
    }

    @Override
    public String sayHello(String name) {
        if(name != null && !"".equals(name) ){
           return helloService.sayHello(name);
        }
        return "参数异常";
    }
}

6.3 创建消息提供者 [dubbo-hello-provider]

  1. 引入maven依赖
<dependencies>
    <!-- 服务提供者引入接口功能,用于实现服务接口-->
    <dependency>
        <artifactId>dubbo-hello-interface</artifactId>
        <groupId>com.etoak.et1912.dubbo</groupId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <!-- Dubbo -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo</artifactId>
    </dependency>

    <!-- 引入高版本的spring-context -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
    </dependency>

    <!-- curator: zk客户端 -->
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-framework</artifactId>
    </dependency>
</dependencies>
  1. 配置provider.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">
    <!--1.配置应用名称-->
    <dubbo:application name="hello-provider" ></dubbo:application>
    <!--2.配置zookeeper注册中心-->
    <dubbo:registry address="zookeeper://127.0.0.1:2181" ></dubbo:registry>
    <!--3.使用dubbo协议在20880端口暴露服务-->
    <dubbo:protocol name="dubbo" port="20880" />
    <!--4.暴露服务,也就是向注册中心注册服务-->
    <dubbo:service interface="com.etoak.service.HelloService" ref="helloService" stub="true"/>
    <!--5.配置服务实现-->
    <bean id="helloService" class="com.etoak.service.HelloServiceImpl" ></bean>
</beans>
  1. 书写服务提供类
package com.etoak.service;
public class HelloServiceImpl implements HelloService{
    @Override
    public String sayHello(String name) {
        return String.format("Hello %s",name);
    }
}
  1. 书写测试类
package com.etoak.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

public class ProviderMain {
    public static void main(String[] args) throws IOException {
        new ClassPathXmlApplicationContext("provider.xml");
        System.in.read();
    }
}
  1. 运行测试类即可在测试端或者网页管理器中查看到注册的服务

    • 在客户端查看已经注册的服务
    ls /dubbo
    ls /dubbo/[service name]
    ls /dubbo/[service name]/provider
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NMkZohIW-1602494371705)(https://ae02.alicdn.com/kf/Hb8b621867fa145b3b3fc9b112c71b8ecY.png)]

    • 在浏览器查看消息提供者

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NxbkRqXP-1602494371706)(https://ae02.alicdn.com/kf/He5fd4a7a4e054e88b5ee1507fffcab2fG.png)]

6.4 创建消息消费者 [dubbo-hello-consumer]

  1. 引入maven依赖
<dependencies>
    <!-- 服务提供者引入接口功能,用于实现服务接口-->
    <dependency>
        <artifactId>dubbo-hello-interface</artifactId>
        <groupId>com.etoak.et1912.dubbo</groupId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <!-- Dubbo -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo</artifactId>
    </dependency>

    <!-- 引入高版本的spring-context -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
    </dependency>

    <!-- curator: zk客户端 -->
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-framework</artifactId>
    </dependency>
</dependencies>
  1. 配置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://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">
    <!--1.配置应用名称-->
    <dubbo:application name="hello-consumer" />
    <!--2.向注册中心订阅服务-->
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />
    <!--3.引用远程服务,创建服务代理-->
    <dubbo:reference id="helloService" interface="com.etoak.service.HelloService"></dubbo:reference>

</beans>
  1. 创建消费者
package com.etoak.test;

import com.etoak.service.HelloService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

public class ConsumerMain {
    public static void main(String[] args) throws IOException {
        ApplicationContext ioc = new ClassPathXmlApplicationContext("consumer.xml");
        //获取远程服务的代理对象
        HelloService helloService = ioc.getBean(HelloService.class);
        String result = helloService.sayHello("");
        System.out.println(result);

        System.in.read();
    }

}
  1. 在控制端和网页端查看消费者
  • 在控制端查看

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aLI99lem-1602494371708)(https://ae04.alicdn.com/kf/H3213ad17eb8a4e3e94d527ee35823a7aG.png)]

  • 在网页端查看

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XuZ1SEvW-1602494371710)(https://ae04.alicdn.com/kf/H372640990885404a8d64a2170a9fabf7g.png)]

7. dubbo 整合 springmvc

7.1 创建父工程[dubbo-mvc]

  1. 创建maven工程 dubbo-mvc,并引入maven依赖
<dependencyManagement>
    <dependencies>
        <!-- servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <!-- spring-web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>
        <!-- spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>
        <!-- spring-context-support -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>
        <!-- spring-jdbc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>
        <!-- spring-tx -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>

        <!-- thymeleaf -->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf</artifactId>
            <version>3.0.11.RELEASE</version>
        </dependency>
        <!-- thymeleaf-spring5 -->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
            <version>3.0.11.RELEASE</version>
        </dependency>

        <!-- jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.5</version>
        </dependency>

        <!-- mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>
        <!-- druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>
        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
        <!-- myabtis-spring -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.1</version>
        </dependency>

        <!-- pageHelper -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.1.10</version>
        </dependency>

        <!-- dubbo相关依赖 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.6.5</version>
            <exclusions>
                <!-- 剔除低版本的spring-context -->
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.13.0</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.spring</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>1.0.2</version>
        </dependency>

        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
            <scope>provided</scope>
        </dependency>

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

7.2 创建 Bean工程

  1. 创建普通maven 工程引入lombok依赖
<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

7.3 创建服务接口[dubbo-mvc-interface]

  1. 引入bean工程依赖
<dependencies>
    <!--依赖bean工程-->
    <dependency>
        <artifactId>dubbo-mvc-bean</artifactId>
        <groupId>com.etoak.et1912.dubbo</groupId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

7.4 创建服务提供者[dubbo-mvc-provider]

  1. 引入maven依赖
javax.servlet-api
spring-web
spring-context-support(spring框架的)

spring-tx
spring-jdbc
mysql
mybatis
mybatis-spring
druid
pagehelper
logback-classic

dubbo
curator-framework
spring-context-support(alibaba的)
  1. 配置web.xml文件
<!-- 这里只整合了spring-web,没有整合spring-webmvc,
     只需要配置spring容器即可 -->
<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath:spring-root.xml</param-value>
</context-param>

<listener>
  <listener-class>
    org.springframework.web.context.ContextLoaderListener
  </listener-class>
</listener>
  1. 开发用户服务接口

​ 在interface工程开发UserService接口

  1. 发布用户服务到zk
<!-- 配置Dubbo -->
<dubbo:annotation package="com.etoak" />
<dubbo:application name="user-service" />
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<dubbo:protocol name="dubbo" port="20880" />
package com.etoak.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.etoak.bean.User;
import com.etoak.mapper.UserMapper;
import com.etoak.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * dubbo提供的@Service注解:用于发布Dubbo服务
 */
@Service
public class UserServiceImpl implements UserService {

  private static final Logger LOG =
   LoggerFactory.getLogger(UserServiceImpl.class);
    
  @Autowired
  UserMapper userMapper;

  @Override
  public User getById(Integer id) {
    LOG.info("param id - {}", id);
    User user = userMapper.getById(id);
    LOG.info("result - {}", user);
    return user;
  }
}
  1. 测试

1、先启动注册中心、dubbo控制台(可选)

2、再启动服务提供者

3、再启动服务消费者

4、开始测试

7.5 创建服务消费者[dubbo-mvc-consumer]

  1. 引入maven依赖
<dependencies>
    <!--servlet-api-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
    </dependency>
    <!--spring-webmvc-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
    </dependency>
    <!--spring:spring-context-support-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
    </dependency>
    <!--thymeleaf-->
    <dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf</artifactId>
    </dependency>
    <!--thymeleaf-spring5-->
    <dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf-spring5</artifactId>
    </dependency>
    <!--jackson-databind-->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>
    <!--logback-->
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
    </dependency>
    <!--lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    <!--dubbo-->
</dependencies>
  1. 配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <!--过滤器-->
    <filter>
        <filter-name>encoding</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>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!--前端控制器-->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>
  1. 配置spring-mvc容器

注意:address后边的地址一定不要写错,不然就报错

<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<?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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-4.2.xsd
	http://www.springframework.org/schema/mvc
	http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd">

    <!--1. 开启注解扫描-->
    <context:component-scan base-package="com.etoak">

        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.RestController"/>
        <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>

        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>

    </context:component-scan>
    <!--2.开启mvc配置-->
    <mvc:annotation-driven></mvc:annotation-driven>
    <!--3.静态文件处理-->
    <mvc:default-servlet-handler />
    <!--4.thymeleaf三个配置-->
    <!--4.1 SpringResourceTemplateResolver-->
    <bean id="templateResolver" class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
        <property name="prefix" value="/templates/" />
        <property name="suffix" value=".html" />
        <property name="templateMode" value="HTML" />
        <property name="characterEncoding" value="UTF-8" />
        <property name="cacheable" value="false" />
    </bean>
    <!--4.2 SpringTemplateEngine-->
    <bean id="templateEngine" class="org.thymeleaf.spring5.SpringTemplateEngine">
        <property name="templateResolver" ref="templateResolver" />
    </bean>
    <!--4.3 ThymeleafViewResolver-->
    <bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
        <property name="templateEngine" ref="templateEngine" />
        <property name="characterEncoding" value="UTF-8" />
    </bean>
    <!--dubbo配置-->
     <dubbo:annotation package="com.etoak" />
    <dubbo:application name="mvc-consumer" />
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />
</beans>
  1. 创建控制器测试
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/index")
    public String index(){
        return "index";
    }
}

8.Dubbo详解

8.1 Dubbo在ZK中的存储结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hEAEUmtS-1602494371713)(https://ae04.alicdn.com/kf/H1a6dfd8de43b4b0b84107a34c5a469caA.png)]

8.2 Dubbo的注册中心有哪些

1、Multicast:Multicast 注册中心不需要启动任何中心节点,只要广播地址一样,就可以互相发现。

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

3、Nacos 是 Dubbo 生态系统中重要的注册中心实现,其中 dubbo-registry-nacos 则是 Dubbo 融合 Nacos 注册中心的实现。

4、基于 Redis 实现的注册中心 。

5、Simple注册中心本身就是一个普通的 Dubbo 服务,可以减少第三方依赖,使整体通讯方式一致。

8.3 Dubbo支持的协议

dubbo、rmi、hessian、http、webservice、rest、thrift、memcached、redis、grpc

Dubbo官方推荐使用 dubbo协议

8.4 启动时检查

​ Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,以便上线时,能及早发现问题,默认 check="true"

8.4.1 关闭注册中的启动检查
<dubbo:registry check="false"
	address="zookeeper://127.0.0.1:2181" />
8.4.2 关闭单个服务的启动检查
<dubbo:reference id="helloService" 
	check="false"
	interface="com.etoak.service.HelloService">
</dubbo:reference>
8.4.3 关闭所有服务的启动检查
<dubbo:consumer check="false" />

8.5 配置加载流程

文档地址

8.5.1 配置来源

首先,从Dubbo支持的配置来源说起,默认有四种配置来源:

  • JVM System Properties,-D参数(配置虚拟机参数)
  • Externalized Configuration,外部化配置(外部配置中心)
  • ServiceConfig、ReferenceConfig等编程接口采集的配置
  • 本地配置文件dubbo.properties(dubbo.properties需要放在classpath根路径下)
8.5.2 配置加载优先级

jvm参数 > 外部化配置 > api编程配置、spring配置 > dubbo.properties

idea中jvm配置

image.png

8.6 XML配置 - 不同粒度配置的覆盖关系

​ 以 timeout 为例,下图显示了配置的查找顺序,其它 retries, loadbalance, actives 等类似:

  • 方法级优先,接口级次之,全局配置再次之。

    方法级配置项:<dubbo:method>

    接口级配置项:<dubbo:service><dubbo:reference>

    全局级配置项:<dubbo:provider><dubbo:consumer>

  • 如果级别一样,则消费方优先,提供方次之。

其中,服务提供方配置,通过 URL 经由注册中心传递给消费方。

image.png

8.7 直连提供者

​ 在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,点对点直连方式,将以服务接口为单位,忽略注册中心的提供者列表,A 接口配置点对点,不影响 B 接口从注册中心获取列表。

<dubbo:reference id="helloService"
  url="dubbo://127.0.0.1:20880"
  interface="com.etoak.service.HelloService">
</dubbo:reference>

8.8 本地存根

​ 提供方有些时候想在客户端也执行部分逻辑,比如:做 ThreadLocal 缓存,提前验证参数,调用失败后伪造容错数据等等

  • 实现步骤

    1、在服务接口包中创建一个HelloServiceStub类,实现HelloService接口

    2、需要提供一个构造方法,构造方法的参数就是HelloService的远程代理对象

    3、在spring中配置本地存根

    <dubbo:service ref="helloService"
    stub="true"
    interface="com.etoak.service.HelloService">
    </dubbo:service>
    
    <dubbo:service ref="helloService"
    stub="com.etoak.service.HelloServiceStub"
    interface="com.etoak.service.HelloService">
    </dubbo:service>
    

8.9 服务分组

​ 当一个接口有多种实现时,可以用 group 区分。

8.10 服务的多版本

​ 当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。

​ 可以按照以下的步骤进行版本迁移:

  1. 在低压力时间段,先升级一半提供者为新版本
  2. 再将所有消费者升级为新版本
  3. 然后将剩下的一半提供者升级为新版本

8.11 负载均衡 LoadBalance

​ 在集群负载均衡时,Dubbo 提供了多种均衡策略,默认是 random 随机调用。

1. Random LoadBalance
随机,按权重设置随机概率。
在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。

2. RoundRobin LoadBalance
轮询,按公约后的权重设置轮询比率。
存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。

3. LeastActive LoadBalance
最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差
使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。

4. ConsistentHash LoadBalance
一致性 Hash,相同参数的请求总是发到同一提供者
当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
算法参见:http://en.wikipedia.org/wiki/Consistent_hashing
默认只对第一个参数 Hash,如果要修改,请配置:<dubbo:parameter key=“hash.arguments” value=“0,1” />
默认用 160 份虚拟节点,如果要修改,请配置 <dubbo:parameter key=“hash.nodes” value=“320” />

控制台配置

image.png

8.12 服务降级

​ 可以通过服务降级功能临时屏蔽某个出错的非关键服务,并定义降级后的返回策略。

  • mock=force:return+null 表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
  • 还可以改为 mock=fail:return+null 表示消费方对该服务的方法调用失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。

控制台配置

image.png

9.dubbo整合spring问题

为什么引入dubbo之后就会找不到spring-root容器

Dubbo开发者不确定使用者使用什么mvc框架,如果使用者使用的是struts,那么系统中是没有spring mvc容器的,这个时候只能去spring root容器中查找配置了,所以Dubbo默认的是查找一定会存在的spring root 容器。

X.错误集锦

  1. Caused by: java.lang.NumberFormatException: For input string: “127.0.0.1:2181”

引发原因:dubbo整合spring mvc时连接写错了

解决办法:address后边的url一定要书写正确

 <dubbo:registry address="zookeeper://127.0.0.1:2181" />
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值