Dubbo

  • 1. dubbo概述
    • 1.1 什么是分布式系统
      • 1.1.1 单一应用架构
      • 1.1.2 垂直应用架构
      • 1.1.3 分布式服务架构
      • 1.1.4 流动计算架构
    • 1.2 Dubbo简介
      • 1.2.1 RPC
      • 1.2.2 节点角色
      • 1.2.3 调用关系
  • 2. 快速入门
    • 2.1 注册中心
      • 2.1.1 Zookeeper
      • 2.1.2 安装
    • 2.2 服务提供方
      • 2.2.1 服务方的pom.xml
      • 2.2.2 服务方接口
      • 2.2.3 服务方实现
      • 2.2.4 服务方的配置文件spring.xml
      • 2.2.5 服务方的web.xml
    • 2.3 服务消费方
      • 2.3.1 消费方的pom.xml
      • 2.3.2 消费方的Controller
      • 2.3.3 消费方的接口
      • 2.3.4 消费方的web.xml
      • 2.3.5 消费方的springmvc.xml
    • 2.4 启动服务测试
  • 3. 监控中心
    • 3.1 服务管理端
      • 3.1.1 安装管理端
      • 3.2.1 管理端使用
    • 3.2 监控统计中心
  • 4. 综合实战
    • 4.1 配置说明
      • 4.1.1 启动时检查
      • 4.1.2 超时时间
      • 4.1.3 重试次数
      • 4.1.4 多版本
      • 4.1.5 本地存根
      • 4.1.6 序列化
      • 4.1.7 地址缓存
    • 4.2 负载均衡策略
    • 4.3 高可用
      • 4.3.1 zookeeper宕机
    • 4.4 服务降级
      • 4.4.1 为什么要服务降级
      • 4.4.2 服务降级实现方式
    • 4.5 整合MyBatis实现用户注册
      • 4.5.1 初始化数据库
      • 4.5.2 创建聚合项目-项目模块化
      • 4.5.3 启动测试

1. dubbo概述

1.1 什么是分布式系统

  • 《分布式系统原理与范型》定义:

    • “分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统”
    • 分布式系统(distributed system)是建立在网络之上的软件系统。
    • 简单来说:多个(不同职责)人共同来完成一件事!
    • 任何一台服务器都无法满足淘宝的双十一的数据吞吐量,一定是很多台服务器公共来完成的。
  • 歇后语:“三个臭皮匠赛过诸葛亮”,就是分布式系统的真实写照

1.1.1 单一应用架构

  • 当网站流量很小时,只需要一个应用,将所有的功能部署到一起(所有业务都放在一个tomcat里),从而减少部署节点和成本;

  • 此时,用于简化 增删改查 工作量的数据访问框架 (ORM)是关键;

  • 例如:某个超市的收银系统,某个公司的员工管理系统

    ORM:对象关系映射(Object Relational Mapping)

  • 优点

    • 小项目开发快 成本低
    • 架构简单
    • 易于测试
    • 易于部署
  • 缺点

    • 大项目模块耦合严重 不易开发 维护 沟通成本高
    • 新增业务困难
    • 核心业务与边缘业务混合在一块,出现问题互相影响

1.1.2 垂直应用架构

  • 当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成几个互不相干的几个应用,以提高效率;
  • 大模块按照mvc分层模式,进行拆分成多个互不相关的小模块,并且每个小模块都有独立的服务器
  • 此时,用于加速前端页面开发的web框架(MVC)是关键;因为每个小应用都有独立的页面

    MVC:模型视图控制器 (Model View Controller)
  • 缺点:
    • 模块之间不可能完全没有交集,公用模块无法重复利用,开发性的浪费

1.1.3 分布式服务架构

  • 当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的业务,逐渐形成稳健的服务中心,使前端应用能更快速的响应多变的市场需求;
  • 此时,用户提高业务复用及整合的分布式服务框架(RPC)远程调用是关键;

RPC:独立的应用服务器之间,要依靠RPC(Romote Procedure Call)才能调用

  • 物流服务不忙,有100台服务器; 商品服务特别忙,也是100台服务器;

    • 如何做到资源优化调配

1.1.4 流动计算架构

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

    SOA:面向服务架构(Service-Oriented Architecture),简单理解就是“服务治理”,例如:公交车站的“调度员”


1.2 Dubbo简介

  • Dubbo是分布式服务框架,是阿里巴巴的开源项目,现交给apache进行维护
  • Dubbo致力于提高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案
  • 简单来说,dubbo是个服务框架,如果没有分布式的需求,是不需要用的

1.2.1 RPC

  • RPC【Remote Procedure Call】是指远程过程调用,是一种进程间通信方式
  • RPC基本的通信原理
  1. 在客户端将对象进行序列化
  2. 底层通信框架使用netty(基于tcp协议的socket),将序列化的对象发给服务方提供方
  3. 服务提供方通过socket得到数据文件之后,进行反序列化,获得要操作的对象
  4. 对象数据操作完毕,将新的对象序列化,再通过服务提供方的socket返回给客户端
  5. 客户端获得序列化数据,再反序列化,得到最新的数据对象,至此,完成一次请求

  • RPC两个核心模块:通讯(socket),序列化。

1.2.2 节点角色

节点 角色说明
Provider 服务的提供方(洗浴中心)
Consumer 服务的消费方(客人)
Registry 服务注册与发现的注册中心(便民服务中心,所有的饭店娱乐场所都在已在本中心注册)
Monitor 监控服务的统计中心(统计服务被调用的次数)
Container 服务运行容器(烧烤一条街,洗浴一条街)

1.2.3 调用关系

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

2. 快速入门

http://dubbo.apache.org/

2.1 注册中心

2.1.1 Zookeeper

  • 官方推荐使用zookeeper注册中心;
  • 注册中心负责服务地址的注册与查找,相当于目录服务;
  • 服务提供者和消费者只在启动时与注册中心交互,注册中不转发请求,压力较小;
  • Zookeeper是apache hadoop的子项目,是一个树形的目录服务,支持变更推送,适合作为dubbo的服务注册中心,工业强度较高,可用于生产环境;

dubbo即是求职的人,也是招聘单位,而zookeeper就是人才市场/招聘网站;

2.1.2 安装

1、安装jdk
2、拷贝apache-zookeeper-3.6.0-bin.tar.gz到opt目录
3、解压安装包

[root@localhost opt]# tar -zxvf apache-zookeeper-3.6.0-bin.tar.gz

4、重命名

[root@localhost opt]# mv apache-zookeeper-3.6.0-bin zookeeper

5、在/opt/zookeeper/这个目录上创建zkData和zkLog目录

[root@localhost zookeeper]# mkdir zkData
[root@localhost zookeeper]# mkdir zkLog

6、进入/opt/zookeeper/conf这个路径,复制一份zoo_sample.cfg 文件并命名为 zoo.cfg

[root@localhost conf]# cp zoo_sample.cfg zoo.cfg

7、编辑zoo.cfg文件,修改dataDir路径:

dataDir=/opt/zookeeper/zkData
dataLogDir=/opt/zookeeper/zkLog

8、启动Zookeeper

[root@localhost bin]# ./zkServer.sh start

9、查看状态:

[root@localhost bin]# ./zkServer.sh status

2.2 服务提供方

1、一个空的maven项目
2、提供一个服务接口即可

2.2.1 服务方的pom.xml

各种依赖请严格按照下面的版本

<packaging>war</packaging>
<properties><spring.version>5.0.6.RELEASE</spring.version>
</properties>
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>${spring.version}</version></dependency><!--dubbo --><dependency><groupId>com.alibaba</groupId><artifactId>dubbo</artifactId><version>2.5.7</version></dependency><dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.4.6</version></dependency><dependency><groupId>com.github.sgroschupf</groupId><artifactId>zkclient</artifactId><version>0.1</version></dependency><dependency><groupId>javassist</groupId><artifactId>javassist</artifactId><version>3.11.0.GA</version></dependency>
</dependencies>
<build><plugins><plugin><groupId>org.apache.tomcat.maven </groupId><artifactId>tomcat7-maven-plugin</artifactId><configuration><port>8001</port><path>/</path></configuration><executions><execution><!-- 打包完成后,运行服务 --><phase>package</phase><goals><goal>run</goal></goals></execution></executions></plugin></plugins>
</build>

2.2.2 服务方接口

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

2.2.3 服务方实现

@com.alibaba.dubbo.config.annotation.Service
public class HelloServiceImpl implements HelloService {@Overridepublic String sayHello(String name) {return "Hello," + name + "!!!";}
}

2.2.4 服务方的配置文件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://code.alibabatech.com/schema/dubbo"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
"><!--1.服务提供方在zookeeper中的“别名”--><dubbo:application name="dubbo-server"/><!--2.注册中心的地址--><dubbo:registry address="zookeeper://192.168.204.141:2181"/><!--3.扫描类(将什么包下的类作为服务提供类)--><dubbo:annotation package="service.impl"/>
</beans>

2.2.5 服务方的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://xmlns.jcp.org/xml/ns/javaee"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"id="WebApp_ID" version="3.1"><listener>  <listenerclass>org.springframework.web.context.ContextLoaderListener</listener-class></listener><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/spring.xml</param-value></context-param>
</web-app>

2.3 服务消费方

2.3.1 消费方的pom.xml

与服务方一致,只需要修改tomcat的端口为8002

2.3.2 消费方的Controller

@RestController
public class HelloAction {@com.alibaba.dubbo.config.annotation.Referenceprivate HelloService hs;@RequestMapping("hello")@ResponseBodypublic String hello( String name){return hs.sayHello(name);}
}

2.3.3 消费方的接口

注意
controller中要依赖HelloService,所以我们创建一个接口;
这里是消费方,不需要实现,因为实现会让服务方为我们搞定!

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

2.3.4 消费方的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://xmlns.jcp.org/xml/ns/javaee"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"id="WebApp_ID" version="3.1"><servlet><servlet-name>springmvc</servlet-name><servletclass>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/spring.xml</param-value></init-param></servlet><servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/</url-pattern></servlet-mapping>
</web-app>

2.3.5 消费方的springmvc.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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd"><!--Dubbo的应用名称,通常使用项目名 --><dubbo:application name="dubbo-consumer" /><!--配置Dubbo的注册中心地址 --><dubbo:registry address="zookeeper://192.168.204.141:2181" /><!--配置Dubbo扫描类,将这个类作为服务进行发布 --><dubbo:annotation package="controller" />
</beans>

2.4 启动服务测试

首先启动服务方,再启动消费方。
访问:http://localhost:8002/hello?name=james

3. 监控中心

我们在开发时,需要知道注册中心都注册了哪些服务,以便我们开发和测试。
图形化显示注册中心的中 服务列表
我们可以通过部署一个web应用版的管理中心来实现。

  • 公共接口----dubbo-interface
package com.itheima.service;public interface UserService {public String sayHello();
}
  • service----dubbo-service
    pom.xml
<?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.itheima</groupId><artifactId>dubbo-service</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><spring.version>5.1.9.RELEASE</spring.version><dubbo.version>2.7.4.1</dubbo.version><zookeeper.version>4.0.0</zookeeper.version></properties><dependencies><!-- servlet3.0规范的坐标 --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><!--spring的坐标--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><!--springmvc的坐标--><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><!--日志--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.21</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.21</version></dependency><!--Dubbo的起步依赖,版本2.7之后统一为rg.apache.dubb --><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo</artifactId><version>${dubbo.version}</version></dependency><!--ZooKeeper客户端实现 --><dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>${zookeeper.version}</version></dependency><!--ZooKeeper客户端实现 --><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>${zookeeper.version}</version></dependency><!--依赖公共的接口--><dependency><groupId>com.itheima</groupId><artifactId>dubbo-interface</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies><build><plugins><!--tomcat插件--><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.1</version><configuration><port>9000</port><path>/</path></configuration></plugin></plugins></build></project>

web.xml----webapp/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"version="2.5"><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>
</web-app>

log4j.properties

# DEBUG < INFO < WARN < ERROR < FATAL
# Global logging configuration
log4j.rootLogger=info, stdout,file
# My logging configuration...
#log4j.logger.com.tocersoft.school=DEBUG
#log4j.logger.net.sf.hibernate.cache=debug
## Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p %d %C: %m%nlog4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=../logs/iask.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}  %l  %m%n

applicationContext.xml----resources/spring/applicationContext.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" xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><!--<context:component-scan base-package="com.itheima.service" />--><!--dubbo配置--><!--配置项目名称,唯一--><dubbo:application name="dubbo-service" /><!--配置注册中心的地址--><dubbo:registry address="zookeeper://192.168.120.211:2181" /><!--配置dubbo包扫描--><dubbo:annotation package="com.itheima.service.impl" />
</beans>

UserServiceImpl.java

package com.itheima.service.impl;import com.itheima.service.UserService;
import org.apache.dubbo.config.annotation.Service;@Service
public class UserServiceImpl implements UserService {@Overridepublic String sayHello() {return "hello dubbo...";}
}

web----dubbo-web
pm.xml

<?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.itheima</groupId><artifactId>dubbo-web</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><spring.version>5.1.9.RELEASE</spring.version><dubbo.version>2.7.4.1</dubbo.version><zookeeper.version>4.0.0</zookeeper.version></properties><dependencies><!-- servlet3.0规范的坐标 --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><!--spring的坐标--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><!--springmvc的坐标--><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><!--日志--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.21</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.21</version></dependency><!--Dubbo的起步依赖,版本2.7之后统一为rg.apache.dubb --><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo</artifactId><version>${dubbo.version}</version></dependency><!--ZooKeeper客户端实现 --><dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>${zookeeper.version}</version></dependency><!--ZooKeeper客户端实现 --><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>${zookeeper.version}</version></dependency><!--依赖service模块--><dependency><groupId>com.itheima</groupId><artifactId>dubbo-service</artifactId><version>1.0-SNAPSHOT</version></dependency><!--依赖公共接口--><dependency><groupId>com.itheima</groupId><artifactId>dubbo-interface</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.1</version><configuration><port>8000</port><path>/</path></configuration></plugin></plugins></build>
</project>

web.xml----webapp/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"version="2.5"><!-- Springmvc -->  <servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- 指定加载的配置文件 ,通过参数contextConfigLocation加载--><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/springmvc.xml</param-value></init-param></servlet><servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>*.do</url-pattern></servlet-mapping></web-app>

log4j.rpoperties

# DEBUG < INFO < WARN < ERROR < FATAL
# Global logging configuration
log4j.rootLogger=info, stdout,file
# My logging configuration...
#log4j.logger.com.tocersoft.school=DEBUG
#log4j.logger.net.sf.hibernate.cache=debug
## Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p %d %C: %m%nlog4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=../logs/iask.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}  %l  %m%n

springmvc.xml----resources/spring/springmvc.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"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><mvc:annotation-driven/><context:component-scan base-package="com.itheima.controller"/><dubbo:application name="dubbo-web"><dubbo:parameter key="qos.port" value="33333" /></dubbo:application><dubbo:registry address="zookeeper://192.168.120.211:2181" /><dubbo:annotation package="com.itheima.controller" /></beans>

UserController.java

package com.itheima.controller;import com.itheima.service.UserService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/user")
public class UserController {// 注入Service/*** 1、从zookeeper注册中心获取userService的访问url* 2、进行远程调用RPC* 3、将结果*/@Reference // 远程注入private UserService userService;@RequestMapping("/sayHello")public String sayHello() {return userService.sayHello();}
}

3.1 服务管理端

3.1.1 安装管理端

  1. 解压 dubbo-admin-master.zip
  2. 修改配置文件

  3. 返回到项目根目录,使用maven打包:mvn clean package
  4. 在dos下运行target目录中的jar文件:java -jar dubbo-admin-0.0.1-
    SNAPSHOT.jar
  5. 此时打开浏览器输入:http://localhost:7001/ ;
    第一次访问时,需要登录,帐号密码都是root

3.2.1 管理端使用

  1. 启动服务方,将服务注册到zookeeper
  2. 启动dubbo-server服务方后,刷新管理端,服务注册成功,只是没有消费者
  3. 点击服务名,进入服务提供者页面
  4. 把消费者也运行起来,刷新服务,显示正常
  5. 查看消费者

3.2 监控统计中心

Monitor:统计中心 ,记录服务被调用多少次等

  1. 解压dubbo-monitor-simple-2.5.3.zip
  2. 修改dubbo-monitor-simple-2.5.3\conf\dubbo.properties
  3. 双击运行dubbo-monitor-simple-2.5.3\bin\start.bat
  4. 分别修改dubbo-server和dubbo-consumer的spring.xml,加入下面标签
<!-- 让监控 去注册中心 自动找服务 -->
<dubbo:monitor protocol="registry"/>

4. 综合实战

4.1 配置说明

4.1.1 启动时检查

  • 启动时会在注册中心检查依赖的服务是否可用,不可用时会抛出异常
  • 在消费方编写初始化容器的main方法启动(tomcat启动方式,必须访问一次action才能初始化spring)
public class Test {public static void main(String[] args) throws IOException {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring.xml");System.in.read();}
}
<!--默认是true:抛异常;false:不抛异常-->
<dubbo:consumer check="false" />
  • 系统级别日志,需要配合log4j才输出,在resources下添加log4j.properties,内容如下:
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %m%n
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=dubbo.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %l %m%n
log4j.rootLogger=error, stdout,file

4.1.2 超时时间

  • 由于网络或服务端不可靠,会导致调用过程中出现不确定的阻塞状态(超时)
  • 为了避免超时导致客户端资源(线程)挂起耗尽,必须设置超时时间
  • 在服务提供者添加如下配置:
<!--设置超时时间为2秒,默认为1秒-->
<dubbo:provider timeout="2000"/>
  • 可以将服务实现HelloServiceImpl.java中加入模拟的网络延迟进行测试:
@Service
public class HelloServiceImpl implements HelloService {public String sayHello(String name) {try {Thread.sleep(3000);}catch (Exception e){e.printStackTrace();}return "Hello,"+name+"!!!!!";}
}
  • 超时设置2秒,而模拟的网络延迟有3秒,超出时限,报错!
  • 配置原则:
    • dubbo推荐在Provider上尽量多配置Consumer端属性:
    1. 作服务的提供者,比服务使用方更清楚服务性能参数,如调用的超时时间,合理的重试次数,等等
    2. 在Provider配置后,Consumer不配置则会使用Provider的配置值,即Provider配置可以作消费者的缺省值。

4.1.3 重试次数

  • 当出现失败,自动切换并重试其它服务器,dubbo重试的缺省值是2次,我们可以自行设置
  • 在provider提供方配置:
<!-- 消费方连接第1次不算,再来重试3次,总共重试4次 -->
<dubbo:provider timeout="2000" retries="3"/>
@Service
public class HelloServiceImpl implements HelloService {public String sayHello(String name) {System.out.println("=============被调用 1 次===============");try {Thread.sleep(3000);}catch (Exception e){e.printStackTrace();}return "Hello,"+name+"!!!!!";}
}
  • 并不是所有的方法都适合设置重试次数

    • 幂等方法:适合(当参数一样,无论执行多少次,结果是一样的,例如:查询,修改)
    • 非幂等方法:不适合(当参数一样,执行结果不一样,例如:删除,添加)
  • 单独设置某个方法
  1. 提供方接口添加sayNo()方法并实现
public interface HelloService {String sayHello( String name );String sayNo();
}
@Service
public class HelloServiceImpl implements HelloService {public String sayHello(String name) {System.out.println("=============hello被调用一次
===============");try {Thread.sleep(3000);}catch (Exception e){e.printStackTrace();}return "Hello,"+name+"!!!!!";}public String sayNo() {System.out.println("-------no被调用一次-------");return "no!";}
}
  1. 消费方接口添加sayNo()方法声明
public interface HelloService {String sayHello( String name );String sayNo();
}
  1. 消费方controller
@Controller
public class HelloAction {//@Reference 此注解已经在xml文件中被<dubbo:reference>顶替,所以自动注入即可@Autowiredprivate HelloService helloService;@GetMapping("hello")@ResponseBodypublic String sayHi(String name){return helloService.sayHello(name);}@GetMapping("no")@ResponseBodypublic String no(){return helloService.sayNo();}
}
  1. 消费方配置方法重试次数
<dubbo:reference interface="service.HelloService" id="helloService"><dubbo:method name="sayHello" retries="3"/><dubbo:method name="sayNo" retries="0"/> <!-- 不重试 -->
</dubbo:reference>

4.1.4 多版本

  • 一个接口,多个(版本的)实现类,可以使用定义版本的方式引入
  • 为HelloService接口定义两个实现类,提供者修改配置:
<dubbo:service interface="service.HelloService" class="service.impl.HelloServiceImpl01" version="1.0.0"/>
<dubbo:service interface="service.HelloService" class="service.impl.HelloServiceImpl02" version="2.0.0"/>
  • 消费者就可以根据version的版本,选择具体的服务版本
<dubbo:reference interface="service.HelloService" id="helloService"
version="2.0.0"><dubbo:method name="sayHello" retries="3"/><dubbo:method name="sayNo" retries="0"/>
</dubbo:reference>
  • 注意:消费者的控制层要改为自动注入,因为@Reference注解和 <dubbo:reference>在这里冲突
@Controller
public class HelloAction {@Autowiredprivate HelloService helloService;
}
  • 当消费者的版本修改为 version="*",那么就会随机调用服务提供者的版本
-------1.0被调用一次-------
-------2.0被调用一次-------
-------1.0被调用一次-------
-------1.0被调用一次-------
-------1.0被调用一次-------
-------2.0被调用一次-------

4.1.5 本地存根

  • 目前我们的分布式架构搭建起来有一个严重的问题,就是所有的操作全都是 消费者发起,由服务提供者执行
  • 消费者动动嘴皮子却什么活都不干,这样会让提供者很累,例如简单的参数验证,消费者完全能够胜任,把合法的参数再发送给提供者执行,效率高了,提供者也没那么累了
  • 例如:去房产局办理房屋过户,请带好自己的证件和资料,如果什么都不带,那么办理过户手续会很麻烦,得先调查你有什么贷款,有没有抵押,不动产证是不是你本人,复印资料等操作。一天肯定办不完。明天还要来。如果你能提前将这些东西准备好,办理过户,1个小时足矣,这就是“房产中介办事效率高的原因”
  • 话不多说,先在消费者处理一些业务逻辑,再调用提供者的过程,就是“本地存根”
  • 代码实现肯定在 消费者,创建一个HelloServiceStub类并且实现HelloService接口
  • 注意:必须使用构造方法的方式注入
public class HelloServiceStub implements HelloService {private HelloService helloService;// 注入HelloServicepublic HelloServiceStub(HelloService helloService) {this.helloService = helloService;}public String sayHello(String name) {System.out.println("本地存根数据验证。。。");if(!StringUtils.isEmpty(name)){return helloService.sayHello(name);}return "i am sorry!";}public String sayNo() {return helloService.sayNo();}
}
  • 修改消费者配置:
<dubbo:reference interface="service.HelloService" id="helloService"
version="1.0.0" stub="service.impl.HelloServiceStub"><dubbo:method name="sayHello" retries="3"/><dubbo:method name="sayNo" retries="0"/>
</dubbo:reference>

4.1.6 序列化

4.1.7 地址缓存

4.2 负载均衡策略

  • 负载均衡(Load Balance), 其实就是将请求分摊到多个操作单元上进行执行,从而共同完成工作任务。
  • 简单的说,好多台服务器,不能总是让一台服务器干活,应该“雨露均沾”
  • dubbo一共提供4种策略,缺省为 random 随机分配调用




  • 修改提供者配置并启动3个提供者,让消费者对其进行访问

    • tomcat端口8001,8002,8003
    • provider端口20881,20882,20883
<dubbo:provider timeout="2000" retries="3" port="20881"/>
+ HelloServiceImpl01类,服务器1,服务器2,服务器3
public String sayNo() {System.out.println("----服务器1---1.0被调用一次-------");return "no!";
}
+ 启动consumer进行测试
  • 消费方修改权重
<dubbo:reference loadbalance="roundrobin" interface="service.HelloService"
id="helloService" version="2.0.0" stub="stub.HelloServiceStub"><dubbo:method name="sayHello" retries="3"/><dubbo:method name="sayNo" retries="0"/>
</dubbo:reference>
  • 最好使用管理端修改权重

4.3 高可用

4.3.1 zookeeper宕机

  • zookeeper注册中心宕机,还可以消费dubbo暴露的服务

    • 监控中心宕掉不影响使用,只是丢失部分采样数据
    • 数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务
    • 注册中心对等集群,任意一台宕掉后,将自动切换到另一台
    • 注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯
    • 服务提供者无状态,任意一台宕掉后,不影响使用
    • 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复
  • 测试:
    • 正常发出请求
    • 关闭zookeeper:./zkServer.sh stop
    • 消费者仍然可以正常消费

4.4 服务降级

  • 壁虎遇到危险会自动脱落尾巴,目的是损失不重要的东西,保住重要的
  • 服务降级,就是根据实际的情况和流量,对一些服务有策略的停止或换种简单的方式处理,从而释放服务器的资源来保证核心业务的正常运行

4.4.1 为什么要服务降级

  • 而为什么要使用服务降级,这是防止分布式服务发生雪崩效应
  • 什么是雪崩?就是蝴蝶效应,当一个请求发生超时,一直等待着服务响应,那么在高并发情况下,很多请求都是因为这样一直等着响应,直到服务资源耗尽产生宕机,而宕机之后会导致分布式其他服务调用该宕机的服务也会出现资源耗尽宕机,这样下去将导致整个分布式服务都瘫痪,这就是雪崩。

4.4.2 服务降级实现方式

  • 在管理控制台配置服务降级:屏蔽和容错
  • 屏蔽:mock=force:return+null 表示消费方对该服务的方法调用都 直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
  • 容错:mock=fail:return+null 表示消费方对该服务的方法调用在 失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。

4.5 整合MyBatis实现用户注册

4.5.1 初始化数据库

CREATE DATABASE smd
USE smd
CREATE TABLE users(uid INT(11) AUTO_INCREMENT PRIMARY KEY,username VARCHAR(50) NOT NULL,PASSWORD VARCHAR(50) NOT NULL,phone VARCHAR(50) NOT NULL,createtime VARCHAR(50) NOT NULL
)

4.5.2 创建聚合项目-项目模块化

  • lagou-dubbo(项目目录)
  • lagou-dubbo-parent(父工程,聚合项目:定义所有模块用的依赖版本)
<modelVersion>4.0.0</modelVersion>
<groupId>com.sunguoan</groupId><artifactId>sun-parent</artifactId>
<version>1.0-SNAPSHOT</version><packaging>pom</packaging><properties>
<spring.version>5.0.6.RELEASE</spring.version>
</properties><dependencies><!-- JSP相关 --><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><scope>provided</scope><version>2.5</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>jsp-api</artifactId><scope>provided</scope><version>2.0</version></dependency><!-- Spring --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>${spring.version}</version></dependency><!-- Mybatis --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.2.8</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.2.2</version></dependency><!-- 连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.0.9</version></dependency><!-- 数据库 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.32</version></dependency><!--dubbo --><dependency><groupId>com.alibaba</groupId><artifactId>dubbo</artifactId><version>2.5.7</version></dependency><dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.4.6</version></dependency><dependency><groupId>com.github.sgroschupf</groupId><artifactId>zkclient</artifactId><version>0.1</version></dependency><dependency><groupId>javassist</groupId><artifactId>javassist</artifactId><version>3.11.0.GA</version></dependency><!-- fastjson --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.47</version></dependency><!-- junit --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version><scope>test</scope></dependency>
</dependencies>
  • lagou-dubbo-entity(实体工程,jar项目)
  • lagou-dubbo-dao(数据访问层工程,jar项目)
  • lagou-dubbo-interface(服务接口定义工程,jar项目)
  • lagou-dubbo-service(privoder服务提供者工程,jar项目)
<parent><groupId>com.sunguoan</groupId><artifactId>sun-parent</artifactId><version>1.0-SNAPSHOT</version>
</parent><modelVersion>4.0.0</modelVersion>
<artifactId>sun-service</artifactId><packaging>war</packaging><dependencies><dependency><groupId>com.sunguoan</groupId><artifactId>sun-interface</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>com.sunguoan</groupId><artifactId>sun-dao</artifactId><version>1.0-SNAPSHOT</version></dependency>
</dependencies>
<build><plugins><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><configuration><port>8001</port><path>/</path></configuration><executions><execution><!-- 打包完成后,运行服务 --><phase>package</phase><goals><goal>run</goal></goals></execution></executions></plugin></plugins>
</build>
  • lagou-dubbo-web(consumer服务消费者工程,war项目)
<!-- 解决post乱码 -->
<filter><filter-name>charset</filter-name><filterclass>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>utf-8</param-value></init-param><init-param><param-name>forceEncoding</param-name><param-value>true</param-value></init-param>
</filter>
<filter-mapping><filter-name>charset</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
<servlet><servlet-name>springMVC</servlet-name><servletclass>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/spring-mvc.xml</param-value></init-param>
</servlet>
<servlet-mapping><servlet-name>springMVC</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>

4.5.3 启动测试

  1. 先选择父项目(聚合工程)进行全员安装成jar
  2. 启动服务service
  3. 启动调用者web

分布式系统架构解决方案----Dubbo相关推荐

  1. 阿里藏经阁不传之秘!超大流量分布式系统架构解决方案笔记

    这本书的创作初衷: 任何一本书,都是一个用于承载和传递知识的载体,读者可以从中探寻自己想要的答案.对我而言,书本就是带我领略奇妙计算机世界的最快途径.之所以想创作一本与大型网站架构相关的书籍,是因为最 ...

  2. 《超大流量分布式系统架构解决方案-人人都是架构师2.0》读书笔记

    持续更新中- 全书总结 本书对于技术的学习并没有很深的阐述,而是从系统的架构角度讲解相关知识,可以帮助同学们或工程师们更好的了解系统的架构知识. 文章目录 持续更新中...... 全书总结 第一章: ...

  3. 《超大流量分布式系统架构解决方案》

    <第一章:大系统小做-大贵妇服务化架构> 网站架构的优化: 1.独立部署,避免不同的系统相互之间争夺共享资源(比如CPU,内存,磁盘等) 2.webServer集群,提高容错性 3.部署分 ...

  4. 分布式系统架构与云原生—阿里云《云原生架构白皮书》导读

    -点击领取<云原生架构白皮书>- 导语: 有幸作为阿里云MVP提前获得了阿里云云原生团队编写的<云原生架构白皮书>,希望通过自己对于云原生的理解为开发者提供一篇观后感或者是能够 ...

  5. 大型互联网分布式系统架构技术要点

    大型互联网分布式系统架构技术要点 解决问题的通用思路是将分而治之(divide-and-conquer),将大问题分为若干个小问题,各个击破.在大型互联网的架构实践中,无一不体现这种思想. 架构目标 ...

  6. 【大型分布式网站】抗住千万流量的大型分布式系统架构设计

    一.大型分布式网站架构技术 1.1 大型网站的特点 用户多,分布广泛 大流量,高并发 海量数据,服务高可用 安全环境恶劣,易受网络攻击 功能多,变更快,频繁发布 从小到大,渐进发展 以用户为中心 免费 ...

  7. 十年互联网架构师,带大家深入学习常见分布式系统架构,涨薪必备

    常见分布式系统架构 复杂的大型软件系统,倾向于使用分布式系统架构.就像Warren Buffett有个关于投资的名言,就是"不要把鸡蛋放在一个篮子里".对于系统而言也是如此.厂商的 ...

  8. 整理下.net分布式系统架构的思路

    最近看到有部分招聘信息,要求应聘者说一下分布式系统架构的思路.今天早晨正好有些时间,我也把我们实际在.net方面网站架构的演化路线整理一下,只是我自己的一些想法,欢迎大家批评指正. 首先说明的是.ne ...

  9. 编程体系结构(09):分布式系统架构

    本文源码:GitHub·点这里 || GitEE·点这里 一.基础概念 1.单服务 所有业务服务和应用组件部署在一台服务上,节省成本,这是单服务结构,适用于并发低,业务单一的场景. 2.集群模式 业务 ...

最新文章

  1. opencv 1 图像载入、显示和输出
  2. mysql查询是否用index_mysql – 为什么这个查询使用where而不是index?
  3. Linux启动界面切换:图形界面-字符界面(转)
  4. 融合变形三维插件想法
  5. java实验报告合肥工业大学_合肥工业大学 计算机专业 计算方法实验报告
  6. 【Linux】一步一步学Linux——type命令(200)
  7. [leetcode] 72.编辑距离
  8. java之hibernate之基于外键的一对一单向关联映射
  9. 二级c语言程序设计翻译,C语言程序设计报错英文翻译
  10. echarts年龄饼图_解决echarts饼图显示百分比,和显示内容字体及大小
  11. cherokee php,CentOS安装最快Web服务器Cherokee+MySQL+PHP
  12. 什么是动态链接库(DLL)以及常见问题
  13. 操作系统(4)状态机视角下的程序执行
  14. 常年“盘踞”数据库前五的 MongoDB,在中国有哪些新动向?
  15. 计算机考试只读,计算机基础考试试题-20210710011550.docx-原创力文档
  16. PHP 数组常用操作函数随记
  17. STM32F429i-DISCO FreeRTOS keil STM32CubeMX
  18. 踩过坑才懂:如何快速打造技术产品
  19. 12月22号至27号进度报告
  20. 控制理论中的几种稳定性介绍

热门文章

  1. vue +vue-router + es6 +webpack 高仿饿了么app
  2. C4D的python语言,Python in C4D学习笔记(前言)
  3. camcard for BB
  4. 高级定时器TIM1输出PWM波
  5. ata高级计算机系统,ATAOffice2021年高级解题步骤
  6. vue echarts地图省市区下钻详解
  7. VNC_一款优秀的远程控制工具软件
  8. ReactNative-Banner
  9. 员工停薪留职协议(模板)
  10. Android通过有线USB上网卡上网