springcloud微服务架构搭建过程
Posted 小丑的忧伤
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springcloud微服务架构搭建过程相关的知识,希望对你有一定的参考价值。
项目地址:源代码
仅作为学习用例使用,是我开发过程中的总结、实际的一部分使用方式
开发环境:
jdk11
springboot2.7.6
springcloud2021.0.5
alibabacloud 2021.0.4.0
redis6.0
mysql8.0
一、项目搭建
wdz-api:存放远程服务调用相关接口
wdz-auth:认证业务
wdz-gateway:网关
wdz-modules:业务模块微服务
wdz-common:存放公用中间件、数据库等服务
pom
<?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>
<packaging>pom</packaging>
<modules>
<module>wdz-common</module>
<module>wdz-gateway</module>
<module>wdz-api</module>
<module>wdz-auth</module>
<module>wdz-modules</module>
</modules>
<groupId>com.wdz</groupId>
<artifactId>wdz-ruzhou</artifactId>
<version>1.0.0</version>
<name>wdz-ruzhou</name>
<description>微服务架构</description>
<properties>
<java.version>11</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.7.6</spring-boot.version>
<spring-cloud.version>2021.0.5</spring-cloud.version>
<spring-cloud.alibaba>2021.0.4.0</spring-cloud.alibaba>
<fastjson2.version>2.0.14</fastjson2.version>
<lombok.version>1.18.24</lombok.version>
</properties>
<dependencyManagement>
<dependencies>
<!--springcloud 微服务依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>$spring-cloud.version</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--springboot 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>$spring-boot.version</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--alibaba 微服务依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>$spring-cloud.alibaba</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>$lombok.version</version>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>$fastjson2.version</version>
</dependency>
</dependencies>
</dependencyManagement>
<!--配置打包环境数据-->
<profiles>
<profile>
<id>dev</id>
<properties>
<profiles.active>dev</profiles.active>
<nacos.username>nacos</nacos.username>
<nacos.password>nacos</nacos.password>
<nacos.server>127.0.0.1:8848</nacos.server>
<nacos.discovery.namespace>5efed786-91f6-44c4-8e14-049df72b2a48</nacos.discovery.namespace>
<nacos.config.namespace>5efed786-91f6-44c4-8e14-049df72b2a48</nacos.config.namespace>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>test</id>
<properties>
<profiles.active>test</profiles.active>
<nacos.username>nacos</nacos.username>
<nacos.password>nacos</nacos.password>
<nacos.server>127.0.0.1:8848</nacos.server>
<nacos.discovery.namespace>f02ccd30-e3d5-4235-9282-d0a613bd322b</nacos.discovery.namespace>
<nacos.config.namespace>f02ccd30-e3d5-4235-9282-d0a613bd322b</nacos.config.namespace>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<profiles.active>prod</profiles.active>
<nacos.username>nacos</nacos.username>
<nacos.password>nacos</nacos.password>
<nacos.server>127.0.0.1:8848</nacos.server>
<nacos.discovery.namespace>747829ca-6d8a-4417-a46a-bd31a6f5e442</nacos.discovery.namespace>
<nacos.config.namespace>747829ca-6d8a-4417-a46a-bd31a6f5e442</nacos.config.namespace>
</properties>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>$java.version</source>
<target>$java.version</target>
<encoding>$project.build.sourceEncoding</encoding>
</configuration>
</plugin>
</plugins>
<!--用于yml配置中变量替换如: @nacos.name@-->
<resources>
<resource>
<directory>src/main/resources</directory>
<!-- 引入所有 匹配文件进行过滤 -->
<includes>
<include>application*</include>
<include>bootstrap*</include>
<include>logback*</include>
</includes>
<!-- 启用过滤 即该资源中的变量将会被过滤器中的值替换 -->
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>
nacos(2.2.0.1)
我为什么选择nacos作为注册中心?
1、独立的可视化管理后台
2、持久化,配置数据直接存储在数据库中
3、动态配置,修改配置可实时生效,不用重启
4、活跃度高,资料文件丰富
5、功能全面
6、是经过阿里巴巴考验的
戳==>官网
安装nacos
点击选择版本下载
windows建议下载zip
linux 建议下载tar.gz
下载完成解压即可
配置数据库
打开conf下的application.properties文件:
修改数据库配置,将注释打开,并配置数据源
创建数据库目前只支持mysql,版本要求:5.6.5+
需要IPV6支持使用:derby-schema.sql 否则使用:mysql-schema.sql 配置完成后
单机启动nacos:
Linux/Unix/Mac使用命令:sh startup.sh -m standalone
windows使用命令:./startup.cmd -m standalone
standalone:表示单机模式运行,非集群模式
官方文档
启动过程中如果出现jwt认证问题启动失败,请参考:戳详情
错误示例
修改文件:
nacos.core.auth.plugin.nacos.token.secret.key
使用base64 处理数据长度大于等于32即可
访问:http://localhost:8848/nacos,默认用户名密码:nacos
集群启动 官方文档
如果是在一台电脑上/服务器上模拟集群:
将nacos解压之后的文件nacos复制多份,
并修改对应conf文件夹下的application.properties文件端口配置
再将conf下的cluster.conf.example 复制一份并修改后缀为conf
将其他nacos地址配置在cluster.conf中
依次启动服务:
windows命令:./startup.cmd
linux命令: sh ./startup.sh
访问对应nacos
nacos 服务配置config与发现 discovery
创建测试注册服务网关服务,nacos作为注册中心有多种方式,本文用javaSDK的方式
pom文件
<?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">
<parent>
<artifactId>wdz-ruzhou</artifactId>
<groupId>com.wdz</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.wdz</groupId>
<artifactId>wdz-gateway</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
yml配置:
server:
port: 8080
servlet:
context-path: /
spring:
application:
name: wdz-gateway
profiles:
active: @profiles.active@
---
# 使用导入的方式读取所有需要的nacos中的配置文件
spring:
config:
import:
- optional:nacos:application-common.yml
- optional:nacos:$spring.application.name.yml
cloud:
nacos:
username: @nacos.username@
password: @nacos.password@
server-addr: @nacos.server@
# 服务发现
discovery:
namespace: @nacos.discovery.namespace@
# 配置
config:
namespace: @nacos.config.namespace@
集群nacos负载配置:
通过nginx配置服务访问的nacos
upstream nacos-cluster
server 127.0.0.1:8247;
server 127.0.0.1:8549;
server 127.0.0.1:8848;
server
listen 801;
server_name localhost;
location /nacos
proxy_pass http://nacos-cluster;
结果
负载均衡Ribbon
内置负载均衡规则类 | 规则描述 |
---|---|
RoundRobinRule | 简单轮询服务列表选择服务器,它是Ribbon默认的负载均衡规则 |
AvailabilityFilteringRule | 忽略规则:1、链接3次失败,会标记为短路状态,将持续30秒,如果还是失败则持续短路,时间增长,2、并发数过高的服务链接,并发数达到上限则会被忽略 |
WeightedResponseTimeRule | 权重策略,每个服务器配置一个权重值,权重值越小,选择这个服务器的比重就会越小 |
ZoneAvooidanceRule | 以区域可用的服务器为基础进行服务器的选择,使用Zone对服务器进行分类,Zone相当于一个机房,一个区域,然后再对Zone内的多个服务做轮询 |
BestAvailableRule | 忽略哪些短路服务器,并选择并发数较低的服务器 |
RandomRule | 随机选择一个可用服务器 |
RetryRule | 重试机制的选择逻辑 |
自定义策略方式:
代码方式:作用的是所有服务
@Bean
public IRule diyRule()
return new RandomRule();
yml方式:作用的是所配置的服务
servicename: # 服务名称如:userservice
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
ribbon默认是懒加载,第一次访问的时候响应时间会比较长,初次加载之后响应就会变短。
开启ribbon饥饿加载有效提高第一次访问响应时间
ribbon:
eager-load:
enabled: true # 开启饥饿加载
clients: # 指定加载的服务名称
- userservice
- orderservice
- systemservice
- XXXservice
nacos服务分级存储模型
一级是服务:如:userservice、orderservice
二级是集群:配置了同一个discovery.cluster-name:
三级是实例:如杭州机房的某台部署了要访问的服务器
设置实例的集群属性:名称一样的在同一个集群内
spring.cloud.nacos.discovery.cluster-name:NacosRule负载均衡策略:
1、优先选择同集群的服务
2、本地集群找不到提供者,才去其他集群找,并且会报警告
3、确定了可用实例列表后,再采用随机负载均衡挑选实例
NacosRule配置:
servicename: # 服务名称如:userservice
ribbon:
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
环境隔离:namespace
spring:
cloud:
nacos:
discovery:
namespace: @nacos.discovery.namespace@
# 不同名称空间之间的服务不能互通,如user使用的prod order使用的dev,这两个服务不能互通
nacos特点
1、支持服务端主动监测提供者状态,临时实例采用心跳模式,非临时实例采用主动监测模式
2、林实施例心跳不正常会被剔除nacos的服务列表,非临时实例不会被剔除
3、服务列表变更消息推送模式,服务列表更新及时
4、nacos集群默认采用AP方式,集群中存在非临时实例时,采用CP模式
CAP:C(一致性),A(可用性),P(分区容错)原文
Feign 源码
feign是声明式的http客户端
使用方式
pom引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
java代码
@FeignClient("applicationName")
public interface ApplicationName
@GetMapping("/get")
Object queryById(Long id);
自定义feign配置
类型 作用 说明 feign.Logger.Level 修改日志级别 包含四种不同的级别:none、basic、headers、full feign.codec.Decoder 响应结果解析器 http远程调用的结果做解析,例如解析json字符串为java对象 feign.codec.Encoder 请求参数编码 将请求参数编码,便于通过http请求发送 feign.Contract 支持注解格式 默认是SpringMvc的注解 5.springcloud微服务架构搭建 之 《springboot集成Hystrix》
1.springcloud微服务架构搭建 之 《springboot自动装配Redis》
2.springcloud微服务架构搭建 之 《springboot集成nacos注册中心》
3.springcloud微服务架构搭建 之 《springboot自动装配ribbon》
4.springcloud微服务架构搭建 之 《springboot集成openFeign》
目录
2.1 使用HystrixCommand 实现fallback
2.2 通过DefaultProperties实现全局fallback
3.1 FeignClient 接口实现降级策略,FallbackFactory
1.项目引入hystirx
1.1.项目引入hystrix坐标配置
<!-- hystrix 配置 版本号:2.1.3.RELEASE--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> <version>$spring.cloud.version</version> </dependency>
1.2.项目启动类启用断路器
package lilock.cn.user; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication(scanBasePackages = "lilock.cn.*") @EnableConfigurationProperties @EnableDiscoveryClient @EnableFeignClients(basePackages = "lilock.cn") //启用feign调用 @EnableCircuitBreaker // 启用断路器 public class UserApplication public static void main(String[] args) SpringApplication.run(UserApplication.class,args);
2. HystrixCommand 注解
Hystrix提供了HystrixCommand,用于配置关于Hystrix相关配置,如:回调方法、超时时间、熔断配置等。想要使用hystrix,必须是用@HystrixCommand注解
这种模式下的hystrix使用,配置都是基于 @HystrixCommand注解配置的,我们通过在方法上添加 @HystrixCommand 注解并配置注解的参数来实现配置。
2.1 使用HystrixCommand 实现fallback
/** * 接口熔断 * @return */ @HystrixCommand(fallbackMethod = "testHystrixError") @GetMapping("/testHystrix") public String testHystrix() log.info("testHystrix 接口调用 apiCmsServiceFeignClient.getHello"); String value = apiCmsServiceFeignClient.getHello(); return "[testHystrix] 验证断路器" + value; public String testHystrixError() log.info(" testHystrixError 调用失败",System.currentTimeMillis()); return "enable testHystrixError";
2.1.1 正常性测试
2.1.2 停掉cms服务,模拟服务不可用
2.2 通过DefaultProperties实现全局fallback
时候一个类里面会有多个 Hystrix 方法,每个方法都是类似配置的话会冗余很多代码,这时候我们可以在类上使用 @DefaultProperties 注解来给整个类的 Hystrix 方法设置一个默认降级方法,特别标注的,降级走特别标注的方法,没有特别标注的,降级走默认方法
@RestController @RequestMapping(path = "/user") @Api(value = "系统用户",tags = "系统用户") @Slf4j @DefaultProperties(defaultFallback = "defaultFallBackMethod") public class UserController /*** * 模拟全局配置fallback */ @HystrixCommand @GetMapping("/testHystrixTimeOutFallback") public BaseResult testHystrixTimeOutFallback(@RequestParam("time") long time) BaseResult<String> value = apiCmsHystrixServiceFeignClient.getHystrixTimeOut(time); log.info("testHystrixTimeOutFallback 接口调用 响应结果:",value); try Thread.sleep(time); catch (Exception e) return value; public BaseResult defaultFallBackMethod() String errorMsg = System.currentTimeMillis() + "defaultFallBackMethod 调用失败触发熔断"; log.error("",errorMsg); return BaseResult.faild(errorMsg);
2.2.1 停到cms服务,模拟测试
2.3 通过自定义参数配置接口的熔断策略
配置一个超时时间,并且fallback走公共模式
/** * 模拟带参数走服务熔断 * @return */ @HystrixCommand(commandProperties = @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1500")) @GetMapping("/testHystrixTimeDefault") public BaseResult testHystrixTimeDefault(long time) log.info("testHystrixTimeDefault 接口调用 apiCmsHystrixServiceFeignClient.testHystrixDefault"); BaseResult<String> value = apiCmsHystrixServiceFeignClient.getHystrix(); try Thread.sleep(time); catch (Exception e) return value; public BaseResult defaultFallBackMethod() String errorMsg = System.currentTimeMillis() + "defaultFallBackMethod 调用失败触发熔断"; log.error("",errorMsg); return BaseResult.faild(errorMsg);
接口sleep 1000ms 时间小于降级1500ms时间,正常返回
接口sleep 2000ms时间大于降级1500ms时间,触发降级
3.开启feign集成hystrix
配置文件开启
feign: hystrix: enabled: true
3.1 FeignClient 接口实现降级策略,FallbackFactory
fallbackFactory的好处是可以统一配置
当然Api接口上也可以单独配置@HystrixCommand
package lilock.cn.cms.api; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import lilock.cn.cms.api.fallback.ApiCmsHystrixServiceFeignClientFallbackFactory; import lilock.cn.common.resp.BaseResult; import lilock.cn.common.ribbon.config.FeignConfig; import lilock.cn.common.ribbon.constant.ApplicationServiceConstants; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; //FeignClient实现了FallbackFactory @FeignClient(value = ApplicationServiceConstants.LILOCK_CMS_WEB,configuration = FeignConfig.class,fallbackFactory = ApiCmsHystrixServiceFeignClientFallbackFactory.class) public interface ApiCmsHystrixServiceFeignClient @GetMapping("/getHystrix") BaseResult<String> getHystrix(); @GetMapping("/getHystrixTimeOut") @HystrixCommand BaseResult<String> getHystrixTimeOut(@RequestParam long time);
3.1.1 服务正常测试
3.1.2 停掉api服务测试
可以看到触发了fallbackFactory的服务降级,服务降级之后还会继续调用下游api
3.1.3 继续模拟频繁调用接口,则会触发熔断
当降级的数量达到一定的百分比之后,接口就会触发熔断,触发熔断之后不会继续调用下游api
4.全局Hystrix配置
hystrix: command: #全局默认配置 default: execution: timeout: #是否给方法执行设置超时时间,默认为true。一般我们不要改。 enabled: true isolation: #配置请求隔离的方式,这里是默认的线程池方式。还有一种信号量的方式semaphore,使用比较少。 strategy: threadPool semaphore: maxConcurrentRequests: 1000 thread: #方式执行的超时时间,默认为1000毫秒,在实际场景中需要根据情况设置 timeoutInMilliseconds: 60000 #发生超时时是否中断方法的执行,默认值为true。不要改。 interruptOnTimeout: true #是否在方法执行被取消时中断方法,默认值为false。没有实际意义,默认就好! interruptOnCancel: false #熔断器相关配置 ##并发执行的最大线程数,默认10 coreSize: 200 #说明:是否允许线程池扩展到最大线程池数量,默认为false。 allowMaximumSizeToDivergeFromCoreSize: true #说明:线程池中线程的最大数量,默认值是10。此配置项单独配置时并不会生效,需要启用allowMaximumSizeToDivergeFromCoreSize maximumSize: 200 #说明1:作业队列的最大值,默认值为-1。表示队列会使用SynchronousQueue,此时值为0,Hystrix不会向队列内存放作业。 #说明2:如果此值设置为一个正int型,队列会使用一个固定size的LinkedBlockingQueue,此时在核心线程池都忙碌的情况下,会将作业暂时存放在此队列内,但是超出此队列的请求依然会被拒绝 maxQueueSize: 20000 #设置队列拒绝请求的阀值,默认为5。 queueSizeRejectionThreshold: 30000 circuitBreaker: #说明:是否启动熔断器,默认为true。我们使用Hystrix的目的就是为了熔断器,不要改,否则就不要引入Hystrix。 enabled: true #说明1:启用熔断器功能窗口时间内的最小请求数,假设我们设置的窗口时间为10秒, #说明2:那么如果此时默认值为20的话,那么即便10秒内有19个请求都失败也不会打开熔断器。 #说明3:此配置项需要根据接口的QPS进行计算,值太小会有误打开熔断器的可能,而如果值太大超出了时间窗口内的总请求数,则熔断永远也不会被触发 #说明4:建议设置一般为:QPS*窗口描述*60% requestVolumeThreshold: 3000 #说明1:熔断器被打开后,所有的请求都会被快速失败掉,但是何时恢复服务是一个问题。熔断器打开后,Hystrix会在经过一段时间后就放行一条请求 #说明2:如果请求能够执行成功,则说明此时服务可能已经恢复了正常,那么熔断器会关闭;相反执行失败,则认为服务仍然不可用,熔断器保持打开。 #说明3:所以此配置的作用是指定熔断器打开后多长时间内允许一次请求尝试执行,官方默认配置为5秒。 sleepWindowInMilliseconds: 5000 #说明1:该配置是指在通过滑动窗口获取到当前时间段内Hystrix方法执行失败的几率后,根据此配置来判断是否需要打开熔断器 #说明2:这里官方的默认配置为50,即窗口时间内超过50%的请求失败后就会打开熔断器将后续请求快速失败掉 errorThresholdPercentage: 70 #说明:是否强制启用熔断器,默认false,没有什么场景需要这么配置,忽略! forceOpen: false #说明:是否强制关闭熔断器,默认false,没有什么场景需要这么配置,忽略! forceClosed: false
5.参考
https://zhuanlan.zhihu.com/p/339535352
https://blog.csdn.net/weixin_40482816/article/details/119215962
以上是关于springcloud微服务架构搭建过程的主要内容,如果未能解决你的问题,请参考以下文章