微服务综合文档

微服务综合

微服务是为了解耦
业务领域定义了边界

系统架构需要遵循三个标准

  • 提高敏捷性:及时响应业务需求,促进企业发展
  • 提升用户体验:提升用户体验,减少用户流失
  • 降低成本:降低增加产品、客户或业务方案的成本

cap

c 一致性
a 可用性
p 分区容错性

微服务需要解决的问题

  • 客户端如何访问这些服务
    • api网关
  • 每个服务之间如何通信
    • 同步 对内 RPC 对外 REST
      • http -> 跨防火墙
      • rpc -> 传输效率高
    • 异步
      • 消息队列
  • 如此多的服务如何治理
    • 服务注册与发现 (服务注册中心) 水平扩展实现
  • 服务挂了如何解决
    • 网络是不可靠的
      • 重试机制
      • 限流
      • 熔断机制
      • 负载均衡
      • 降级 (本地缓存)

微服务设计模式

  • 聚合器
  • 代理
  • 链式
  • 分支
  • 数据共享
  • 异步消息

什么是bean

pojo 原生java对象
bean 有业务的叫bean

响应式

异步非阻塞
全程异步化

http 无状态

session 就是 cookie
前端 -> 服务器
请求 -> 响应

ajax 轮询
tcp 建立长连接
WebSocket 长连接
响应式变成

WebFlux 基于 Netty 实现异步响应式编程
观察者模式

spring boot 优缺点

优点

  • 快速构建项目
  • 对主流开发框架的无配置集成
  • 项目可独立运行,无需外部依赖serclet容器
  • 提供运行时的应用监控
  • 极大的提高了开发、部署效率
  • 与云计算的天然集成
  • 开箱即用

缺点

  • 版本迭代速度快,一些模块改动很大
  • 由于自己不做配置,报错难定位

Thymeleaf

Thymeleaf 是 互联网项目进化的一个中间产物

动态动静分离前后分离
jspThymeleafvue.js、reast.js等

Hikari

快速、简单、可靠
字节码简洁
优化代理和拦截器
自定义数组类型 代替 ArrayList
自定义集合类型
其他针对 BoneCP 缺陷的优化

Spring Cloud Alibaba

主要功能

  • 服务限流降级
  • 服务注册与发现
  • 分布式配置管理
  • 消息驱动能力
  • 阿里云对象存储
  • 分布式任务调度

组件

  • sentinel 把流量最为切入点 从流量控制 熔断降级 系统负载保护等多个维度保护服务的稳定性
  • nacos 一个更易构建云原生应用的动态服务发现、配置管理和服务管理的平台
  • RocketMQ 一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务
  • Dubbo 一款高性能的Java RPC框架
  • Seata 一个易于使用的高性能微服务分布式事务解决方案
  • Alibaba Cloude ACM 一款在分布式架构环境中对应用配置进行集中管理和推送的应用配置中心产品
  • Alibaba Cloud OSS 阿里云对象存储服务
  • Alibaba Cloud SchedulerX 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于Cron表达式)任务调度服务
  • Alibaba Cloud SMS 覆盖全球的短信服务、友好、高效、智能的互联网化通讯能力

元数据

描述数据的数据

nacos

nacos 可以使用docker版本,方便我们快速部署

clone项目

git clone https://github.com/nacos-group/nacos-docker.git
cd nacos-docker

单机模式启动

# standalone-mysql.yaml 可能有 standalone-mysql-5.7.yaml 等
# docker-compose 默认是找寻 docker-compose.yml的,我们需要使用 -f 来选择自定义的配置文件 -d 后台运行
docker-compose -f example/standalone-mysql.yaml up -d

查看日志

docker-compose -f example/standalone-mysql.yaml logs -f

nacos控制台

#默认是8848端口
http://ip:8848/nacos
#账号密码都是 nacos

Nacos Config 远程

可以多环境配置

http://ip:8848 的nacos中新建一个配置

image-20200229192816559

spring:
  application:
    # 服务名
    name: service-consumer
  cloud:
    nacos:
      #服务注册中心
      discovery:
        server-addr: ip:8848
server:
  # 服务端口
  port: 8080
management:
  # 端点检查(健康检查)
  endpoints:
    web:
      exposure:
        include: "*"
myValue: "造梦弥豆子"

需要在 pom.xml 引入Nacos Config Starter

需要使用2.1的版本,2.2中暂无 spring.cloud.nacos.config. 相关配置

<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  <version>2.1.0.RELEASE</version>
</dependency>

bootstrap.properties 配置

spring.application.name=service-consumer-config
spring.cloud.nacos.config.server-addr=ip:8848
spring.cloud.nacos.config.file-extension=yaml

注解

@EnableDiscoveryClient spring cloud中 需要在 Application 来启动服务发现

@EnabelFeignClients 开启feign支持

feign 配置

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
  <version>2.2.1.RELEASE</version>
</dependency>

@RefreshScope 使用远程配置文件

Spring 配置文件加载优先级

Bootstrap.properties -> bootstrap.yml -> application.properties -> application .yml

Nacos 多环境配置

操作起来很简单,只需要为不同的环境编写专门的配置文件,如:application-dev.ymlapplication-prod.yml, 启动项目时只需要增加一个命令参数 --spring.profiles.active= 环境配置即可

java -jar 1.0.0-SNAPSHOT.jar --spring.profiles.active=prod

什么是 Nacos Config Profile

spring-cloud-starter-alibaba-nacos-config 在加载配置的时候,不仅仅加载了以 dataid 为 ${spring.application.name}.${file-extension:properties} 为前缀的基础配置,还加载了 dataid 为 ${spring.application.name}-${profile}.${file-extension:properties} 的基础配置。在日常开发中如果遇到多套环境下的不同配置,可以通过 Spring 提供的 ${spring.profiles.active} 这个配置项来配置。

添加不同环境的配置

image-20200301151125489

然后在我们的 resources 中新增 多个配置文件

image-20200301151227787

spring.profiles.active=prod
spring.application.name=service-provider-config
spring.cloud.nacos.config.server-addr=ip:8848
spring.cloud.nacos.config.file-extension=yaml

idea 中可以选择启动的环境

image-20200301151335258

sentinel 分布式系统流量防卫兵

什么是服务雪崩

在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以通过 HTTP/RPC 相互调用,在 Spring Cloud 中可以用 RestTemplate + LoadBalanceClientFeign 来调用。为了保证其高可用,单个服务通常会集群部署。由于网络原因或者自身的原因,服务并不能保证 100% 可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet 容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的 “雪崩” 效应。为了解决这个问题,业界提出了 熔断器模型

阿里巴巴开源了 Sentinel 组件,实现了熔断器模式,Spring Cloud 对这一组件进行了整合。在微服务架构中,一个请求需要调用多个服务是非常常见的

img

较底层的服务如果出现故障,会导致连锁故障。当对特定的服务的调用的不可用达到一个阀值熔断器将会被打开

img

熔断器打开后,为了避免连锁故障,通过 fallback 方法可以直接返回一个固定值。

什么是 Sentinel

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

Sentinel 的特征

  • 丰富的应用场景: Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷(对于突然到来的大量请求,您可以配置流控规则,以稳定的速度逐步处理这些请求,从而避免流量突刺造成系统负载过高)、集群流量控制、实时熔断下游不可用应用等
  • 完备的实时监控: Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况
  • 广泛的开源生态: Sentinel 提供开箱即用的与其它开源框架 / 库的整合模块,例如与 Spring CloudDubbogRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel
  • 完善的 SPI 扩展点: Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等

Sentinel 的主要特征

img

Sentinel 的组成

  • 核心库(Java 客户端): 不依赖任何框架 / 库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持
  • 控制台(Dashboard): 基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器

Sentinel 控制台

概述

Sentinel 提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和集群),规则管理和推送的功能。另外,鉴权在生产环境中也必不可少。这里,我们将会详细讲述如何通过简单的步骤就可以使用这些功能。Sentinel 控制台最少应该包含如下功能

  • 查看机器列表以及健康情况: 收集 Sentinel客户端发送的心跳包,用于判断机器是否在线。
  • 监控 (单机和集群聚合): 通过 Sentinel 客户端暴露的监控 API,定期拉取并且聚合应用监控信息,最终可以实现秒级的实时监控。
  • 规则管理和推送: 统一管理推送规则。
  • 鉴权: 生产环境中鉴权非常重要。这里每个开发者需要根据自己的实际情况进行定制。

启动控制台

获取

您可以从 官方 GitHub Release 页面 页面下载最新版本的控制台 JAR 包。

启动

启动 Sentinel 控制台需要 JDK 版本为 1.8 及以上版本

nohup java -Dserver.port=8999 -Dcsp.sentinel.dashboard.server=localhost:8999 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.7.1.jar &

其中 -Dserver.port=8080 用于指定 Sentinel 控制台端口为 8080

从 Sentinel 1.6.0 起,Sentinel 控制台引入基本的 登录 功能,**默认用户名和密码都是 sentinel **

鉴权

用户可以通过如下参数进行配置

  • -Dsentinel.dashboard.auth.username=sentinel 用于指定控制台的登录用户名为 sentinel
  • -Dsentinel.dashboard.auth.password=123456 用于指定控制台的登录密码为 123456;如果省略这两个参数,默认用户和密码均为 sentinel
  • -Dserver.servlet.session.timeout=7200 用于指定 Spring Boot 服务端 session 的过期时间,如 7200表示 7200 秒;60m 表示 60 分钟,默认为 30 分钟
Nacos的配置
spring:
  application:
    name: service-consumer
  cloud:
    nacos:
      discovery:
        server-addr: 119.23.57.96:8848
    sentinel:
      transport:
        dashboard: 119.23.57.96:8999
feign:
  hystrix:
    enabled: true
server:
  port: 8080
management:
  endpoints:
    web:
      exposure:
        include: "*"
myValue: "造梦弥豆子"

新增一个Fallback

package com.czq.spring.cloud.alibaba.consumer.service.fallback;

import com.czq.spring.cloud.alibaba.consumer.service.EchoService;
import org.springframework.stereotype.Component;

// 给 spring 托管
@Component
public class EchoServiceFallback implements EchoService {

    @Override
    public String echo(String string) {
        return "你的网络有问题";
    }

    @Override
    public String lb() {
        return "你的网络有问题";
    }
}
EchoServer 中加入注解配置
@FeignClient(name= "service-provider",fallback = EchoServiceFallback.class)

Sentinel 需要在服务部署的同服务器启动否则无法成功熔断

**Dobbo **

什么是Dobbo

Apache Dubbo (incubating) |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC 分布式服务框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。她最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。从服务模型的角度来看,Dubbo 采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方(Provider)和服务消费方(Consumer)两个角色。

高可用 崩溃恢复

高性能 Jvm Tomcat RPC

高并发 垂直拓展 水平拓展

img

节点角色说明

节点角色说明
Provider暴露服务的服务提供方
Consumer调用远程服务的服务消费方
Registry服务注册与发现的注册中心
Monitor统计服务的调用次数和调用时间的监控中心
Container服务运行容器

image-20200301185543970

调用关系

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

Dubbo 功能特点

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

什么是RPC

分布式是促使 RPC 诞生的领域,RPC 是一种编程模型,并没有规定你具体要怎样实现,无论使用 HTTP 或是 RMI 都是可以的。

假设你有一个计算器接口,Calculator,以及它的实现类 CalculatorImpl,那么在系统还是 单体应用 时,你要调用 Calculator 的 add 方法来执行一个加运算,直接 new 一个 CalculatorImpl,然后调用 add 方法就行了,这其实就是非常普通的 本地函数调用,因为在 同一个地址空间,或者说在同一块内存,所以通过方法栈和参数栈就可以实现。

img

现在,基于高性能和高可靠等因素的考虑,你决定将系统改造为分布式应用,将很多可以共享的功能都单独拎出来,比如上面说到的计算器,你单独把它放到一个服务里头,让别的服务去调用它。

img

这下问题来了,服务 A 里头并没有 CalculatorImpl 这个类,那它要怎样调用服务 B 的 CalculatorImpl 的 add 方法呢?

RPC 要解决的两个问题

  • 解决分布式系统中,服务之间的调用问题
  • 远程调用时,要能够像本地调用一样方便,让调用者感知不到远程调用的逻辑

如何实现RPC

实际情况下,RPC 很少用到 HTTP 协议来进行数据传输,毕竟我只是想传输一下数据而已,何必动用到一个文本传输的应用层协议呢,我为什么不直接使用二进制传输?比如直接用 Java 的 Socket 协议进行传输?

不管你用何种协议进行数据传输,一个完整的 RPC 过程,都可以用下面这张图来描述

img

以左边的 Client 端为例,Application 就是 RPC 的调用方,Client Stub 就是我们上面说到的代理对象,也就是那个看起来像是 Calculator 的实现类,其实内部是通过 RPC 方式来进行远程调用的代理对象,至于 Client Run-time Library,则是实现远程调用的工具包,比如 JDK 的 Socket,最后通过底层网络实现实现数据的传输。

这个过程中最重要的就是 序列化反序列化 了,因为数据传输的数据包必须是二进制的,你直接丢一个 Java 对象过去,人家可不认识,你必须把 Java 对象序列化为二进制格式,传给 Server 端,Server 端接收到之后,再反序列化为 Java 对象。

RPC vs Restful

RPC 是面向过程Restful 是面向资源,并且使用了 HTTP 动词。从这个维度上看,Restful 风格的 URL 在表述的精简性、可读性上都要更好。

阿里为何放弃 Zookeeper

CAP

有个思考,从 CAP 角度考虑,服务注册中心是 CP 系统还是 AP 系统呢?

  • 服务注册中心是为了服务间调用服务的,那么绝对不允许因为服务注册中心出现了问题而导致服务间的调用出问题
  • 假如有 node1,node2,node3 集群节点。保存着可用服务列表 ip1,ip2,ip3,试想如果此时不一致,比如 node1 只保存了ip1,ip2,此时服务读取 node1 的节点,那么会造成什么影响?

调用 node1 的服务,顶多就是负载均衡时不会有流量打到 ip3,然后等 node1 同步回 ip3 后,又一致了,这对服务其实没什么太大影响。所以,推测出服务注册中心应该是个 AP 系统。

Zookeeper 是个 CP 系统,强一致性

  • 场景1,当 master 挂了,此时 Zookeeper 集群需要重新选举,而此时服务需要来读取可用服务,是不可用的。影响到了服务的可用性当然你可以说服务本地有缓存可用列表。然而下面这种方式就更无法处理了。
  • 场景2,分区可用。试想,有 3 个机房,如果其中机房 3 和机房 1,2 网络断了,那么机房 3 的注册中心就不能注册新的机器了,这显然也不合理从健康检查角度来看

img

Zookeeper 是通过 TCP 的心跳判断服务是否可用,但 TCP 的活性并不代表服务是可用的,如:连接池已满,DB 挂了等

理想的注册中心

  • 服务自动注册发现。最好有新的服务注册上去时还能推送到调用端
  • 能对注册上来的机器方便的进行管理,能手动删除(发送信号让服务优雅下线)、恢复机器
  • 服务的健康检查,能真正的检测到服务是否可用
  • 可以看到是否有其他调用服务正在订阅注册上来的服务
  • 能够带上些除了 IP 外的其它信息

Dubbo 服务注册与发现

概述

由于我们已经有了 Nacos 注册中心,Sentinel熔断限流控制中心,所以我们不再使用 ZookeeperDubbo Admin 来管理我们的 Dubbo 应用程序,Dubbo 仅当作我们微服务中的 RPC 通信框架,真正实现对内 RPC,对外 REST

创建服务提供者

创建一个名为 hello-apache-dubbo-provider 的服务提供者项目,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>
    <parent>
        <groupId>com.funtl</groupId>
        <artifactId>hello-apache-dubbo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>hello-apache-dubbo-provider</artifactId>
    <packaging>pom</packaging>
    <url>http://www.funtl.com</url>
    <inceptionYear>2018-Now</inceptionYear>
    <licenses>
        <license>
            <name>Apache 2.0</name>
            <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
        </license>
    </licenses>
    <developers>
        <developer>
            <id>liwemin</id>
            <name>Lusifer Lee</name>
            <email>lee.lusifer@gmail.com</email>
        </developer>
    </developers>
    <modules>
        <module>hello-apache-dubbo-provider-api</module>
        <module>hello-apache-dubbo-provider-service</module>
    </modules>
</project>
创建服务提供者的接口模块

创建一个名为 hello-apache-dubbo-provider-api 的模块(该模块只负责定义接口),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>
    <parent>
        <groupId>com.funtl</groupId>
        <artifactId>hello-apache-dubbo-provider</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>hello-apache-dubbo-provider-api</artifactId>
    <packaging>jar</packaging>
    <url>http://www.funtl.com</url>
    <inceptionYear>2018-Now</inceptionYear>
    <licenses>
        <license>
            <name>Apache 2.0</name>
            <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
        </license>
    </licenses>
    <developers>
        <developer>
            <id>liwemin</id>
            <name>Lusifer Lee</name>
            <email>lee.lusifer@gmail.com</email>
        </developer>
    </developers>
</project>
定义接口
package com.funtl.apache.dubbo.provider.api;
public interface EchoService {
    String echo(String string);
}
创建服务提供者接口实现

创建一个名为 hello-apache-dubbo-provider-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>
    <parent>
        <groupId>com.funtl</groupId>
        <artifactId>hello-apache-dubbo-provider</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>hello-apache-dubbo-provider-service</artifactId>
    <packaging>jar</packaging>
    <url>http://www.funtl.com</url>
    <inceptionYear>2018-Now</inceptionYear>
    <licenses>
        <license>
            <name>Apache 2.0</name>
            <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
        </license>
    </licenses>
    <developers>
        <developer>
            <id>liwemin</id>
            <name>Lusifer Lee</name>
            <email>lee.lusifer@gmail.com</email>
        </developer>
    </developers>
    <dependencies>
        <!-- Spring Boot Begin -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Spring Boot End -->
        <!-- Apache Dubbo Begin -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo-registry-nacos</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.spring</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <!-- Apache Dubbo End -->
        <!-- Projects Begin -->
        <dependency>
            <groupId>com.funtl</groupId>
            <artifactId>hello-apache-dubbo-provider-api</artifactId>
            <version>${project.parent.version}</version>
        </dependency>
        <!-- Projects End -->
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.funtl.apache.dubbo.provider.ProviderApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
application.yml

主要增加了 Dubbo 包扫描路径和 Nacos Server 配置

spring:
  application:
    name: dubbo-provider
  main:
    allow-bean-definition-overriding: true
dubbo:
  scan:
    base-packages: com.funtl.apache.dubbo.provider.service
  protocol:
    name: dubbo
    # 自动分配
    port: -1 
  registry:
    address: nacos://119.23.57.96:8848

Application

package com.funtl.apache.dubbo.provider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}

Service

通过 org.apache.dubbo 包下的 @Service 注解将服务暴露出去

package com.funtl.apache.dubbo.provider.service;
import com.funtl.apache.dubbo.provider.api.EchoService;
import org.apache.dubbo.config.annotation.Service;
@Service(version = "1.0.0")
public class EchoServiceImpl implements EchoService {
    @Override
    public String echo(String string) {
        return "Echo Hello Dubbo " + string;
    }
}
创建服务消费者

创建一个名为 hello-apache-dubbo-consumer 的服务消费者项目,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>
    <parent>
        <groupId>com.funtl</groupId>
        <artifactId>hello-apache-dubbo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>hello-apache-dubbo-consumer</artifactId>
    <packaging>jar</packaging>
    <url>http://www.funtl.com</url>
    <inceptionYear>2018-Now</inceptionYear>
    <licenses>
        <license>
            <name>Apache 2.0</name>
            <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
        </license>
    </licenses>
    <developers>
        <developer>
            <id>liwemin</id>
            <name>Lusifer Lee</name>
            <email>lee.lusifer@gmail.com</email>
        </developer>
    </developers>
    <dependencies>
        <!-- Spring Boot Begin -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Spring Boot End -->
        <!-- Apache Dubbo Begin -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo-registry-nacos</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.spring</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <!-- Apache Dubbo End -->
        <!-- Projects Begin -->
        <dependency>
            <groupId>com.funtl</groupId>
            <artifactId>hello-apache-dubbo-provider-api</artifactId>
            <version>${project.parent.version}</version>
        </dependency>
        <!-- Projects End -->
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.funtl.apache.dubbo.consumer.ConsumerApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
application.yml

主要增加了 Dubbo 包扫描路径、健康检查以及 Nacos Server 配置

spring:
  application:
    name: dubbo-consumer
  main:
    allow-bean-definition-overriding: true
dubbo:
  scan:
    base-packages: com.funtl.apache.dubbo.consumer.controller
  protocol:
    name: dubbo
    port: -1
  registry:
    address: nacos://192.168.141.132:8848
server:
  port: 8080
endpoints:
  dubbo:
    enabled: true
management:
  health:
    dubbo:
      status:
        defaults: memory
        extras: threadpool
  endpoints:
    web:
      exposure:
        include: "*"
Application
package com.funtl.apache.dubbo.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
}
Controller

通过 org.apache.dubbo 包下的 @Reference 注解像调用本地服务一样调用远程服务,轻松实现透明的远程过程调用

package com.funtl.apache.dubbo.consumer.controller;
import com.funtl.apache.dubbo.provider.api.EchoService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class EchoController {
    @Reference(version = "1.0.0")
    private EchoService echoService;
    @GetMapping(value = "/echo/{string}")
    public String echo(@PathVariable String string) {
        return echoService.echo(string);
    }
}

Dubbo 实现高速序列化

Dubbo中的序列化
  • 序列化 Http 只能字符串传输
    • 将对象装换成二进制 -> 传输需要时间 解压缩
    • Json 字符串序列化
  • 反序列化
    • 将二进制转换成对象
    • Json 字符串反序列化

Dubbo RPC 是 Dubbo 体系中最核心的一种高性能、高吞吐量的远程调用方式,可以称之为多路复用的 TCP1 长连接调用:

  • 长连接: 避免了每次调用新建 TCP 连接,提高了调用的响应速度
  • 多路复用: 单个TCP 连接可交替传输多个请求和响应的消息,降低了连接的等待闲置时间,从而减少了同样并发数下的网络连接数,提高了系统吞吐量

拓展阅读

TPC

注脚


  1. TCP 三次握手 四次挥手 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值