JAVA分布式篇3——Dubbo

JAVA分布式篇3——Dubbo

1、架构演变

1.1、单应用架构

  • 当网站流量很小时,只需要一个应用,将所有的功能部署到一起(所有业务都放在一个tomcat 里),从而减少部署节点和成本
  • 用于简化 增删改查 工作量的数据访问框架 (ORM)是关键
  • 例如:某个超市的收银系统,某个公司的员工管理系统

在这里插入图片描述

优点

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

缺点

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

1.2、垂直应用架构

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

在这里插入图片描述

缺点

  • 模块之间不可能完全没有交集,公用模块无法重复利用,开发性的浪费

1.3、分布式服务架构

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

在这里插入图片描述

1.4、流动计算架构

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

在这里插入图片描述

2、Dubbo

  • Dubbo是分布式服务框架,是阿里巴巴的开源项目,现交给apache进行维护
  • Dubbo致力于提高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案

3、RPC

RPC【Remote Procedure Call】是指远程过程调用,是一种进程间通信方式

3.1、RPC通信原理

  • 在客户端将对象进行序列化
  • 底层通信框架使用netty(基于tcp协议的socket),将序列化的对象发给服务方提供方
  • 服务提供方通过socket得到数据文件之后,进行反序列化,获得要操作的对象
  • 对象数据操作完毕,将新的对象序列化,再通过服务提供方的socket返回给客户端
  • 客户端获得序列化数据,再反序列化,得到最新的数据对象,至此,完成一次请求

在这里插入图片描述

RPC的核心:通信、序列化

4、Dubbo角色介绍

节点角色说明
Provider服务的提供方
Consumer服务的消费方
Registry服务注册与发现的注册中心
Monitor监控服务的统计中心
Container服务运行容器

在这里插入图片描述

4.1、启动流程

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

5、Dubbo快速入门

5.1、dubbo监控

在正式开始dubbo前,我们先来处理dubbo监控问题

github https://github.com/apache/dubbo-admin

官网打不开可尝试下面地址

gitee https://codechina.csdn.net/mirrors/apache/dubbo-admin

百度云:https://pan.baidu.com/s/1_b6X3SkgTskLdal3HTtHmw提取码:exa0

进入dubbo-admin-master

如zookeeper与dubbo不在一台机器,需修改配置文件(dubbo-admin-master\dubbo-admin\src\main\resources\application.properties)

在这里插入图片描述

打开cmd,执行mvn package -Dmaven.skip.test=true,时间会有点久,出现下图表成功

在这里插入图片描述

进入dubbo-admin-master\dubbo-admin\target,拷贝jar包到服务器,后台启动jar包

[root@VM-8-13-centos bin]# cd /root
[root@VM-8-13-centos ~]# ls
dubbo-admin-0.0.1-SNAPSHOT.jar
[root@VM-8-13-centos ~]# nohup java -jar dubbo-admin-0.0.1-SNAPSHOT.jar > dubbo-admin.log  2>&1 &
[1] 32315
[root@VM-8-13-centos ~]# netstat -tunlp|grep 7001
tcp6       0      0 :::7001                 :::*                    LISTEN      32315/java

访问监控页面

http://81.70.1.65:7001/

默认账号密码都为root

在这里插入图片描述

到此监控页面配置完成

下面介绍linux结束进程

首先查看端口pid

[root@VM-8-13-centos ~]# netstat -tunlp|grep 7001
tcp6       0      0 :::7001                 :::*                    LISTEN      32315/java

杀死进程

[root@VM-8-13-centos ~]# kill -9 32315

5.2、创建maven项目导入依赖

5.2.1、服务方

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>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContent.xml</param-value>
    </context-param>
</web-app>

log4j.properties

log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/zk.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n

applicationContext.xml

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans"
       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="winkto-dubbo-provider"/>
    <!--注册中心地址-->
    <dubbo:registry address="zookeeper://81.70.1.65:2181" timeout="30000"/>
    <!--服务-->
    <dubbo:annotation package="cn.winkto.service" />
</beans>

服务

public interface RuoyeService {
    public String sayBye(String name);
}
@DubboService
public class RuoyeServiceImpl implements RuoyeService {
    public String sayBye(String name) {
        System.out.println(name);
        return name+" bye";
    }
}
5.2.2、消费方

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_4_0.xsd"
         version="4.0">
    <!--注册DispatcherServlet-->
    <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:springmvc-config.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!--/ 匹配所有的请求;(不包括.jsp)-->
    <!--/* 匹配所有的请求;(包括.jsp)-->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

log4j.properties

log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/zk.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n

springmvc-config.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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       https://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://dubbo.apache.org/schema/dubbo
       http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!--Dubbo的应用名称,通常使用项目名 -->
    <dubbo:application name="dubbo-consumer" />
    <!--配置Dubbo的注册中心地址 -->
    <dubbo:registry address="zookeeper://81.70.1.65:2181" timeout="30000" />

    <dubbo:annotation package="cn.winkto.controller" />

    <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
    <context:component-scan base-package="cn.winkto.controller"/>
    <!-- 让Spring MVC不处理静态资源 -->
    <mvc:default-servlet-handler />
    <!--处理器映射器和处理器适配器,以及功能增强-->
    <mvc:annotation-driven />

</beans>

伪服务接口

public interface RuoyeService {
    public String sayBye(String name);
}

controller

@RestController
public class YoyaController {
    @DubboReference
    private RuoyeService ruoyeService;

    @RequestMapping("/bye/{name}")
    public String bye(@PathVariable String name){
        System.out.println(name);
        return ruoyeService.sayBye(name);
    }
}
测试
http://localhost:8082/dubbo_consumer_war_exploded/bye/yoya

6、配置详解

6.1、启动检查

启动时会在注册中心检查依赖的服务是否可用,不可用时会抛出异常

<!--默认是true:抛异常;false:不抛异常-->
<dubbo:consumer check="false" />

6.2、超时时间

由于网络或服务端不可靠,会导致调用过程中出现不确定的阻塞状态(超时) 为了避免超时导致客户端资源(线程)挂起耗尽,必须设置超时时间

<!--设置超时时间为2秒,默认为1秒-->
<dubbo:provider timeout="2000"/>

dubbo推荐在Provider上尽量多配置Consumer端属性

  • 作服务的提供者,比服务使用方更清楚服务性能参数,如调用的超时时间,合理的重试 次数,等等
  • 在Provider配置后,Consumer不配置则会使用Provider的配置值,即Provider配置可 以作消费者的缺省值

6.3、重试次数

当出现失败,自动切换并重试其它服务器,dubbo重试的缺省值是2次,我们可以自行设置(在提供方设置)

<dubbo:provider timeout="2000" retries="3"/>

并不是所有的方法都适合设置重试次数

  • 幂等方法:适合(当参数一样,无论执行多少次,结果是一样的,例如:查询,修改)
  • 非幂等方法:不适合(当参数一样,执行结果不一样,例如:删除,添加)

配置重试次数

<dubbo:reference id="ruoyeService" interface="cn.winkto.service.RuoyeService">
    <dubbo:method name="bye" retries="1"/>
</dubbo:reference>

6.4、多版本配置

提供者

@DubboService
public class RuoyeServiceImpl1 implements RuoyeService {
    public String sayBye(String name) {
        System.out.println(name);
        return name+" bye";
    }
}
@DubboService
public class RuoyeServiceImpl2 implements RuoyeService {
    public String sayBye(String name) {
        System.out.println(name);
        return name+" byebye~";
    }
}
<dubbo:service interface="cn.winkto.service.RuoyeService" class="cn.winkto.service.RuoyeServiceImpl1" version="1.0.0"/>
<dubbo:service interface="cn.winkto.service.RuoyeService" class="cn.winkto.service.RuoyeServiceImpl2" version="2.0.0"/>

消费者

<dubbo:reference id="ruoyeService" interface="cn.winkto.service.RuoyeService" version="2.0.0">
    <dubbo:method name="bye" retries="1"/>
</dubbo:reference>
@RestController
public class YoyaController {

    @DubboReference(version = "2.0.0")
    private RuoyeService ruoyeService;

    @RequestMapping("/bye/{name}")
    public String bye(@PathVariable String name){
        System.out.println(name);
        return ruoyeService.sayBye(name);
    }
}

消费者的控制层要改为自动注入

当消费者的版本修改为 version="*",那么就会随机调用服务提供者的版本

6.5、本地存根

先在消费者处理一些业务逻辑,再调用提供者的过程,就是“本地存根”

在消费者,创建一个接口实现类,注意:必须使用构造方法的方式注入

@Service
public class RuoyeServiceImpl implements RuoyeService {
    private RuoyeService ruoyeService;

    public RuoyeServiceImpl(RuoyeService ruoyeService) {
        this.ruoyeService = ruoyeService;
    }

    public String sayBye(String name) {
        if (!name.equals("zhangsan"))
        return ruoyeService.sayBye(name);
        return "名称不正确哦";
    }
}
@RestController
public class YoyaController {

    @DubboReference(version = "2.0.0",stub = "cn.winkto.service.RuoyeServiceImpl")
    private RuoyeService ruoyeService;

    @RequestMapping("/bye/{name}")
    public String bye(@PathVariable String name){
        System.out.println(name);
        return ruoyeService.sayBye(name);
    }
}

6.6、负载均衡策略

  • 负载均衡(Load Balance), 其实就是将请求分摊到多个操作单元上进行执行,从而共同完成工作 任务
  • dubbo一共提供4种策略,缺省为 random 随机分配调用

在这里插入图片描述

6.7、高可用

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

  • 监控中心宕掉不影响使用,只是丢失部分采样数据
  • 数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务
  • 注册中心对等集群,任意一台宕掉后,将自动切换到另一台
  • 注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯 服务提供者无状态,任意一台宕掉后,不影响使用
  • 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复

6.8、 服务降级

服务降级,就是根据实际的情况和流量,对一些服务有策略的停止或换种简单的方式处理,从而释 放服务器的资源来保证核心业务的正常运行

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

眼眸流转

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

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

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

打赏作者

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

抵扣说明:

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

余额充值