一文教你如何落地 spring cloud alibaba 企业级架构
一.nacos
1.为什么使用选择 nacos
nacos 在 springcloud 体系中作为注册中心与配置中心使用。相当于 eureka 与 apollo 的功能。
一个老生常谈的问题 nacos 和 eureka 区别,下图是楼主在网上查找到。
但是在楼主实际应用中 还有以下有点特别称道:
nacos 有配置功能,相对于楼主之前的 eureka+apollo 这无疑大大的简化了系统的复杂性。
nacos 使用了数据库进行管理数据,使在处理数据时心里更舒服了。
nacos 拥有 namespace 和 gourp 的概念,可以隔离同名的服务。这样在多人起后端服务时,可以注册到一个 nacos 服务 隔离开就可以了。
2.Nacos 快速开始
这个快速开始手册是帮忙您快速在您的电脑上,下载、安装并使用 Nacos。
1.版本选择
您可以在 Nacos 的release notes及博客中找到每个版本支持的功能的介绍,当前推荐的稳定版本为 1.4.2 或 2.0.1。
2.预备环境准备
Nacos 依赖 Java 环境来运行。如果您是从代码开始构建并运行 Nacos,还需要为此配置 Maven环境,请确保是在以下版本环境中安装使用:
64 bit OS,支持 Linux/Unix/Mac/Windows,推荐选用 Linux/Unix/Mac。
3.下载源码或者安装包
你可以通过源码和发行包两种方式来获取 Nacos。
1.从 Github 上下载源码方式
2.下载编译后压缩包方式
您可以从 最新稳定版本 下载 nacos-server-$version.zip
包。
4.启动服务器
1.Linux/Unix/Mac
启动命令(standalone 代表着单机模式运行,非集群模式):
如果您使用的是 ubuntu 系统,或者运行脚本报错提示[[符号找不到,可尝试如下运行:
2.Windows
启动命令(standalone 代表着单机模式运行,非集群模式):
当 idea 使用源码单机启动时需要以下配置
5.单机时使用数据库
当不添加配置时,默认是使用内存保存信息,我们可以添加数据库配置,使数据保存在数据库内。
暂时官方只支持 mysql,其他数据库需要自己手动修改。
1.源码启动
使用源码 idea 启动需要修改以下文件的以下位置
2.已经打包的 jar 包
nacos\conf\application.properties 修改数据库配置
6.启动成功
出现以下图案代表启动成功,看出来模式为单机模式,路径为 Console 输出,访问即可
对于官网集群搭建的要求,是要求大企业的,个人认为小公司如果没有条件可以不必满足,也可以正常启动。但是有条件还是建议上集群。
3.springboot 注册进入 nacos
1.修改 pom 文件
在 pom.xml 文件中最好选择合理的版本,否则会报各种各样的错 。
版本可以根据官方文档选择:https://github.com/alibaba/spring-cloud-alibaba/wiki/版本说明
同时为了保证版本相同建议再父工程中加入以下配置,意思是子工程 groupid 为 org.springframework.cloud,com.alibaba.cloud,org.springframework.boot 的都依赖父工程版本
2.修改 bootstrap.xml
这里一定要使用 bootstrap.yml 而不是 application.yml,因为 bootstrap.yml 运行先于后者,如果使用 application.yml 可能会出现即使有注册的地址,还是去连接 localhost:8848 的情况。
可以为服务指定 namespace 和 group,在一个 namespace 和 group 中的服务只能获取同 namespace 和 group 中的服务,这样可以同时配置 dev 和 pro 环境。获取小组内的小伙伴都可以连接一个 nacos 服务,而不是像 eureka 一人启动一个。
1.新建命名空间
配置文件中 namespace 是需要建立的,方式如图。
配置文件中是命名空间 id
2.新建分组
分组不用在 nacos 中新建 ,直接编写即可。
3.修改启动类
在 spring boot 启动类上加入 @EnableDiscoveryClient 注解即可。
注意:如果使用了 logback 作为日志
System.setProperty("nacos.logging.default.config.enabled", "false");
需要添加 否则会因为日志命名报错
4.启动
然后启动服务,访问 ip:8848/nacos 可以验证是否注册成功。
同时也发布到了指定的 namespace 和 groupid。
4.配置中心
配置中心:bootstrap.yml 中的配置可以通过 nacos 配置修改,同时大部门不需要重启服务就可以生效。
由于引入了 nacos,楼主不再使用 apollo 配置中心。变更原因如下
由于架构变更为 springcloud alibaba,nacos 可以承担起 eureka+apollo 的功能。
可以降低系统的复杂性。方便运维。
对配置中心的需求仅有动态配置,无更细腻话的权限和灰度发布等功能要求。
1.实战整合 springboot
建议启动类使用 bootstrap.yml
1.新建 nacos 配置
请注意选择合适命名空间
配置解释如下:
Data ID 的命名格式如下:{spring.application.name}-{spring.profiles.active}.{文件类型},也就是系统名称+dev/pro.yaml(一般情况)见下图。
如果没有 spring.profiles.active 会省略“-”与“spring.profiles.active”
group:其中需要注意 namespace 与 group 需要与 nacos 中配置对应(这两个概念上文有介绍),否则会获取不到配置。
配置格式:这里因为使用了 bootstrap.yml 所以选择上述配置。
配置内容:需要在 nacos 中更改的配置项。
2.配置成功
如果成功:
切记 namespace 与 group 一定要匹配。同时可以监控到那台服务使用该配置。
3.客户端接口编写
@RefreshScope 不要少写!否则报错!改变配置多次调用接口,可以发现返回值发生变化。
二.修改 nacos 数据库
nacos 功能很强大,但是官方只提供了 mysql 的版本,对于其他的数据库并不适配。博主公司使用 postgresql(因为免费),所以需要修改。本文章将介绍如何修改,并打成 docker 镜像发布。
1.下载源码
这里就不介绍如何修改了,以下是楼主修改的好的源码地址,版本为 1.4,下载打包即可,相对比较好改,如果有其他版本更改要求可以百度查看更改位置自行更改。
链接:https://pan.baidu.com/s/1VdzqtBYOx7TyBXMgwrVSqw 提取码:r8tg
2.数据库配置修改
数据库配置在以下位置修改。
3.打包
打包命令如下,这里与官方文档不同,因为在打包过程中,官网版本会验证文件格式,有时候会报错,所以跳过格式检测。
这里需要注意 在打包过程中还会检查注释 所以尽量避免注释!如果报错 可以根据日志 到 targer/rat.txt 下查找报错原因。
打包成功后可以到nacos-1.4.1\distribution\target\nacos-server-1.4.1
位置查看打好的包
2.制作镜像
上文我们更改了数据库类型,就不能使用官方 docker 镜像了。所以我们这里使用修改源码之后的 nacos 项目制作镜像。
1.下载
目的是获取官方的 Dockerfile,修改后使用他打包镜像。
2.修改 Dockerfile
官方的 Dockerfile 意思是下载 nacos 的压缩文件,这里我们指定成本地我们已经打包好的 gz 文件。将其放到/usr/local/git/nacos-docker/build/
路径下。(gz 文件在上文可以找到。)
3.修改数据库配置
修改下文位置的 application.properties 文件,修改数据源。
4.打包
由于我们上文直接配置数据库连接,所以直接打镜像就可以了。
5.启动
三.小企业适用的组件化的服务间的调用
服务间调用是微服务体系中必不可少的一部分,在 springcloud alibaba 的官网中,推荐使用是 dubbo,但因为并发量比较小,同时 dubbo 相对比较复杂,所有楼主在服务间调用选型时,依然选择了 openfeign。同时将服务间调用的接口封装为子工程,进行统一的 api 管理。避免小伙伴们造重复的轮子。
1.新建 api 子工程
1.搭建子工程
这里新建了一个子工程,文件结构如下。
2.添加 pom.xml
3.实现 fallback 熔断方法
当服务调用失败,会跳转到该类。后文会与 Sentinel 一起使用。
4.feign 接口实现
这里需要注意,如果在 get 请求时,同时 boby 中有值,feign 会把 get 转换成 post,所以这种情况需要使用 @SpringQueryMap 注解。
2.父工程调用
1.修改 pom.xml
1.在 pom 文件中引入子工程 ,详细配置可以参考楼主文章:
2.修改启动类
注意:@EnableFeignClients("com.common.api")一定要指定 api 子工程路径,否则不执行调用。
3.调用
四.getway 网关极简落地
在 spring cloud netflix 时使用 zuul 作为官网,但是随着 zuul2.0 的多次跳票和 getway 异军突起。getway 已经是一款主流的产品了,同时 springcloud alibaba 官网的推荐网关也是 getway,所以在选型时不需要犹豫。干就完了。同时 getway 使用了 webflux,较第一代网关更优秀。
1.为什么使用网关
使用网关后,对于系统相当有了一个统一的入口,例如你有 100 个微服务系统,现在只需要对外暴露网关的地址即可。同时所有的请求都是通过网关的分发,所以很方便的在网关上对请求拦截,重而实现反向代理,鉴权,流量控制,熔断,日志监控等。
2.实现
getway 基础实现很简单。鉴权等功能会在以后章节中发布。
1.添加 pom.xml
注意:getway 使用的是 webflux,不要引入 spring-boot-starter-web
2.修改启动类
3.bootstrap.yml
getway 也需要注册到 nacos 中。也需要将 namespace 和 group 对应。
楼主因为在小公司,所以只使用该规则就满足了业务要求,如果有其他规则使用,请自行百度,这里不具体介绍。
注意:
getway 只能获取同 namespace 和 group 中的服务。
websocket 接口与普通接口用以上配置就可以同时接受,不用额外配置路由。
3.配置 oauth2 的跨域
spring cloud ouath2 + getway 跨域是有特别的配置的(与普通跨域不同)需要特别注意。
1.修改 bootstrap.yml
2.添加 GatewayConfig
注意如果网关中添加了跨域配置,业务服务就不要添加了,否则就会报错!
五.Sentinel 落地与应用
1.Sentinel 介绍
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。 Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
Sentinel 具有以下特征:
丰富的应用场景: Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、实时熔断下游不可用应用等。
完备的实时监控: Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
广泛的开源生态: Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
完善的 SPI 扩展点: Sentinel 提供简单易用、完善的 SPI 扩展点。您可以通过实现扩展点,快速的定制逻辑。例如定制规则管理、适配数据源等。
白话来讲,作用就是当大量请求怼过来时,你可以设置接收多少请求,其余的都会返回 如访问人数过多等信息(请参考双 11 秒杀你大多数参与的结果),这样保证服务器不被压垮,保证了大部分的用户体验,同时被熔断的请求不也会莫名的显示各种不明所以的报错或者是直接白页,体验更加友好。
2.如何使用 Sentinel
1.下载安装
官网提供打好的 jar 包直接下载即可.
地址:https://github.com/alibaba/Sentinel/releases/tag/1.8.1
或者下载源码,自己打包。
会在 Sentinel-master\sentinel-dashboard\target 下生成。
2.启动
Sentinel 控制台是一个标准的 Spring Boot 应用,以 Spring Boot 的方式运行 jar 包即可。
3.@SentinelResource 注解(使用 feign 调用可以省略)
埋点功能,在调用接口时,如果发生限流或者是异常,那么会抛出 blockHandler/fallback 指定的异常信息。
注意:注解方式埋点不支持 private 方法。
@SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。@SentinelResource 注解包含以下属性:
value:资源名称,必需项(不能为空)
entryType:entry 类型,可选项(默认为 EntryType.OUT)
blockHandler / blockHandlerClass: blockHandler 对应处理 BlockException 的函数名称,可选项。blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 class 对象,注意对应的函数必需为 static 函数,否则无法解析。
fallback / fallbackClass:fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求:
返回值类型必须与原函数返回值类型一致;
方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 class 对象,注意对应的函数必需为 static 函数,否则无法解析。
defaultFallback(since 1.6.0):默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。defaultFallback 函数签名要求:
返回值类型必须与原函数返回值类型一致;
方法参数列表需要为空,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
exceptionsToIgnore(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。1.8.0 版本开始,defaultFallback 支持在类级别进行配置。
注:1.6.0 之前的版本,fallback 函数只针对降级异常(DegradeException)进行处理,不能针对业务异常进行处理。特别地,若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。若未配置 blockHandler、fallback 和 defaultFallback,则被限流降级时会将 BlockException 直接抛出(若方法本身未定义 throws BlockException 则会被 JVM 包装一层 UndeclaredThrowableException)。
示例:
4.springboot 整合
如果要在您的项目中引入 Sentinel,使用 group ID 为 com.alibaba.cloud 和 artifact ID 为 spring-cloud-starter-alibaba-sentinel 的 starter。
1.修改 pom.xml
2.修改 application.yml
spring.cloud.sentinel.transport.port 是本地启的端口,与 dashboard 进行数据交互。官方文档是这样写的:这里的 spring.cloud.sentinel.transport.port 端口配置会在应用对应的机器上启动一个 Http Server,该 Server 会与 Sentinel 控制台做交互。比如 Sentinel 控制台添加了一个限流规则,会把规则数据 push 给这个 Http Server 接收,Http Server 再将规则注册到 Sentinel 中。
注意 transport:port: 8719 这个端口不能多次占用,比如果一个项目制定的为 8719 那么同服务器的任何项目都不能在使用 8719 了
3.验证
访问 ip:8080 账号/密码,出现以下页面即可。
注意:当访问一次接口之后 才能在左面出现服务选项!!
3.Feign 支持
Sentinel 适配了 Feign 组件。如果想使用,除了引入 spring-cloud-starter-alibaba-sentinel 的依赖外还需要 2 个步骤:
配置文件打开 Sentinel 对 Feign 的支持:feign.sentinel.enabled=true
加入 spring-cloud-starter-openfeign 依赖使 Sentinel starter 中的自动化配置类生效:
如果不开启,将不能实现熔断,会直接抛出异常!
1.修改 yml 文件
2.示例
这是一个 FeignClient 的简单使用示例:
4.Spring Cloud Gateway 支持
若想跟 Sentinel Starter 配合使用,需要加上 spring-cloud-alibaba-sentinel-gateway 依赖,同时需要添加 spring-cloud-starter-gateway 依赖来让 spring-cloud-alibaba-sentinel-gateway 模块里的 Spring Cloud Gateway 自动化配置类生效:
六.Sentinel 的常用配置详解
上文在安装整合后,还需要在 Sentinel 的页面编辑熔断和降级规则。下文将介绍常用的配置规则。
1.流控
1.快速使用
在接口上点击流控,设置单机阈值(每秒钟的并发量),针对来源不用修改。
使用 postman 测试,当多次点击后会报错。
2.配置详解(无特殊需求可以跳过)
1.阈值类型
线程数:当操作线程大于配置,限流!
QPS:当每秒并发数大于配置,限流!
2.流程模式
直接:直接限流,上文实例展示。
关联:被关联的资源达到阈值,导致当前资源被限流。(如下:当 B 超过 QPS 为 1 之后,A 限流:)
链路:链路上游达到阈值,当前资源限流。例如:接口的上游都是 sentinel_spring_web_context 如果 sentinel_spring_web_context 超过阈值,demo 限流!
3.流控效果
直接失败:直接抛出异常,上文示例方式。
warm up:当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。warm up 冷启动主要用于启动需要额外开销的场景,例如建立数据库连接,秒杀等等,防止服务瞬间被打垮。白话讲就是,根据冷加载因子,默认 3,经过一段时间,才能达到预设的 QPS。下图含义是初始阈值为 10/3 = 3,在 5 秒内到达 QPS 到达 10。
排队等待:当达到阈值,请求一个一个通过,排队超过 1s,抛出异常。
2.降级
1.慢调用比例
满足两个条件会触发熔断:
请求数大于最小请求数。下面是每秒钟 5 个。
慢请求达到设置的比例。(请求时间大于最大 RT 的次数*比例阈值)
2.异常比例
需要两个条件。
每秒钟请求超过最小请求数,这里是五个。
异常比例超过 50%触发熔断。
3.异常数
需要两个条件。
每秒钟请求超过最小请求数 ,这里是五个。
异常数大于 5 个。
3.热点规则
热点规则是按照参数值进行限流。下文含义是,监控/demo 接口 如果有第一个参数,那么每秒的 qps 为 1,如果第一个参数值为"a",QPS 为 20。
1.系统规则
系统保护规则是从应用级别的入口流量进行控制,从单台机器的 load、CPU 使用率、平均 RT、入口 QPS 和并发线程数等几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
Load 自适应(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的
maxQps * minRt
估算得出。设定参考值一般是CPU cores * 2.5
。CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。
平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
可以理解为系统规则是全局的限流配置,可以针对服务的全局 QPS、机器的 CPU 等参数进行限流。
4.问题
问题一:发现 sentinel 报错,查看日志。
然后查看 spring boot 业务项目,发现出现以下错误 ,发现 fastjson 版本不对,然后去当前对象的 sentinel 中查看 jar 包版本替换即可。
如果各位小伙伴有所所获,还望一波点赞呦。
版权声明: 本文为 InfoQ 作者【小黄鸡1992】的原创文章。
原文链接:【http://xie.infoq.cn/article/bcb3a8a5e33c83f585359bf4e】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论