Java经典框架之Dubbo

发布时间:2024年01月06日

Dubbo

Java 是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java 虚拟机,Java 仍是企业和开发人员的首选开发平台。
??

课程内容的介绍

1. Dubbo概述
2. Dubbo基本应用
3. Dubbo实战案例
? ? ?

一、Dubbo概述

1、Dubbo及架构变化
1.1 Dubbo 介绍
Dubbo 是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的RPC 实现服务的输出和输入功能,可以和 Spring 框架无缝集成。Dubbo 框架,是基于容器运行的.。容器是 Spring。
官方网站 : http://dubbo.apache.org/
阿里巴巴已经将 dubbo 框架捐献给了 Apache 软件基金会。

??
现在出去找工作如果不会点分布式和微服务相关的内容,都不太好更面试官扯蛋。但这些架构也不是突然就出现的,而是经过不但演变才出现及流行起来的,本文就给大家来梳理下java项目架构的演变历程。
??
系统架构演化历程
单体架构
??大型网站都是从小型网站发展而来的,网站架构也是一样,是从小型网站架构逐步演化而来的,小型网站最开始没有太多人访问,只需要一台服务器就绰绰有余了,这时的架构如下:

??

应用程序、数据库、文件等所有的资源都在一台服务器上,通常服务器操作系统使用Linux、应用程序使用java或者其他语句,然后部署在Apache或者Nginx上。数据库使用MySQL,使用开源的技术实现,然后部署在一台廉价的服务器上就开始了网站的发展之路。

? ? ??

应用服务和数据服务分离
??好景不长,随着公司业务的发展,一台服务逐渐满足不了需求,越来越多的用户访问导致性能越来越差,数据存储空间开始不足,这时我们需要将应用和数据分离,分离后开始使用三台服务器:应用服务器、文件服务器、数据库服务器。如图:

??

应用和数据分离后,不同特性的服务器承担着不同的服务角色,网站的并发处理能力和数据存储空间都得到了很大的改善,支持网站业务进一步发展,但是随着用户逐渐增多,数据库压力越来越大,访问延迟,进而影响整个网站的性能,此时需要进一步优化。

缓存的使用
??网站访问有个著名的二八定律,即80%的业务集中访问在20%的数据上,如果我们将这一小部分的数据缓存在内存中,能够很好的减少数据库的访问压力,提高整个网站的数据访问速度。

? ?

缓存常用的组件可以是Redis,ehcache等。

? ??
集群的使用
??缓存解决了数据库访问量比较大的问题,但是并不能解决随着业务增多造成的服务器并发压力大的问题,这时我们需要增加一台应用服务器来分担原来服务器的访问压力和存储压力。如图:

??

通过负载均衡调度服务器,可将来自用户的访问请求分发到应用服务器中的任何一台服务器中,这样多台服务器就分担了原来一台服务器的压力,我们只需要注意会话的一致性就可以了。

??

数据库读写分离
??系统正常运行了一段时间后,虽然加的有缓存,使绝大多数的数据库操作可以不通过数据库就能完成,但是任然有一部分的操作(缓存访问不命中,缓存过期)和全部的写操作需要访问数据库,当用户达到一定规模后,数据库因为负载压力过大还是会成为系统的瓶颈,
??这时主流的数据库都提供的有主从热备份功能,通过配置两台数据库实现主从关系,可以将一台数据库服务器的数据更新同步到另一台服务器上。可以利用这一功能来实现数据库读写分离。从而改善数据库的负载压力,如图:

??

mysql的读写分离可以通过自身自带的从主复制实现,Oracle的话可以通过阿里巴巴的mycat组件来实现。

??

反向代理和CDN加速
??为了应付复杂的网络环境和不同地区用户的访问,通过CDN和反向代理加快用户访问的速度,同时减轻后端服务器的负载压力。CDN与反向代理的基本原理都是缓存。CDN部署在网络提供商的机房。用户请求到来的时候从距离自己最近的网络提供商机房获取数据,而反向代理则部署在网站的中心机房中,请求带来的时候先去反向代理服务器中查看请求资源,如果有则直接返回。如图:

??

使用CDN和反向代理的目的都是尽早返回数据给用户,一方面加快用户的访问速度,另一方面也减轻后端服务器的负载压力。

??

分布式文件和分布式数据库
??任何强大的单一服务器都满足不了大型网站持续增长的业务需求。数据库经过读写分离后,从一台服务器拆分成两天服务器,但是随着业务的增长后面依然不能满足需求,这时我们需要使用分布式数据库,同时文件系统也一样,需要使用分布式文件系统。
??分布式数据库是数据库拆分的最后的手段,只有在表单数据规模非常庞大的时候才使用,不到不得已时,我们更常用的手段是业务分库,将不同的业务数据部署在不同的物理服务器上。

??

NoSql和搜索引擎
??随着业务越来越复杂,对数据存储和检索的需求也越来越复杂,这时一些NoSQL(Reids,HBase,mongodb)数据库技术和搜索引擎(Solr,Elasticsearch)的时候就显得很有必要。如下图:

? ? ?

NoSQL和搜索引擎对可伸缩的分布式特性具有更好的支持,应用服务器通过一个统一的数据访问模块访问各种数据,减轻应用程序管理诸多数据源的麻烦。

??

业务拆分
??当访问量达到一定规模的时候我们可以通过分而治之的手段将整个系统的业务分成不同的产品线,例如我们将系统的首页,商铺,订单,买家,卖家,支付,订单等拆分成不同的产品线。
??具体到技术实现上,也可以根据产品线划分,将一个网站拆分成许多不同的应用,每个应用独立部署维护,应用之间通过RPC框架(dubbo,webService,httpClient…)建立连接,也可以通过消息队列实现异步分发处理。来构成一个完整的系统,如下图:

??

分布式服务
随着业务拆分越来越小,存储系统越来越庞大,应用系统的整体复杂度呈指数级增加,部署维护越来越困难,由于所有应用要和所有数据库系统连接,最终导致数据库连接资源不足,拒绝服务。

1.当服务越来越多时,服务URL配置管理变得非常困难,F5硬件负载均衡器的单点压力也越来越大。
2.当进一步发展,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。
3.接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器?
4.服务多了,沟通成本也开始上升,调某个服务失败该找谁?服务的参数都有什么约定?
5.一个服务有多个业务消费者,如何确保服务质量?
6.随着服务的不停升级,总有些意想不到的事发生,比如cache写错了导致内存溢出,故障不可避免,每次核心服务一挂,影响一大片,人心慌慌,如何控制故障的影响面?服务是否可以功能降级?或者资源劣化?

? ?
解决方案:公共的应用模块被提取出来,部署在分布式服务器上供应用服务器调用。也就是我们将的分布式服务或者微服务。

??
1.2 单体架构
单体架构也称之为单体系统或者是单体应用。就是一种把系统中所有的功能、模块耦合在一个应用中的架构方式。其优点为:项目易于管理、部署简单。缺点:测试成本高、可伸缩性差、可靠性差、迭代困难、跨语言程度差、团队协作难。
??
1.3 SOA 架构:
面向服务的架构(SOA- Service-Oriented Architecture)是一个组件模型,它将应用程序拆分成不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起来。接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台、操作系统和编程语言。这使得构建在各种各样的系统中的服务可以以一种统一和通用的方式进行交互。
??
1.4 RPC 远程过程调用
远程过程调用协议( Remote Procedure Call Protocol),它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC 协议假定某些传输协议的存在,如 TCP 或 UDP,为通信程序之间携带信息数据。在 OSI 网络通信模型中,RPC 跨越了传输层和应用层。RPC 使得开发包括网络分布式多程序在内的应用程序更加容易。
??
2、Dubbo 框架结构图
2.1 Dubbo 角色介绍

??
registry
注册中心是用于发布和订阅服务的一个平台.用于替代 SOA 结构体系框架中的 ESB 服务总线的。
??
发布
开发服务端代码完毕后,将服务信息发布出去. 实现一个服务的公开。

?

订阅
客户端程序,从注册中心下载服务内容 这个过程是订阅。
订阅服务的时候,会将发布的服务所有信息,一次性下载到客户端.客户端也可以自定义,修改部分服务配置信息。如: 超时的时长, 调用的重试次数等。
? ?
consumer
服务的消费者, 就是服务的客户端。
消费者必须使用 Dubbo 技术开发部分代码. 基本上都是配置文件定义。
??
provider
服务的提供者, 就是服务端。
服务端必须使用 Dubbo 技术开发部分代码. 以配置文件为主。
??
container
容器. Dubbo 技术的服务端(Provider), 在启动执行的时候, 必须依赖容器才能正常启动。
默认依赖的就是 Spring 容器. 且 Dubbo 技术不能脱离 Spring 框架。
在 2.5.3 版本的 dubbo 中, 默认依赖的是 spring2.5 版本技术. 可以选用 Spring4.5 以下版本。
在 2.5.7 版本的 dubbo 中, 默认依赖的是 spring4.3.10 版本技术. 可以选择任意的 spring版本。
??
monitor
监控中心,是 Dubbo 提供的一个jar工程。
主要功能是监控服务端(Provider)和消费端(Consumer)的使用数据的。?如:服务端是什么,有多少接口,多少方法,调用次数,压力信息等。客户端有多少,调用过哪些服务端,调用了多少次等。

? ?
2.2 Dubbo 执行流程
start:启动 Spring 容器时,自动启动 Dubbo 的 Provider。
register:Dubbo 的 Provider 在启动后自动会去注册中心注册内容注册的内容包括:
1.1 Provider 的 IP。
1.2 Provider 的端口。
1.3 Provider 对外提供的接口列表,哪些方法,哪些接口类。
1.4 Dubbo 的版本。
1.5 访问 Provider 的协议。
subscribe: 订阅.当 Consumer 启动时,自动去 Registry 获取到所已注册的服务的信息。
notify: 通知.当 Provider 的信息发生变化时,自动由 Registry 向 Consumer 推送通知。
invoke: 调用. Consumer 调用 Provider 中方法。
1.1 同步请求.消耗一定性能.但是必须是同步请求,因为需要接收调用方法后的结果。
count:次数. 每隔 2 分钟,provoider 和 consumer 自动向 Monitor 发送访问次数.Monitor进行统计。
??

3.Dubbo 支持的协议
3.1Dubbo 协议(官方推荐协议)

??
3.2RMI(Remote Method Invocation)协议

??
3.3Hessian 协议

??
4.Dubbo 支持的注册中心
4.1Zookeeper(官方推荐)
1. 优点:
支持分布式.很多周边产品。
2. 缺点:
受限于 Zookeeper 软件的稳定性。Zookeeper 专门分布式辅助软件,稳定较优。
??
4.2 Multicast
1. 优点:
去中心化,不需要单独安装软件。
2. 缺点:
Provider 和 Consumer 和 Registry 不能跨机房(路由)。
??
4.3Redis
1. 优点:
支持集群,性能高。
??
2. 缺点:
要求服务器时间同步。否则可能出现集群失败问题。
? ?
4.4Simple
1. 优点:
标准 RPC 服务。没有兼容问题。
2. 缺点:
不支持集群。
??

二、Dubbo基本应用

1. Dubbo基本案例
实现项目之间的调用。
??
1.1 项目结构

??
1.2 公共模块
在commons模块中定义个service接口即可。
package com.bobo;

public interface UserService {

    String sayHello(String name);

}
??

??
1.3 provider
创建服务提供者。
    <dependencies>
        <!-- 添加commons模块 -->
        <dependency>
            <groupId>com.bobo</groupId>
            <artifactId>dubbo-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--- 添加Spring依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>
        <!-- dubbo的依赖 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.5.3</version>
            <exclusions>
                <exclusion>
                    <groupId>spring</groupId>
                    <artifactId>org.springframework</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- Zookeeper的客户端 -->
        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.1</version>
        </dependency>
    </dependencies>
??
创建服务端提供的服务。
package com.bobo.service;

import com.bobo.service.UserService;

public class UserServiceImpl implements UserService {
    @Override
    public String sayHello(String name) {

        System.out.println("服务端执行了: " + name);
        return "HELLO:" + name + "[msg]";
    }
}
??
添加Spring的配置文件。
<?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:dubbo="http://code.alibabatech.com/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
    http://www.springframework.org/schema/context/spring-context-4.0.xsd
    http://code.alibabatech.com/schema/dubbo
    http://code.alibabatech.com/schema/dubbo/dubbo.xsd">


    <!-- 提供方应用信息 -->
    <dubbo:application name="dubboProvider" />
    <!-- 配置Zookeeper注册中心 -->
    <dubbo:registry protocol="zookeeper"
                    address="192.168.100.120:2181,192.168.100.121:2181,192.168.100.122:2181"/>
    <!-- 开启监控 -->
    <dubbo:monitor protocol="registry" />
    <!-- 设置Dubbo使用的协议 -->
    <dubbo:protocol name="dubbo" port="20880" />


    <!-- 注入UserServiceImpl -->
    <bean class="com.bobo.service.UserServiceImpl" id="userService"/>

    <!-- 声明需要对外暴露的服务 -->
    <dubbo:service interface="com.bobo.service.UserService" ref="userService"
        group="dubbo" version="1.0.0" timeout="5000"
    />

</beans>
??
为了看到日志效果,我们添加log4j.properties文件。
log4j.rootLogger=INFO,A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
? ?
添加启动文件。
package com.bobo;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AppStart {

    public static void main(String[] args) throws Exception{
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 挂起当前线程
        Thread.currentThread().join();
    }
}
??
文章来源:https://blog.csdn.net/m0_52514893/article/details/135417474
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。