分布式架构与Dubbo基础入门与实践

本文涉及的产品
应用型负载均衡 ALB,每月750个小时 15LCU
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
网络型负载均衡 NLB,每月750个小时 15LCU
简介: 分布式架构与Dubbo基础入门与实践

【1】分布式系统

① 什么是分布式系统

《分布式系统原理与范型》定义:“分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统”。

分布式系统(distributed system)是建立在网络之上的软件系统。

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


② 架构发展演变

如下图所示:

  • 单一应用架构

当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。

适用于小型网站,小型管理系统,将所有功能都部署到一个功能里,简单易用。

缺点: 1、性能扩展比较难 ;2、协同开发问题; 3、不利于升级维护。


  • 垂直应用架构

当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键。

通过切分业务来实现各个模块独立部署,降低了维护和部署的难度,团队各司其职更易管理,性能扩展也更方便,更有针对性。

缺点: 公用模块无法重复利用,开发性的浪费。


  • 分布式服务架构

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


  • 流动计算架构

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

即,通常分布式应用就是面向服务的分布式架构。


③ RPC

  • 什么叫RPC

RPC(Remote Procedure Call)是指远程过程调用,是一种进程间通信方式,他是一种技术的思想,而不是规范。它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。即程序员无论是调用本地的还是远程的函数,本质上编写的调用代码基本相同。

  • RPC基本原理


时序图如下:


可以发现RPC两个核心模块:通讯和序列化。

常见的RPC框架有:Dubbo、GRPC(谷歌)、Thrift(Facebook)、HSF(High Speed Service Framework 阿里)、JSF(京东)及Motan(新浪)。

【2】Dubbo

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

官网地址:http://dubbo.apache.org/

官网开发文档:http://dubbo.apache.org/zh-cn/docs/user/preface/


Dubbo的官方用户文档提供了很详细的使用说明与实例,遇到问题请一定参考官网文档!

① 结构示意图

如下所示(012345表示执行顺序,实线表示同步,虚线表示异步):

特性如下:

  • 面向接口代理的高性能RPC调用:提供高性能的基于代理的远程调用能力,服务以接口为粒度,为开发者屏蔽远程调用底层细节。
  • 智能负载均衡:内置多种负载均衡策略,智能感知下游节点健康状况,显著减少调用延迟,提高系统吞吐量。
  • 服务自动注册与发现:支持多种注册中心服务,服务实例上下线实时感知。
  • 高度可扩展能力:遵循微内核+插件的设计原则,所有核心能力如Protocol、Transport、Serialization被设计为扩展点,平等对待内置实现和第三方实现。
  • 运行期流量调度:内置条件、脚本等路由策略,通过配置不同的路由规则,轻松实现灰度发布,同机房优先等功能。
  • 可视化的服务治理与运维:提供丰富服务治理、运维工具–随时查询服务元数据、服务健康状态及调用统计,实时下发路由策略、调整配置参数。

② 几个概念

服务提供者(Provider):暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。

服务消费者(Consumer): 调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己所需的服务。服务消费者从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

注册中心(Registry):注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

监控中心(Monitor):服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。


③ 调用关系说明

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

【3】Zookeeper注册中心

Dubbo推荐使用Zookeeper作为注册中心,当然Dubbo还支持其他作为注册中心如Multicast 注册中心,Redis注册中心和Simple 注册中心(本身就是一个普通的 Dubbo 服务)。

① 核心概念

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

官网地址:http://zookeeper.apache.org/

下载地址:https://archive.apache.org/dist/zookeeper/


② 流程说明:

  • 服务提供者启动时: 向 /dubbo/com.foo.BarService/providers 目录下写入自己的 URL 地址
  • 服务消费者启动时: 订阅 /dubbo/com.foo.BarService/providers 目录下的提供者 URL 地址。并向 /dubbo/com.foo.BarService/consumers 目录下写入自己的 URL 地址
  • 监控中心启动时: 订阅 /dubbo/com.foo.BarService 目录下的所有提供者和消费者 URL 地址。

③ 支持以下功能:

  • 当提供者出现断电等异常停机时,注册中心能自动删除提供者信息;
  • 当注册中心重启时,能自动恢复注册数据,以及订阅请求;
  • 当会话过期时,能自动恢复注册数据,以及订阅请求;
  • 当设置 <dubbo:registry check="false" />时,记录失败注册和订阅请求,后台定时重试;
  • 可通过 <dubbo:registry username="admin" password="1234" /> 设置 zookeeper 登录信息
  • 可通过 <dubbo:registry group="dubbo" /> 设置 zookeeper 的根节点,不设置将使用无根树
  • 支持 *号通配符<dubbo:reference group="*" version="*" />,可订阅服务的所有分组和所有版本的提供者

更多详情参考:Dubbo官网文档。


④ Windows下简单搭建Zookeeper

将下载好的Zookeeper解压到本地目录下,并修改zoo.cfg配置文件。

步骤如下:

  • 解压运行bin/zkServer.cmd ,初次运行会报错,没有zoo.cfg配置文件;
  • 将conf下的zoo_sample.cfg复制一份改名为zoo.cfg即可。

注意几个重要位置:

dataDir=./   临时数据存储的目录(可写相对路径)
clientPort=2181   zookeeper的默认端口号
  • 修改完成后再次启动zookeeper
  • 使用zkCli.cmd测试
ls /:列出zookeeper根下保存的所有节点
create –e  /myzookeeper 123:创建一个myzookeeper 节点,值为123
get /myzookeeper :获取/myzookeeper 节点的值

服务端启动示意图如下:

客户端测试如下:



【4】Windows下安装Dubbo管理控制台

dubbo本身并不是一个服务软件。它其实就是一个jar(2.6之后为jar,之前为war需要在Tomcat下运行)包能够帮你的java程序连接到zookeeper,并利用zookeeper消费、提供服务。所以你不用在Linux上启动什么dubbo服务。

但是为了让用户更好的管理监控众多的dubbo服务,官方提供了一个可视化的监控程序,不过这个监控即使不装也不影响使用。

安装步骤如下:

  • 进入Dubbo的GitHub项目项目地址;
  • 在最下方Dubbo eco system中点击进入Dubbo-OPS;
  • Download ZIP并解压到本地


进入目录,修改dubbo-admin配置

修改 src\main\resources\application.properties 指定zookeeper地址:

dubbo.registry.address=zookeeper://127.0.0.1:2181

打包dubbo-adminmvn clean package -Dmaven.test.skip=true

D:\Java_Tomcat_MySQL_jdk_zip\incubator-dubbo-ops-master\dubbo-admin>mvn clean package -Dmaven.test.skip=true
//D:\Java_Tomcat_MySQL_jdk_zip\incubator-dubbo-ops-master 为项目路径

打包成功如下图所示:


  • 使用命令运行jarjava -jar dubbo-admin-0.0.1-SNAPSHOT.jar
  • 浏览器访问(http://localhost:7001/)默认用户名密码root/root


Dubbo OPS项目与管理后台jar包下载:点击下载。


【5】服务器提供者/消费者项目简单实践

① 简单需求

某个电商系统,订单服务需要调用用户服务获取某个用户的所有地址。

我们现在 需要创建两个服务模块进行测试 :

image.png

测试预期结果:订单服务模块在A服务器,用户服务模块在B服务器,A可以远程调用B的功能。

② 创建服务提供者和消费者

如下所示,创建两个maven工程,分别表示provider和consumer:


那消费者如何调用provider的方法呢?这里如果将provider依赖进consumer,则就成了单体应用。

或者可以这样,将provider的bean和service拷贝到consumer中,如下所示:


该种方式项目实例参考SpringBoot整合Dubbo和Zookeeper。

这种方式是有问题:第一,暂且不说现在OrderServiceImpl调用UserService肯定失败(实现类在另外一个项目);第二,UserService可能会被多个模块调用,原则上不应该每个调用UserService的模块都添加bean和UserService接口,添麻烦。而且也不符合Dubbo的服务化最佳实践


这里将bean和接口抽离出来放在一个公共API项目中,provider和consumer依赖该项目。如下所示:

现在需要解决的问题就是远程调用,OrderServiceImpl如何调用userService.getUserAddressList(userId);


③ Dubbo改造服务提供者

第一步:引入依赖:

<!-- 引入dubbo -->
  <!-- https://mvnrepository.com/artifact/com.alibaba/dubbo -->
  <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>dubbo</artifactId>
    <version>2.6.2</version>
  </dependency>
  <!-- 注册中心使用的是zookeeper,引入操作zookeeper的客户端端 -->
  <dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>2.12.0</version>
  </dependency>

dubbo 2.6以前的版本引入zkclient操作zookeeper ,dubbo 2.6及以后的版本引入curator操作zookeeper。

下面两个zk客户端根据dubbo版本2选1即可:

<dependency>
  <groupId>com.101tec</groupId>
  <artifactId>zkclient</artifactId>
  <version>0.10</version>
</dependency>
<!-- curator-framework -->
<dependency>
  <groupId>org.apache.curator</groupId>
  <artifactId>curator-framework</artifactId>
  <version>2.12.0</version>
</dependency>

第二步,配置服务

在provider类路径下添加配置文件provider.xml:

  <!-- 1、指定当前服务/应用的名字(同样的服务名字相同,不要和别的服务同名) -->
  <dubbo:application name="user-service-provider"></dubbo:application>
  <!-- 2、指定注册中心的位置 -->
  <!-- <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> -->
  <dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"></dubbo:registry>
  <!-- 3、指定通信规则(通信协议?通信端口) -->
  <dubbo:protocol name="dubbo" port="20882"></dubbo:protocol>
  <!-- 4、暴露服务   ref:指向服务的真正的实现对象 -->
  <dubbo:service interface="com.web.gmall.service.UserService" 
    ref="userServiceImpl" >
    <dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method>
  </dubbo:service>
  <!--统一设置服务提供方的规则  -->
  <dubbo:provider timeout="1000"></dubbo:provider>
  <!-- 服务的实现 -->
  <bean id="userServiceImpl" class="com.web.gmall.service.impl.UserServiceImpl"></bean>

第三步,编写主类进行测试

public class MainApplication {
  public static void main(String[] args) throws IOException {
    ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("provider.xml");
    ioc.start();
    System.in.read();
  }
}

使用Dubbo Admin管理后台查看,可以发现已经新增了一个服务提供者:


④ Dubbo改造服务消费者

第一步:引入依赖:

<!-- 引入dubbo -->
  <!-- https://mvnrepository.com/artifact/com.alibaba/dubbo -->
  <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>dubbo</artifactId>
    <version>2.6.2</version>
  </dependency>
  <!-- 注册中心使用的是zookeeper,引入操作zookeeper的客户端端 -->
  <dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>2.12.0</version>
  </dependency>

第二步,配置服务

在消费者class资源路径下配置consumer.xml:

    <context:component-scan base-package="com.web.gmall.service.impl"></context:component-scan>
  <dubbo:application name="order-service-consumer"></dubbo:application>
  <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry>
  <!--声明需要调用的远程服务的接口;生成远程服务代理  -->
  <dubbo:reference interface="com.web.gmall.service.UserService" 
    id="userService" >
  </dubbo:reference>

第三步,编写主类进行测试

public class MainApplication {
  @SuppressWarnings("resource")
  public static void main(String[] args) throws IOException {
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("consumer.xml");
    OrderService orderService = applicationContext.getBean(OrderService.class);
    orderService.initOrder("1");
    System.out.println("调用完成....");
    System.in.read();
  }
}

在保证Zookeeper服务端,Dubbo Admin和服务器提供者启动并正常运行前提下,运行该消费者主类,将会从服务提供者那里获取数据!

使用Dubbo Admin后台查看:

截止现在,Dubbo+Zookeeper简单整合实践,源码下载地址。


【6】安装Monitor监控中心

Simple Monitor 挂掉不会影响到 Consumer 和 Provider 之间的调用,所以用于生产环境不会有风险。

Simple Monitor 采用磁盘存储统计信息,请注意安装机器的磁盘限制,如果要集群,建议用mount共享磁盘。

① 安全并运行Monitor

和安装Dubbo Admin时步骤类似,进入incubator-dubbo-ops-master\dubbo-monitor-simple目录下,使用maven命令进行打包:

mvn clean package -Dmaven.test.skip=true

这里运行jar前,需要查看一下配置文件。将dubbo-monitor-simple-2.0.0-assembly.tar.gz复制并解压到指定文件夹下,查看其conf目录下的配置文件:

// Zookeeper注册中心地址
dubbo.registry.address=zookeeper://127.0.0.1:2181
//监控中心于其他服务通信端口
dubbo.protocol.port=7070
//监控中心web页面访问端口
dubbo.jetty.port=8080

之后,进入dubbo-monitor-simple-2.0.0\assembly.bin目录,运行start.bat。

进入浏览器查看监控中心:


此时监控中心还没有消费者。


② 修改服务提供者/消费者配置

在consumer.xml中添加如下配置:

<dubbo:monitor protocol="registry"></dubbo:monitor>

在provider.xml中如下配置:

<dubbo:monitor address="127.0.0.1:7070"></dubbo:monitor>


这两种有什么区别?参考官方文档:



重新启动provider和consumer,提供者向消费者索取服务再次查看Monitor,将会发现com.alibaba.dubbo.monitor.MonitorService对应的consumer有两个:provider和consumer都是MonitorService的消费者!


项目GitHub地址:点击下载


相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
目录
相关文章
|
2月前
|
存储 缓存 NoSQL
分布式系统架构8:分布式缓存
本文介绍了分布式缓存的理论知识及Redis集群的应用,探讨了AP与CP的区别,Redis作为AP系统具备高性能和高可用性但不保证强一致性。文章还讲解了透明多级缓存(TMC)的概念及其优缺点,并详细分析了memcached和Redis的分布式实现方案。此外,针对缓存穿透、击穿、雪崩和污染等常见问题提供了应对策略,强调了Cache Aside模式在解决数据一致性方面的作用。最后指出,面试中关于缓存的问题多围绕Redis展开,建议深入学习相关知识点。
205 8
|
4天前
|
消息中间件 人工智能 自然语言处理
基于 RocketMQ 事件驱动架构的 AI 应用实践
基于 RocketMQ 事件驱动架构的 AI 应用实践
|
8天前
|
Kubernetes 监控 Serverless
基于阿里云Serverless Kubernetes(ASK)的无服务器架构设计与实践
无服务器架构(Serverless Architecture)在云原生技术中备受关注,开发者只需专注于业务逻辑,无需管理服务器。阿里云Serverless Kubernetes(ASK)是基于Kubernetes的托管服务,提供极致弹性和按需付费能力。本文深入探讨如何使用ASK设计和实现无服务器架构,涵盖事件驱动、自动扩展、无状态设计、监控与日志及成本优化等方面,并通过图片处理服务案例展示具体实践,帮助构建高效可靠的无服务器应用。
|
8天前
|
监控 Kubernetes Cloud Native
基于阿里云容器服务Kubernetes版(ACK)的微服务架构设计与实践
本文介绍了如何基于阿里云容器服务Kubernetes版(ACK)设计和实现微服务架构。首先概述了微服务架构的优势与挑战,如模块化、可扩展性及技术多样性。接着详细描述了ACK的核心功能,包括集群管理、应用管理、网络与安全、监控与日志等。在设计基于ACK的微服务架构时,需考虑服务拆分、通信、发现与负载均衡、配置管理、监控与日志以及CI/CD等方面。通过一个电商应用案例,展示了用户服务、商品服务、订单服务和支付服务的具体部署步骤。最后总结了ACK为微服务架构提供的强大支持,帮助应对各种挑战,构建高效可靠的云原生应用。
|
21天前
|
存储 SQL 监控
转转平台IM系统架构设计与实践(二):详细设计与实现
以转转IM架构为起点,介绍IM相关组件以及组件间的关系;以IM登陆和发消息的数据流转为跑道,介绍IM静态数据结构、登陆和发消息时的动态数据变化;以IM常见问题为风景,介绍保证IM实时性、可靠性、一致性的一般方案;以高可用、高并发为终点,介绍保证IM系统稳定及性能的小技巧。
29 6
|
2月前
|
存储 缓存 关系型数据库
社交软件红包技术解密(六):微信红包系统的存储层架构演进实践
微信红包本质是小额资金在用户帐户流转,有发、抢、拆三大步骤。在这个过程中对事务有高要求,所以订单最终要基于传统的RDBMS,这方面是它的强项,最终订单的存储使用互联网行业最通用的MySQL数据库。支持事务、成熟稳定,我们的团队在MySQL上有长期技术积累。但是传统数据库的扩展性有局限,需要通过架构解决。
78 18
|
6天前
|
监控 Cloud Native Java
基于阿里云容器服务(ACK)的微服务架构设计与实践
本文介绍如何利用阿里云容器服务Kubernetes版(ACK)构建高可用、可扩展的微服务架构。通过电商平台案例,展示基于Java(Spring Boot)、Docker、Nacos等技术的开发、容器化、部署流程,涵盖服务注册、API网关、监控日志及性能优化实践,帮助企业实现云原生转型。
|
2月前
|
存储 缓存 安全
分布式系统架构7:本地缓存
这是小卷关于分布式系统架构学习的第10篇文章,主要介绍本地缓存的基础理论。文章分析了引入缓存的利弊,解释了缓存对CPU和I/O压力的缓解作用,并讨论了缓存的吞吐量、命中率、淘汰策略等属性。同时,对比了几种常见的本地缓存工具(如ConcurrentHashMap、Ehcache、Guava Cache和Caffeine),详细介绍了它们的访问控制、淘汰策略及扩展功能。
87 6
|
3月前
|
弹性计算 API 持续交付
后端服务架构的微服务化转型
本文旨在探讨后端服务从单体架构向微服务架构转型的过程,分析微服务架构的优势和面临的挑战。文章首先介绍单体架构的局限性,然后详细阐述微服务架构的核心概念及其在现代软件开发中的应用。通过对比两种架构,指出微服务化转型的必要性和实施策略。最后,讨论了微服务架构实施过程中可能遇到的问题及解决方案。
|
4月前
|
Cloud Native Devops 云计算
云计算的未来:云原生架构与微服务的革命####
【10月更文挑战第21天】 随着企业数字化转型的加速,云原生技术正迅速成为IT行业的新宠。本文深入探讨了云原生架构的核心理念、关键技术如容器化和微服务的优势,以及如何通过这些技术实现高效、灵活且可扩展的现代应用开发。我们将揭示云原生如何重塑软件开发流程,提升业务敏捷性,并探索其对企业IT架构的深远影响。 ####
88 3

热门文章

最新文章