前言

简介

组件



Nacos

简介

  • Nacos 致力于帮助您发现、配置和管理微服务;
  • Service 是 Nacos 世界的一等公民,支持几乎所有主流类型的服务:
    • Kubernetes Service
    • gRPC & Dubbo RPC Service
    • Spring Cloud RESTful Service
  • 特性
    • 服务发现和服务健康监测;
    • 动态服务配置;
    • 动态 DNS 服务;
    • 服务及元数据管理;
  • 地图
  • 资料
    • 源码地址:https://github.com/alibaba/nacos.git
    • 历史版本:https://github.com/alibaba/nacos/releases
    • 文档地址:https://nacos.io/zh-cn/index.html

安装与应用

  • 依赖
    • 64 位 JDK 1.8+;
    • Maven 3.2.x+;
  • 安装
    • Windows
      • 从历史版本中下载 Zip 包,解压到本地即可使用;
    • Linux
      • 源码方式
        • cd /projectCode
        • git clone https://github.com/alibaba/nacos.git
        • cd nacos
        • mvn clean install -U -Dmaven.test.skip=true -Prelease-nacos
        • cd distribution/target/nacos-server-2.0.4/nacos/bin
      • 压缩包方式
        • wget https://github.com/alibaba/nacos/releases/download/1.4.3/nacos-server-1.4.3.tar.gz
        • tar -zxvf nacos-server-1.4.3.tar.gz -C /usr/
        • firewall-cmd --zone=public --add-port=8848/tcp --permanent
        • firewall-cmd --reload
        • firewall-cmd --zone=public --list-ports
  • 运行
    • Windows
      • startup.cmd -m standalone ---- 开启服务,默认为集群方式启动,启动报错,需改为单机版方式 standalone
      • shutdown.cmd ---- 关闭服务;
    • Linux
      • cd /usr/nacos/bin
      • sh startup.sh -m standalone ---- 开启服务,standalone 单机运行模式;
      • bash startup.sh -m standalone ---- Ubuntu 开启服务;
      • sh shutdown.sh ---- 关闭服务;
    • 访问主页:http://127.0.0.1:8848/nacos/
      • 用户名/密码:nacos/nacos;
  • 应用
    • 服务管理
      • 服务注册
        • curl -X POST "http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=springBoot&ip=127.0.0.1&port=80"
      • 服务发现
        • curl -X GET "http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=springBoot"
    • 配置管理
      • 发布配置
        • curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=HelloWorld"
      • 获取配置
        • curl -X GET "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test"
    • 命名空间
      • 用于区分不同的部署环境,实现隔离,不同的命名空间逻辑上是隔离的,其主要作用是区分服务使用的范围,比如开发、测试、生产、灰度四个命名空间来互相隔离;

Parent Project

  • 版本管理
    • 参考 https://github.com/alibaba/spring-cloud-alibaba/wiki/版本说明;
    • Spring Boot 版本: 2.6.3;
    • Spring Cloud 版本:Spring Cloud 2021.0.1;
    • Spring Cloud Alibaba 版本:2021.0.1.0;
  • 搭建 Maven Java 项目
    • 参考 Tool_IDE 创建 java_spring_cloud_alibaba;
    • 删除 src,项目右键 properties ---- Java Build Path ---- Source,删除 Source 包;
  • Pom 依赖
    • 指定打包类型:<packaging>pom</packaging>
    • 1
    • 2

Entity Module

  • 说明
    • 将微服务中使用的 Entity 抽取出来放在该模块中,方便统一管理;
  • 搭建 Maven 子模块项目
    • 参考 Tool_IDE 创建 alibaba_entity;
  • Pom 依赖
    • 未指定版本,继承父版本,好处是在子 Module 相互引用时,可通过 ${version} 指定子 Module 的版本;
    • 1
    • 2
  • 引入 Entity;
  • 项目打包;

Service Module Test

Service Module Account

配置中心

  • 说明
    • Nacos 除了微服务的注册与发现之外,还将配置中心整合在了一起,我们可以将整个架构体系内的所有配置都集中在 Nacos 中存储;
    • 我们将改造微服务 Service Module Test 和 Service Module Account;
  • Service Module Account
    • Pom 依赖
      • 1
      • 2
    • 配置
      • 创建 bootstrap.properties 父上下级配置文件,配置以下部分;
        • 1
        • 2
      • Nacos 主页创建微服务配置;
        • http://127.0.0.1:8848/nacos
        • 配置服务 ---- 配置列表 ---- 新建配置;
        • Data ID:${prefix}-${spring.profiles.active}.${file-extension}
          • ${prefix} ---- 默认 spring.application.name,也可通过 spring.cloud.nacos.config.prefix 配置;
          • ${spring.profiles.active} ---- 环境,通过 spring.profiles.active 配置,若不配置,则没有 -${spring.profiles.active} 这部分
          • ${file-extension} ---- 文件后缀,通过 spring.cloud.nacos.config.file-extension 配置;
        • Group:暂时使用默认;
        • 配置内容
          • application.properties 中,一部分内容移植到了 bootstrap.properties 中,其余部分移植到此处,本案例没有其余配置,故而新增配置测试项;
          • 1
          • 2
      • application.properties 更名为 applicationBack.properties;
    • 应用
      • ConfigController
        • 配置测试接口,添加 @RefreshScope 注解,用于自动刷新;
        • 1
        • 2
      • 访问:127.0.0.1:8004/api/config
      • Nacos 修改对应配置文件内容;
      • 再次访问:127.0.0.1:8004/api/config,配置已经刷新;
  • Service Module Test
    • 改造方式同上;
  • Group 方案
    • 如果需要自定义分组名称,则在创建配置时指定分组名即可;
    • bootstrap.properties 添加 spring.cloud.nacos.config.group=* 配置;
  • NameSpace 方案
    • Nacos 创建不同的命名空间,自动生成 id;
    • bootstrap.properties 添加 spring.cloud.nacos.config.namespace=* 配置;
  • 思考
    • 配置虽能自动刷新,但只是值更新,启动服务用到的配置并未重新初始化;


服务调用

  • 说明
    • Service Module Account 中的 User 接口调用 Service Module Test 中的 City 接口,实现微服务接口调用;
    • 注册中心无论使用 Eureka Server 还是使用 Nacos,对应用层是没有影响的,这归功于 Spring Cloud Common 的封装,它在服务的注册与发现、客户端负载均衡等方面做了很好的抽象,具体实现由各厂商的中间件完成,应用层依赖于这些接口,不会关注具体的实现,就好比于 JDBC 接口,具体由什么数据库实现,应用层并不关心;
    • 调用方式
      • RestTemplate
      • OpenFeign
      • WebClient:Spring 5 引入的 Spring Reative Web 框架,WebClient 相当于 Reative 版的 RestTemplate;

OpenFeign

  • Pom 依赖
    • 消费者 Service Module Account;
    • 1
    • 2
  • 配置
    • 启动类添加 @EnableFeignClients 注解;
  • 应用
    • 在 service 包下创建 CityFeignClient 接口,用于调用 Service Module Test 微服务接口;
      • 1
      • 2
    • UserServiceImpl
      • 1
      • 2
    • 访问接口:127.0.0.1:8004/api/user/1


负载均衡

  • 说明:
    • Spring Cloud 2020 之前版本,默认使用 Netflix Ribbon 作为负载均衡器,Nacos 也集成了 Ribbon(很奇怪为啥没有替换掉),但 Spring Cloud 2020 版本之后推荐使用 Spring Cloud Loadbalancer;
    • Spring Cloud Loadbalancer 介绍参见 Spring_Cloud;

Loadbalancer

  • 微服务多实例
    • Service Module Test 启动三个实例:8001、8002、8003;
    • 访问 Nacos 服务列表:http://127.0.0.1:8848/nacos,微服务注册成功;
    • 访问 127.0.0.1:8004/api/user/1,刷新页面可见,OpenFeign 使用轮询方式调用 City 接口;
  • Service Module Account
    • Pom 依赖
      • 上一步已引入;
    • 配置
      • CustomLoadBalancerConfig
        • 1
        • 2
      • 启动类添加 @LoadBalancerClient 注解;
        • 1
        • 2
    • 应用
      • 启动 Service Module Account,访问 127.0.0.1:8004/api/user/1,刷新页面可见,OpenFeign 使用随机方式调用 City 接口;


网关

Gateway

  • 在此用另外一个项目的示例做说明。
  • 创建 spring_cloud_gateway 子模块。
  • Pom 依赖
    • 1
    • 2
  • application.properties
    • 1
    • 2
  • 启动类
    • 1
    • 2
  • 测试
    • http://127.0.0.1:8001/api/common/dictionary/imageType
    • http://127.0.0.1:8000/api/common/dictionary/imageType


Sentinel

简介

  • 主要特性
  • 两大部分
    • 核心库(Java 客户端):不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持;
    • 控制台(Dashboard):基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器;
  • 文档地址:https://github.com/alibaba/Sentinel/wiki/介绍;
  • 仓库地址:https://github.com/alibaba/Sentinel;

安装与运行

  • 历史版本:https://github.com/alibaba/Sentinel/releases;
  • 下载到本地,CMD 运行
    • 默认 8080 端口运行,可能与其它软件冲突,故选择 9090 端口;
    • java -jar sentinel-dashboard-1.8.3.jar --server.port=9090
  • 访问:127.0.0.1:9090 sentinel | sentinel;

添加微服务

  • Service Module Test & Service Module Account,添加方式相同;
  • Pom 依赖
    • 1
    • 2
  • 配置
    • 上面我们已经开启了 Nacos Config,所以直接在 Nacos 中修改配置;
    • http://127.0.0.1:8848/nacos,修改对应配置列表;
      • 1
      • 2

实时监控

  • 说明
    • 微服务加入了 Sentienl,在调用服务接口时,就会通过内部通信服务把日志信息发送给 Dashboard 服务,并在页面上展示;
  • 实现
    • 启动 Service Module Test 8001、8002、8003;
    • 启动 Service Module Account 8004;
    • 访问 Nacos 服务列表
    • 访问 Service Module Account 接口;
      • http://127.0.0.1:8004/api/user/1
      • http://127.0.0.1:8004/api/config
    • 访问 Sentinel 仪表盘 http://127.0.0.1:9090/#/dashboard/metric/alibaba-service-account,已生成对应的服务;
      • QBS:表示 1 秒的请求数;
      • QPS:表示 1 秒的拒绝请求数;

簇点链路

  • 说明
    • 微服务、Api 调用情况,提供流控、熔断、热点、授权等操作;

流量控制

  • 说明
    • 流量控制(Flow Control),其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性;
  • Service Module Account 实现
    • 对应微服务或接口上添加流控;
    • /api/user/{id},当每秒请求的次数超过阈值,那么会直接返回失败的信息;
    • 浏览器快速刷新 http://127.0.0.1:8004/api/user/1,得到被流控的结果;

熔断降级

  • 说明
    • 服务调用中,如果依赖的服务出现了不稳定的情况,请求的响应时间变长,那么调用方的响应时间也会变长,线程会产生堆积,最终可能耗尽线程池,服务本身也变得不可用,Sentinel 在服务出现不稳定情况时,会对让请求快速失败,避免影响到其他资源而导致级联错误,当资源被降级后,在接下来的时间窗口内,对该资源的调用都自动熔断;
    • 降级策略
      • 慢调用比例
        • 在 1000ms 内请求数超过 5 个,且平均响应时间超过 300ms 的请求的比例(超过 300ms 的请求占总请求的比例)大于 0.4,则该资源自动熔断 10s,10s 后根据下一个请求判断是否再次被熔断;
      • 异常比例
        • 在 1000ms 内请求数超过 5 个,且异常的比例(异常的请求占总请求的比例)大于 0.8,则该资源自动熔断 15s,15s 后根据下一个请求判断是否再次被熔断;
      • 异常数
        • 在 1000ms 内请求数超过 5 个,且异常的请求超过 6 个,那么该资源将自动熔断 20s,20s 后根据下一个请求判断是否再次被熔断;
    • @SentinelResource ---- 降级熔断注解,类似于 @HystrixCommand
      • value:资源名称,必需项;
      • blockHandler:指定流控或降级异常时的处理逻辑;
        • 必须是 public 修饰;
        • 返回类型与原方法一致;
        • 参数类型需要和原方法相匹配,并在最后加 BlockException 类型的参数;
        • 默认需和原方法在同一个类中,若希望使用其他类的函数,可配置 blockHandlerClass,并指定 blockHandlerClass 里面的方法;
      • fallback:指定非流控或降级异常时的处理逻辑;
        • 返回类型与原方法一致;
        • 参数类型需要和原方法相匹配,Sentinel 1.6 开始,也可以在方法最后加 Throwable 类型的参数;
        • 默认需和原方法在同一个类中,若希望使用其他类的函数,可配置 fallbackClass,并制定 fallbackClass 里面的方法;
  • Service Module Account 实现
    • UserServiceImpl,为接口添加流控和熔断处理代码;
      • 1
      • 2
    • 启动项目,调用接口 http://127.0.0.1:8003/api/account/userVo/1/1890;
    • 访问 Sentinel 微服务下簇点链路,找到 getUserVoByUserIdAndCityId 资源(@SentinelResource 注解配置的资源名),添加流控、熔断等规则;

    • 为该资源配置异常数规则;
    • 为该资源配置流控规则;
    • 测试
      • 快速调用接口  http://127.0.0.1:8003/api/account/userVo/1/1890,页面返回 blockHandler 处理结果;
      • 调用接口 http://127.0.0.1:8003/api/account/userVo/-1/1890,页面返回熔断 fallbackHandler  处理结果;


规则持久化

  • 说明
    • 重启微服务或 Sentinel,配置的规则消失,大量的规则配置并未持久化;
    •  推送模式
      • Pull 模式:客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件,甚至是 VCS 等,这样做的方式是简单,缺点是无法及时获取变更
      • Push 模式:规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心,这种方式有更好的实时性和一致性保证;
    • 数据源
      • SentinelProperties 内部提供了 TreeMap 类型的 DataSource 属性用于配置数据源信息,有多种配置:
        • 文件配置
        • Nacos 配置
        • ZooKeeper 配置
        • Apollo 配置
    • 规则类型:参见 com.alibaba.cloud.sentinel.datasource.RuleType;
  • Service Module Account 实现
    • Pom 依赖
      • 1
      • 2
    • 配置
      • Nacos Config ---- alibaba-service-account-dev.properties
        • 由于版本迭代关系,Wiki 或网上配置不一定适用于所有版本,查看 NacosDataSourceProperties 源码分析配置项;
        • 1
        • 2
      • Nacos Config ---- 新建配置
        • 1
        • 2
        • resource:资源名,即限流规则的作用对象;
        • limitApp:流控针对的调用来源,若为 default 则不区分调用来源;
        • grade:限流阈值类型(QPS 或并发线程数);0代表根据并发数量来限流,1 代表根据 QPS 来进行流量控制;
        • count:限流阈值;
        • strategy:调用关系限流策略;
        • controlBehavior:流量控制效果(直接拒绝、Warm Up、匀速排队);
        • clusterMode:是否为集群模式;
    • 应用
      • 重启 Service Module Account 微服务;
      • 访问接口:http://127.0.0.1:8004/api/user/1;
      • 刷新 Sentinel 流控面板,加载配置的规则;
    • 思考
      • Sentinel 控制台、Nacos 控制台均可修改规则;
      • Sentinel 修改规则仅存在于服务的内存中,不会修改 Nacos 中的配置值,重启后恢复原来的值;
      • Nacos 修改规则后,服务的内存中规则会更新,Nacos 中持久化规则也会更新,重启后依然保持;


Seata

简介

  • Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务;
  • 资料地址
    • Seata 项目 Github 地址:https://github.com/seata/seata
    • Seata 中间件下载地址:https://github.com/seata/seata/releases
    • Seata 中文官方文档:http://seata.io/zh-cn/
    • Seata 官方示例:https://github.com/seata/seata-samples
  • 术语
    • XID(Transaction ID):全局唯一的事务 ID;
    • TC (Transaction Coordinator):事务协调者,维护全局和分支事务的状态,驱动全局事务提交或回滚;
    • TM (Transaction Manager):事务管理器,定义全局事务的范围,开始全局事务、提交或回滚全局事务;
    • RM (Resource Manager):资源管理器,管理分支事务处理的资源,与 TC 交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚;
  • 处理过程
    • TM 向 TC 申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的 XID;
    • XID 在微服务调用链路的上下文中传播;
    • RM 向 TC 注册分支事务,将其纳入 XID 对应全局事务的管辖;
    • TM 向 TC 发起针 XID 的全局提交或回滚决议;
    • TC 调度 XID 下管辖的全部分支事务完成提交或回滚请求;
    • -----------------------------------
    • 一阶段
      • 解析 SQL,得到表、操作类型(insert、update、delete)、查询条件;
      • 查询改变前的数据;
      • 执行增删改操作;
      • 查询改变后的数据;
      • 插入回滚日志:把改变前后的数据和 SQL 信息组成一条回滚日志,插入 undo_log 表中(未查到该数据)
      • 向 TC 申请全局锁,生成全局唯一事务 ID(XID);
      • 本地事务提交:业务数据和 undo_log 数据一并提交;
      • 将本地事务提交结果上报给 TC;
    • 二阶段提交
      • TC 收到微服务本地事务提交成功请求,把请求放到一个异步任务队列中;
      • 异步任务将批量地删除相应 undo_log 记录;
    • 二阶段回滚
      • TC 收到微服务本地事务提交失败请求,返回一个回滚请求,微服务开启一个本地事务;
      • 微服务通过 XID 找到对应的 undo_log 记录,并生成回滚 SQL;
      • 执行回滚 SQL,提交本地事务;
      • 将回滚操作事务执行结果报告给 TC;

Server 端

  • 下载
    • https://github.com/seata/seata/releases
  • 文件解读
    • seata-server-1.4.2/conf/README-zh.md
      • Server 端建表 Sql、各种方式部署的脚本;
      • Client 端业务库回滚日志表 Sql、客户端配置等;
      • 配置中心,Seata 在各种注册中心注册,添加配置的脚本;
    • seata-server-1.4.2/conf/registry.conf
      • 指定事务协调者(TC)的注册中心,提供 file 、nacos 、eureka、redis、zk、consul、etcd3、sofa 方式,由 type 指定,默认 file;
      • 指定事务协调者(TC)的配置文件,提供 file、nacos 、apollo、zk、consul、etcd3 方式,由 type 指定,默认 file;
    • seata-server-1.4.2/conf/file.conf
      • 指定事务协调者(TC)数据存储位置,提供 file、db、redis 方式,默认 file;
        • File 方式
          • 本地文件目录,无需配置;
        • DB 方式
          • DataSource:有三种连接池 druid、dbcp、hikari;
          • 创建 seata 库以及 global_table、branch_table、lock_table 表,建表 sql 参见帮助文档;
          • 将 seata-server-1.4.2/lib/jdbc MySQL 对应版本驱动 jar 拷贝到 seata-server-1.4.2/bin 目录下;
  • 配置
    • 事务协调者(TC)的注册中心、配置文件、数据存储地址
      • File 方式:是本地文件系统,无需修改配置;
      • 其他方式:根据实际情况配置;
    • 客户端配置应与服务端配置保持一致;
  • 运行
    • seata-server-1.4.2/bin
      • seata-server.bat
      • sh ./seata-server.sh
      • -------- 启动参数 --------
      • -p:Seata Server 启动端口,默认 8091;
      • -h:注册中心 IP
      • -m:事务日志存储方式,支持 file, db, redis,默认为 file;
      • -n : 用于指定 seata-server 节点 ID,如 1,2,3…… 默认为 1;
      • -e : 指定 seata-server 运行环境,如:dev, test 等, 服务启动时会使用 registry-dev.conf 这样的配置;
    • 启动后提示:Server started, listen port: 8091;
    • 因为使用 file 方式,启动后 bin 目录出现了 sessionStore 文件夹,用于存储事务协调者(TC)相关数据;

业务准备

  • Service Module Test
    • 引入 MySQL、Mybatis,并做相关配置,参见 Spring_Boot 文档;
    • 提供 updateCity 接口:127.0.0.1:8003/api/city,Put 请求,操作 test 数据库 city 表;
  • Service Module Account
    • 引入 MySQL、Mybatis,并做相关配置,参见 Spring_Boot 文档;
    • 提供 updateUser 接口:127.0.0.1:8004/api/user,Put 请求,Service 层两步操作,其一操作 account 数据库 user 表,其二通过 OpenFeign 调用 updateCity 接口操作 test 数据库 City 表;
  • 模拟场景
    • 调用 updateUser 接口,当远程调用 updateCity 成功后,人为构造异常,通过分布式事务,让 updateCity 回滚数据;

Client 端

  • Service Module Test
    • Pom 依赖
      • 1
      • 2
    • 配置
      • Seata 客户端配置文件 file.conf、registry.conf;
        • 文件下载地址查看帮助文档,Git 地址为:https://github.com/seata/seata/tree/develop/script/client;
        • 将文件拷贝到项目 src/main/resources 文件夹下;
        • file.conf
          • vgroupMapping.default_tx_group = "default"
            • 事务分组配置,是 Seata 的资源逻辑,类似服务实例,在此修改为:
            • vgroupMapping.test_server_group = "default"
            • 意思是该微服务在 Seata 中注册的事务分组名为:test_server_group;
          • default.grouplist = "127.0.0.1:8091"
            • 指定 Server 端地址,仅在 registry.type=file 时候起作用,且不支持集群;
        • 若 Server 端事务协调者(TC)配置做了修改,那么 Client 端也需做相同的修改,在此案例中事务协调者(TC)配置均使用 file 方式,所以客户端也无需修改;
      • Nacos 配置列表 alibaba-service-test-dev.properties;
        • 数据源配置
          • spring.datasource.url 数据库 JDBC 连接;
          • spring.datasource.jdbc-url 自定义连接池连接;
          • 因为我们要自定义数据源,故而要使用 jdbc-url 配置,不然会抛出 jdbcUrl is required with driverClassName 错误;
        • 事务分组配置
          • 1
          • 2
          • 此处的配置应和 Client 端 file.conf 中 service.vgroupMapping 后缀名保持一致;
          • 程序会通过该配置获取事务分组名 test_server_group,然后去 Client 端 file.conf 中的 service.vgroupMapping 配置(老版本 service.vgroup_mapping),取得事务协调者(TC)集群的名称,再构造服务名,然后去注册中心去拉取事务协调者(TC)服务列表;
        • 实例
          • 1
          • 2
      • 数据源
        • Seata 通过代理数据源的方式实现分支事务,所以在应用中需要重新配置数据源,注入 io.seata.rm.datasource.DataSourceProxy;
        • DataSourceProxyConfig
          • 1
          • 2
      • 回滚日志表 undo_log
        • 参考帮助文档,查找建表 Sql,数据库版本不同,需要修改 sql 语句;
    • 应用
      • 微服务小事务使用 @Transactional 注解,分布式大事务使用 @GlobalTransactional 注解;
        • 1
        • 2
  • Service Module Account
    • Pom 依赖
      • 同上;
    • 配置
      • Seata 客户端配置文件 file.conf、registry.conf;
        • 文件下载地址查看帮助文档,Git 地址为:https://github.com/seata/seata/tree/develop/script/client;
        • 将文件拷贝到项目 src/main/resources 文件夹下;
        • file.conf
          • vgroupMapping.default_tx_group = "default"
            • 事务分组配置,是 Seata 的资源逻辑,类似服务实例,在此修改为:
            • vgroupMapping.account_server_group = "default"
            • 意思是该微服务在 Seata 中注册的事务分组名为:account_server_group
          • default.grouplist = "127.0.0.1:8091"
            • 指定 Server 端地址,仅在 registry.type=file 时候起作用,且不支持集群;
          • 若 Server 端事务协调者(TC)配置做了修改,那么 Client 端也需做相同的修改,在此案例中事务协调者(TC)配置均使用 file 方式,所以客户端也无需修改;
      • Nacos 配置列表 alibaba-service-account-dev.properties;
        • 数据源配置
          • spring.datasource.url 数据库 JDBC 连接;
          • spring.datasource.jdbc-url 自定义连接池连接;
          • 因为我们要自定义数据源,故而要使用 jdbc-url 配置,不然会抛出 jdbcUrl is required with driverClassName 错误;
        • 事务分组配置
          • 1
          • 2
          • 此处的配置应和 Client 端 file.conf 中 service.vgroupMapping 后缀名保持一致;
          • 程序会通过该配置获取事务分组名 account_server_group,然后去 Client 端 file.conf 中的 service.vgroupMapping 配置(老版本 service.vgroup_mapping),取得事务协调者(TC)集群的名称,再构造服务名,然后去注册中心去拉取事务协调者(TC)服务列表;
      • 数据源
        • 同上,修改 basePackages = "com.sfac.alibabaServiceAccount.dao";
      • 回滚日志表 undo_log
        • 同上;
    • 应用
      • 微服务小事务使用 @Transactional 注解,分布式大事务使用 @GlobalTransactional 注解;
        • 1
        • 2

部署测试

  • 启动服务
    • 启动 Nacos;
    • 启动 Sentinel;
    • 启动 Seata Server 端;
    • Service Module Test 启动三个服务,分别对应 8001、8002、8003 端口;
    • Service Module Account 启动一个服务,对应 8004 端口;
  • 正常流程
    • 127.0.0.1:8004/api/user 接口 Service 层,去掉 int i = 1 / 0; 代码;
    • PostMan 请求该接口;
    • 数据库修改成功
  • 异常流程
    • 127.0.0.1:8004/api/user 接口 Service 层,添加 int i = 1 / 0; 代码,人为抛出异常;
    • PostMan 请求该接口;
    • 数据库数据回滚
  • 控制台日志
    • Service Module Account
    • Service Module Test


图片上传

简介

  • 微服务中图片处理最好不要采用 Spring Boot 中本地静态资源的方式,若静态资源只配置在某一个微服务中,那图片也只能在该服务器内,再者,图片地址的多样性和可扩展性,网关不好把控;
  • 我们需要一台图片服务器,使用 Nginx 搭建,公共微服务提供上传图片的接口,图片直接写到图片服务器中,返回该图片的网络访问地址;

图片服务器

  • 下载并安装 Nginx;
  • /usr/local/nginx/conf/nginx.conf
    • 1
    • 2
  • 规则
    • 开放 8000 端口;
    • 根路径配置到系统 /static 文件夹下,并开启浏览器打开文件夹模式;
    • 上传图片根据“文件类型”、“图片种类”、“文件名”定位,例如:上传为图片类型、profile 种类的图片,文件名为当前的时间戳,那么该图片的访问路径为:http://www.sfac.xyz:8000/images/profile/1650874597429.jpg;
    • 创建 /static 文件夹放置图片;
    • chmod 777 /static/ -R,为该文件夹设置权限;

图片接口

  • 思路
    • 首先要确定连接图片服务器的协议,ftp:// 协议 还是 sftp:// 协议,ftp 协议使用 Apache commons-net 包,sftp 协议使用 jsch 包;
    • 其次需要考虑 Java 连接远程服务器的验证方式,最常见的是用户名和密码方式,但我创建的图片服务器禁用了用户名密码登陆、禁用了 root 登陆,使用其他账户的 RSA 公私匙验证登陆,在这种情况下,客户端采用 sftp 协议 + id_rsa 证书的方式可登陆服务器;
    • 接着需要了解 sftp 包操作服务器的接口;
    • 然后才撸代码;
  • jianghu_entity
    • FileType.java
      • 1
      • 2
    • ImageCategory.java
      • 1
      • 2
    • FileUtil.java
      • 略;
  • jianghu_common
    • Pom
      • 1
      • 2
    • application.properties
      • 1
      • 2
    • id_rsa
      • 将证书拷贝到 src/main/resources 下;
    • FtpConfigBean
      • 1
      • 2
    • FtpUtil
      • 1
      • 2
    • ImageServiceImpl
      • 1
      • 2
    • ImageController
      • 1
      • 2

验证

  • 启动项目;
  • Postman 测试
  • http://www.sfac.xyz:8000/images/profile/1650874597429.jpg


JWT 认证

思路

  • 用户登录微服务生成 JWT 字符串返回前端;
  • VuexStore 拿到 JWT 后,做如下处理:
    • 在 LocalStorage 中保存为 ToKen(JWT 字符串)、TokenObject(JWT Decode 后的对象);
    • 在 VuexStore state 中保存 TokenObject;
    • 在 VuexStore getters 中提供 isLogin 方法,判断 TokenObject 是否为空,以及是否过期;
  • main.js 中 Vue Router 注册全局前置守卫,进行登录验证;
  • 在调用后端接口时,从 LocalStorage 中取出 ToKen,设置在请求头中传给接口;
  • 请求后端接口全部由路由控制,创建过滤器,捕获请求头中的 Token 信息,并做验证,验证通过则真正调用接口,否则返回错误状态码;

后端部分

  • Entity 项目
    • 说明:Account 微服务和 Gateway 微服务均需要 JWT 依赖,所以将 JWT 放在 Entity 项目中,微服务引入 Entity 即可;
    • Pom 依赖
      • 1
      • 2
    • JwtUtil
      • JWT 工具类;
      • 1
      • 2
  • Account 微服务
    • Pom 引入 Entity 项目;
    • UserServiceImpl
      • 1
      • 2
    • UserController
      • 1
      • 2
  • Gateway 项目
    • Pom 引入 Entity 依赖;
    • AuthorizeFilter
      • 自定义全局过滤器;
      • 1
      • 2

前端部分

  • 参见 JavaScript_Vue_Admin_3.x 中 Storage 组件、VuexStore 组件、Request 组件、登陆组件;


资源分级

  • 思路

    • 目标:不同用户访问不同资源。
    • 资源(文档、音频、视频、人物)使用 Grade 属性控制等级;
    • GateWay 身份验证过滤器中,将用户 ID 设置到请求头中;
    • Entity 项目新增 ResourceLevel 自定义注解,grade 属性标注资源等级;
    • 方案一
      • Entity 项目新增 ResourceAop 切面,切入 ResourceLevel 方法,环绕通知中,根据用户 ID 设置 ResourceLevel 注解 grade 值;
      • 微服务接口中,若需要添加资源等级控制,在方法上添加 ResourceLevel 注解,利用反射获取 grade 值,再根据 grade 值到数据库查询资源。
    • 方案二
      • Entity 项目新增 ResourceAop 切面,切入 ResourceLevel 方法,@AfterReturning 通知,获取用户 ID 以及目标返回对象等级,来设定响应码,并修改返回对象。
  • 网关

    • AuthorizeFilter.java
      • 1
      • 2
  • Entity 项目

    • ResourceLevel.java
      • 1
      • 2
    • ResourceAop.java
      • 1
      • 2
  • 微服务接口

    • JianghuCommonApplication.java
      • 启动类添加组件扫描注解:@ComponentScan(basePackages= {"com.sfac.common.*", "com.sfac.entity.*"})
    • 方案一
      • ElasticSearchServiceImpl.java
        • 根据 grade 进行分类查询。
        • 1
        • 2
      • FTServiceImpl.java
        • 查询资源和 grade 比较,返回错误状态码
        • 1
        • 2
    • 方案二
      • 在需要资源分级的方法上添加 @ResourceLevel 注解。


问题收集