一、背景

  • 身为Java程序员,微服务是必须要掌握的一种架构。Spring Cloud作为提供微服务架构的完整技术生态链,给我们提供了非常多的框架与组件。其中的重要成员Spring Cloud Netflix也形成了一系列的技术栈:包括服务注册与发现(Eureka),断路器(Hystrix),智能路由(Zuul)和客户端负载平衡(Ribbon)等。
  • 但不幸的是Spring Cloud Netflix的技术栈相继宣布进行维护阶段:



二、初识Spring Cloud Alibaba

  • 做为国内互联网大厂的阿里巴巴,在开源领域的成就有目共睹。
  1. 2016 年,阿里全面拥抱 Spring Boot;
  2. 2017 年 12 月,Spring Cloud Alibaba 立项并顺利进入 Spring Cloud 孵化器。
  3. 2019 月 10 月 3 日,Spring Cloud Alibaba 正式 "挂牌" Spring 官方。

    关于Spring Cloud Alibaba的孵化过程具体可参考:《Spring Cloud Alibaba 从孵化到 "挂牌" 之旅》

同 Spring Cloud 一样,Spring Cloud Alibaba 也是一套微服务解决方案,包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。

(图片来源:阿里云云栖号)

  • 做为微服务生态圈中冉冉升起的一颗新星,我们有理由去了解并掌握Spring Cloud Alibaba的各个技术栈。本文也将通过项目工程演练的方式对Spring Cloud Alibaba中的服务治理组件Nacos与高可用防护组件Sentinel进行基础实践。

三、Nacos的基础实践

  • 在2018年 6 月份 Aliware 技术行上海站 Dubbo 开发者沙龙上,阿里巴巴高级技术专家郭平 (坤宇) 宣布了阿里巴巴的一个新开源项目 Nacos。

Nacos 支持几乎所有主流类型的“服务”的发现、配置和管理:

  1. Kubernetes Serviceg
  2. RPC & Dubbo RPC Service
  3. Spring Cloud RESTful Service

    Nacos生态图(来自Nacos官网)

3.1 安装Nacos并启动服务

  • 获取Nacos安装文件并进行解压
# 下载nacos最新版
wget https://github.com/alibaba/nacos/releases/download/1.3.2/nacos-server-1.3.2.tar.gz
# 解压文件
tar -xvf nacos-server-1.3.2.tar.gz
# 通过nacos-mysql.sql脚本建立数据库
cd nacos/conf
vim nacos-mysql.sql
  • 建立Nacos配置数据库
 /******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_info */
/******************************************/
CREATE TABLE `config_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(255) DEFAULT NULL,
`content` longtext NOT NULL COMMENT 'content',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`src_user` text COMMENT 'source user',
`src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip',
`app_name` varchar(128) DEFAULT NULL,
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
`c_desc` varchar(256) DEFAULT NULL,
`c_use` varchar(64) DEFAULT NULL,
`effect` varchar(64) DEFAULT NULL,
`type` varchar(64) DEFAULT NULL,
`c_schema` text,
PRIMARY KEY (`id`),
...

  • 修改配置文件
 cd nacos/conf
# 编辑配置文件
vim application.properties #*************** Spring Boot Related Configurations ***************#
### Default web context path:
server.servlet.contextPath=/nacos
### Default web server port:
server.port=8848 #*************** Network Related Configurations ***************#
### If prefer hostname over ip for Nacos server addresses in cluster.conf:
# nacos.inetutils.prefer-hostname-over-ip=false ### Specify local server's IP:
# nacos.inetutils.ip-address= #*************** Config Module Related Configurations ***************#
### If use MySQL as datasource:
spring.datasource.platform=mysql ### Count of DB:
db.num=1 ### Connect URL of DB:
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user=root
db.password=root
  • 运行nacos
cd nacos/bin
# 单机运行
sh startup.sh -m standalone
  • 登录nacos控制台

3.2 建立微服务并向Nacos注册服务

  • 建立微服务工程项目



  • 勾选Nacos Service Discovery依赖

  • 打开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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>nacos.democonsumer</groupId>
<artifactId>sentinel</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>sentinel</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
<spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies> <dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>
  • 设置项目配置文件:application.yml
# 端口
server:
port: 8083 spring:
application:
name: goods-service
cloud:
# nacos服务注册
nacos:
discovery:
server-addr: 172.16.109.118:8848
  • 通过 Spring Cloud Alibaba原生注解 @EnableDiscoveryClient 开启服务注册发现功能
// 通过 Spring Cloud 原生注解 @EnableDiscoveryClient 开启服务注册发现功能
@EnableDiscoveryClient
@SpringBootApplication
public class DemoServiceApplication { public static void main(String[] args) { SpringApplication.run(DemoServiceApplication.class, args);
} }
  • 建立HTTP接口的商品信息微服务,模拟返回商品列表
/**
* 商品信息微服务-模拟返回商品列表
*/
@RestController
@RequestMapping("api/goods")
public class GoodsService {
public static final Logger logger = LoggerFactory.getLogger(GoodsService.class);
// 返回商品列表
@GetMapping
public List<Goods> getAllGoods(HttpServletRequest httpServletRequest) {
List<Goods> goods = new ArrayList<>();
goods.add(new Goods("电脑", 10));
goods.add(new Goods("手机", 20));
goods.add(new Goods("书籍", 30));
logger.info("服务被调用:"+httpServletRequest.getRequestURI());
return goods;
} }
  • 启动微服务程序

  • 查看Nacos控制台的服务中心列表,可以看到商品信息微服务已在Nacos注册成功

3.3 建立微服务消费者进行服务调用

  • 仿照以上3.2小节建立微服务提供者步骤,建立服务消费者工程项目;
  • 打开pom.xml,下载依赖
...
<!-- 加入Nacos Discovery Client 依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
...
  • 项目配置:application.yml
# 端口
server:
port: 8090
# Spring配置
spring:
application:
name: user-consumer
cloud:
nacos:
discovery:
server-addr: 172.16.109.118:8848
enabled: true # 调用微服务超时时间设置
ribbon:
ConnectTimeout: 5000
ReadTimeout: 5000 # feign日志以什么级别监控哪个接口
logging:
level:
nacos.democonsumer.GoodService : debug
# 商品微服务地址
service:
url=http://goods-service/
  • 通过 Spring Cloud Alibaba原生注解 @EnableDiscoveryClient 开启服务发现功能,并向Spring注册一个RestTemplate Bean
@EnableDiscoveryClient
@SpringBootApplication
public class DemoConsumerApplication { // 向Spring注册一个RestTemplate Bean
@Bean
// 负载均衡
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
} public static void main(String[] args) {
SpringApplication.run(DemoConsumerApplication.class, args);
}
}
  • 创建Restful测试接口,通过该测试接口可发现并调用Nacos中注册的商品信息微服务
/**
* 用户消费者--调用nacos服务中心的商品信息微服务,并对外提供RestFul接口测试
*/
@RestController
@RequestMapping("user/")
public class UserConsumer { @Autowired
private RestTemplate restTemplate; @Value("${service.url}")
private String url; @GetMapping("/goods")
public User getUserGoods() {
User user = new User();
// 调用商品微服务
Object response = restTemplate.getForEntity(url + "api/goods", Object.class).getBody();
try {
user.setName("jack");
user.setGoods((List<GoodsDTO>) response);
} catch (Exception e){
throw new RuntimeException(e.getMessage());
}
return user;
}
}
  • 运行服务消费者程序,并打开HttpClient工具进行测试



3.4 Nacos小结

  • Spring Cloud Alibaba 的Nacos组件可以完美取代Eureka做为微服务发现及注册的基础框架。
  • 通过Nacos特性大图中,我们还可以了解到,Nacos除了服务发现的框架,还能做到配置管理,DNS服务等功能。

四、Sentinel的基础实践

4.1 安装Sentinel监控

 # 下载服务端
wget https://github.com/alibaba/Sentinel/releases/download/v1.8.0/sentinel- dashboard-1.8.0.jar
# 启动服务(默认端口为8080)
java -jar sentinel-dashboard-1.8.0.jar
  • 登录控制台,默认用户名与密码为sentinel



4.2 通过Sentinel对微服务提供方进行流量控制

  • 对原有商品信息微服务提供者增加Sentinel依赖
<project>
...
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
...
</project>
  • 修改项目配置文件application.yml增加Sentinel控制台地址
server:
port: 8083 spring:
application:
name: goods-service
cloud:
# nacos服务注册
nacos:
discovery:
server-addr: 172.16.109.118:8848
# sentinel服务
sentinel:
transport:
dashboard: 172.16.109.118:8080
  • 运行微服务程序,通过Nacos控制台观察微服务注册信息

  • 我们再通过HttpClient工具访问一下微服务的Api端口,并进入Sentinel控制台进行监控:在控制台中,我们发现了服务名称,及该服务下的各种规则设置菜单。

4.2.1 通过JMeter模拟高并发流量

  • 设置20000个并发请求

  • 设置HTTP请求地址:

  • 设置报告输出

  • 启动JMeter,观察Sentinel控制台,可以看到QPS的实时状况。

4.2.2 设置流控规则进行流量控制

  • 对Sentinel控制台中服务的资源增加流量控制规则

  • 给微服务接口的QPS设置阈值



  • 再次启动JMeter进行高并发测试,在控制台中进行观察,可以看到服务接口的QPS被限制在阈值以下。

  • JMeter结果列表中可以观察到异常信息。

4.2.3 设置降级规则进行流量控制

  • 对Sentinel控制台中服务的资源增加熔断降级规则

慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。

  • 在实时监控界面可以看到请求被拒绝,证明熔断降级规则生效

  • 在JMeter结果表格中也出现了大量失败的调用请求

4.3 通过Sentinel对微服务调用方进行流量控制

  • Sentinel流程控制组件除了可以在微服务端进行必要的流量控制外,也可以在服务调用方的客户端进行控。,
  • 微服务调用方加入OpenFeign组件
<-- pom.xml -->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
  • 项目配置
server:
port: 8090 spring:
application:
name: user-consumer
cloud:
nacos:
discovery:
server-addr: 172.16.109.118:8848
# sentinel服务
sentinel:
transport:
dashboard: 172.16.109.118:8080 # 调用微服务超时时间设置
ribbon:
ConnectTimeout: 5000
ReadTimeout: 5000 # feign日志以什么级别监控哪个接口
logging:
level:
nacos.democonsumer.GoodService : debug # 启用sentinel
feign:
sentinel:
enabled: true
  • 主启动类增加注解
/**
* 主启动类
*/
// 启用Feign组件
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class DemoConsumerApplication { public static void main(String[] args) {
SpringApplication.run(DemoConsumerApplication.class, args);
}
}
  • 参照Nacos中注册的服务名,在服务调用者程序中映射微服务接口, 并通过@FeignClient调用微服务,同时定义服务熔断时如何处理(fallback)

/**
* 映射商品微服务接口
*/
@Component
// 增加服务容错处理,指定服务熔断时处理的类名
@FeignClient(value="goods-service",fallback =FallBackService.class )
public interface GoodService { @GetMapping(value="/api/goods")
List<GoodsDTO> getGoods(); } /**
* 服务熔断处理:返回空值
*/
@Component
public class FallBackService implements GoodService {
private final static Logger logger= LoggerFactory.getLogger(FallBackService.class) ; @Override
public List<GoodsDTO> getGoods() {
logger.info("服务已熔断...");
return new ArrayList<>();
}
}
  • 服务调用者调用程序无需变化
/**
* 用户消费者--调用nacos服务中心的商品服务,并对外提供RestFul接口测试
*/
@RestController
@RequestMapping("user/")
public class UserConsumer {
// 注入商品微服务接品
@Autowired
private GoodService goodService; @GetMapping("/goods")
public User getUserGoods() {
User user = new User();
// 通过GoodsService接口调用商品微服务
try {
List<GoodsDTO> goods = goodService.getGoods();
user.setName("jack");
user.setGoods(goods);
} catch (Exception e){
throw new RuntimeException(e.getMessage());
}
return user;
} }
  • 接下来启动微服务调用者,通过HttpClient工具进行测试,调用正常

  • 进入到Sentinel控制台,同样可以看到消费者的Api接口

4.3.1 对服务调用者中的服务提供方进行流量控制

  • 对Sentinel控制台中服务的资源增加流量控制规则,在FeignClient中,Sentinel为Feign调用生成了资源名策略定义,定义规则为 [httpmethod :protocol://requesturl](比如 GET:http://goods-service/api/goods)

  • 为便于测试,故意将QPS的单机阈值设为0



  • 使用HttpClient工具再次测试,由于我们在流量控制规则中已对QPS做了限制,服务调用请求已无法通过,故触发fallback,返回空值。

  • 服务调用者日志信息提示服务已熔断..

4.4 Sentinel实践小结

  • Sentinel与Hystrix相比,更加轻量级:Sentinel对主流框架提供适配的 API,来定义需要保护的资源,并提供设施对资源进行实时统计和调用链路分析。
  • Sentinel 提供了更加多样化的流量控制,熔断降级和系统负载保护手段。
  • Sentine具备完善的实时监控和控制台。

Spring Cloud Alibaba微服务生态的基础实践的更多相关文章

  1. Spring Cloud Alibaba | 微服务分布式事务之Seata

    Spring Cloud Alibaba | 微服务分布式事务之Seata 本篇实战所使用Spring有关版本: SpringBoot:2.1.7.RELEASE Spring Cloud:Green ...

  2. Spring Cloud Alibaba | Sentinel: 服务限流基础篇

    目录 Spring Cloud Alibaba | Sentinel: 服务限流基础篇 1. 简介 2. 定义资源 2.1 主流框架的默认适配 2.2 抛出异常的方式定义资源 2.3 返回布尔值方式定 ...

  3. Spring Cloud Alibaba微服务一站式解决方案-开篇v2.2.1.RELEASE

    学习路线 **本人博客网站 **IT小神 www.itxiaoshen.com 生态概述 架构演进 什么是微服务 https://martinfowler.com/microservices/ Mic ...

  4. Spring Cloud Alibaba微服务架构入门最容易理解篇

    微服务架构介绍 Spring Cloud Alibaba推荐的微服务生态架构基于分层架构实现如下: 接入层:最外层为LVS+Keepalived,可承受几十万级高并发流量洪峰,然后再通过内层的ngin ...

  5. Spring Cloud Alibaba | Sentinel: 服务限流高级篇

    目录 Spring Cloud Alibaba | Sentinel: 服务限流高级篇 1. 熔断降级 1.1 降级策略 2. 热点参数限流 2.1 项目依赖 2.2 热点参数规则 3. 系统自适应限 ...

  6. Spring Cloud构建微服务架构(一)服务注册与发现

    Spring Cloud简介 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全局锁 ...

  7. Spring Cloud构建微服务架构:服务网关(路由配置)【Dalston版】

    转载:http://blog.didispace.com/spring-cloud-starter-dalston-6-2/ 原创  2017-08-26  翟永超  Spring Cloud 被围观 ...

  8. Spring Cloud构建微服务架构(五)服务网关

    通过之前几篇Spring Cloud中几个核心组件的介绍,我们已经可以构建一个简略的(不够完善)微服务架构了.比如下图所示: 我们使用Spring Cloud Netflix中的Eureka实现了服务 ...

  9. Spring Cloud构建微服务架构 - 服务网关

    通过之前几篇Spring Cloud中几个核心组件的介绍,我们已经可以构建一个简略的(不够完善)微服务架构了.比如下图所示: alt 我们使用Spring Cloud Netflix中的Eureka实 ...

随机推荐

  1. JavaScript 基础三

    遍历对象的属性 for...in 语句用于对数组或者对象的属性进行循环操作. for (变量 in 对象名字) { 在此执行代码 } 这个变量是自定义 符合命名规范 但是一般我们 都写为 k 或则 k ...

  2. Mapreduce之排序&规约&实战案例

    MapReduce 排序和序列化 简单介绍 ①序列化 (Serialization) 是指把结构化对象转化为字节流②反序列化 (Deserialization) 是序列化的逆过程. 把字节流转为结构化 ...

  3. SpringBoot+MyBatis整合报错Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required

    项目启动的时候报这个错误,这个问题我百度了一天,果然不出意外的还是没能解决,其中有一篇文章相对来说还是有点用的:https://blog.csdn.net/qq8693/article/details ...

  4. 第四篇 Scrum冲刺博客

    一.会议图片 二.项目进展 成员 完成情况 今日任务 冯荣新 商品底部工具栏 购物车列表 陈泽佳 渲染搜索结果,防抖的实现 静态结构 徐伟浩 未完成 商品信息录入 谢佳余 未完成 搜索算法设计 邓帆涛 ...

  5. Windows下搭载虚拟机以及环境安装

    前言 最近回到家中进行赛前自主提升 模拟赛考虑到考试环境是NOI Linux 而大多数同学电脑环境为Windows 有同学想要模拟真实考试环境 但是NOI Linux的系统过于"阉割版&qu ...

  6. 牛客网PAT练习场-数素数

    题解:就是一道素数筛选法 题目地址:https://www.nowcoder.com/questionTerminal/e0fb49acb75f47e8b6fa2077d9071799 /** * C ...

  7. Java中动态规则的实现方式

    背景 业务系统在应用过程中,有时候要处理“经常变化”的部分,这部分需求可能是“业务规则”,也可能是“不同的数据处理逻辑”,这部分动态规则的问题,往往需要可配置,并对性能和实时性有一定要求. Java不 ...

  8. Java 接口简述

    Java 接口 接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明.一个类通过继承接口的方式,从而来继承接口的抽象方法. 接口并 ...

  9. Kafka 0.10.1版本源码 Idea编译

    Kafka 0.10.1版本源码 Idea编译 1.环境准备 Jdk 1.8 Scala 2.11.12:下载scala-2.11.12.msi并配置环境变量 Gradle 5.6.4: 下载Grad ...

  10. WPF Devexpress控件库中ChartControl--实现不等距x轴

    一.概要 解决问题--ChartControl不等距x轴显示 二.CS代码 用过ChartControl的开发者们应该都知道,ChartControl中设置x轴间距间隔都是固定的数值. 比如(间隔10 ...