1、首先创建好一个springboot父工程,这里以springboot-aliyun-2.6.13举例
- 创建好工程后,将工程中的src目录删除掉,使之成为一个空着的父工程项目,这个项目将为我们管理当前父工程下所有微服务工程的pom依赖关系
- 将父工程的pom文件做如下注释部分的改动
<modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>cloud_demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>cloud_demo</name> <description>cloud_demo</description> //改动1:这里表示这个父工程将以pom文件形式打包并管理当前父工程下所有微服务的pom依赖 <packaging>pom</packaging> //改动2:这里表示当前maven的聚合工程模型 <modules> <module>commun-service</module> <module>user-service</module> <module>order-service</module> </modules>
- 然后需要将我们所需要管理的springboot版本依赖、springcloud版本依赖、alibabacloud版本依赖,伴随着自定义的properties标签内的自定义变量全部都定义所管理的版本,具体pom代码已经整理至下方的代码模板中,复制粘贴即可
<properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-boot.version>2.6.13</spring-boot.version> <spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version> <spring-cloud.version>2021.0.5</spring-cloud.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <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> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
至此我们的pom父工程就算定义好了一套标准的模板可供当前项目的微服务依赖使用。
2、微服务的注册发现(Nacos)
- 首先需要找到对应的子工程,在pom文件中创建对应的父子工程关系,并引入nacos对应依赖
<parent> //这里的三大坐标是你的父工程 <artifactId>cloud_demo</artifactId> <groupId>com.example</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
- 然后在我们的子工程的配置文件中,加入如下定义
spring.application.name=user-service //向nacos注册服务的名称 spring.cloud.nacos.discovery.server-addr=http://nacos ip address:8848 //nacos的内网地址 spring.cloud.nacos.discovery.namespace=9b289478-8fe8-43de-8f46-06a4306fda70 // nacos的命名空间ID spring.cloud.nacos.discovery.group=caiyi //你的自定义nacos组名称
- 然后在启动类上加上nacos服务发现注解
@SpringBootApplication @EnableDiscoveryClient //服务发现 public class UserServiceApplication { public static void main(String[] args) { SpringApplication.run(UserServiceApplication.class, args); } }
这时候启动项目,去到内网环境的nacos就可以找到你刚刚注册的服务实例了,至此服务注册完成。
3、服务间调用(openFeign)
- 首先找到服务调用方对应子工程pom文件,并加入对应openFeign与loadBalancer的依赖,这里默认你已经完成了服务调用方的服务注册
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency>
- 然后在启动类上添加上openFeign客户端注解赋能openFeign
@SpringBootApplication @EnableFeignClients //赋能openFeign @EnableDiscoveryClient public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } }
- 接下来创建对应的feign客户端接口,将服务生产者拉取到本服务
//这里注解括号内,是你要赋能此接口向nacos注册的服务名称 @FeignClient("user-service") public interface UserFeign { //这里采用springMVC的接口风格赋能方法,使得这个方法已经变成了服务生产者 //这里注意你的接口路径要写全,不要忽略@RequestMapping后面的路径(如果你写了的话) @GetMapping("user/getUserById") User getUserById(@RequestParam("userId") Integer userId); }
- 最后在对应的service中,注入你的feign接口,并调用你已经赋能的方法
@Service public class OrderServiceImpl implements OrderService { @Autowired private UserFeign userFeign; @Override public Order getUserOrder(Integer userId) { System.out.println("测试服务间调用"); return new Order(userFeign.getUserById(userId),1); } }
至此,服务间调用就大功告成了!
4、使用Nacos配置中心完成子工程统一配置
- 首先导入Nacos的依赖(这里默认您已经完成了父子工程依赖管理),同时还需要导入bootstrap依赖(后面会用到)
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> </dependency>
- 将子工程中的application.properties改名为bootstrap.application。这是因为application.properties是用户级的配置文件,而bootstrap是系统级的配置文件。所以后者会优于前者执行
- 在bootstrap.application中书写对应配置中心的命名空间ID,组名,dataID,配置中心
spring.application.name=user-service spring.cloud.nacos.config.server-addr=xxxx:8848 spring.cloud.nacos.config.namespace=9b289478-8fe8-43de-8f46-06a4306fda70 spring.cloud.nacos.config.group=caiyi //如果引入多个文件可以像下方这样引入单独的依赖配置做依赖共享,从0开始,以此类推 spring.cloud.nacos.config.shared-configs[0].dataId=mysql-service.properties spring.cloud.nacos.config.shared-configs[0].group=caiyi
- 在配置中心中将对应服务的注册名字,nacos地址,命名空间ID,组名,等等配置好
spring.application.name=user-service spring.cloud.nacos.discovery.group=caiyi spring.cloud.nacos.discovery.server-addr=xxxx:8848 spring.cloud.nacos.discovery.namespace=9b289478-8fe8-43de-8f46-06a4306fda70 //这里是写在nacos配置中心中的
配置完成,启动项目即可看到已经在向配置中心拉取配置的log
2024-02-21 15:13:13.945 INFO 26244 --- [ main] c.e.userservice.UserServiceApplication : Started UserServiceApplication in 4.975 seconds (JVM running for 5.755) 2024-02-21 15:13:13.959 INFO 26244 --- [ main] c.a.c.n.refresh.NacosContextRefresher : [Nacos Config] Listening config: dataId=user-service.properties, group=caiyi 2024-02-21 15:13:13.961 INFO 26244 --- [ main] c.a.c.n.refresh.NacosContextRefresher : [Nacos Config] Listening config: dataId=user-service, group=caiyi
至此配置成功。
5、引入网关服务(gateway)
在项目中,许多时候服务做了集群,而且服务部署的机器各不相同,分布式集群部署,此时我们访问服务时将不再是一个固定的地址,故此我们需要引入网关服务作为我们整个服务的代理访问入口,这样和前端进行数据交互的时候也更加规范。
- 如果想使用网关服务,首先我们需要引入gateway依赖与loadbalancer依赖,网关会默认你的服务已经不是一个单机部署的项目了,所以我们需要加入负载均衡让网关自动挑选一个合适的服务地址使用
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency>
- 这里需要说明:gateway依赖webflux,与mvc不兼容,不可引入springmvc依赖
- 然后需要在对应properties中加入如下配置,向nacos注册中心注册我们的网关服务
server.port=8888 spring.application.name=gateway-service spring.cloud.nacos.config.server-addr=xxxx:8848 spring.cloud.nacos.config.namespace=9b289478-8fe8-43de-8f46-06a4306fda70 spring.cloud.nacos.config.group=caiyi # 自动加载注册中心已注册的服务的路由 spring.cloud.gateway.discovery.locator.enabled=true
- 至此网关服务已经搭建完成,但是我们应该如何访问呢?
localhost:8888/order-service/order/getUserOrder?userId=12
通过网关的端口注册好之后,我们需要直接访问网关的端口,然后加上nacos中对应你想调用的已经注册的服务名称,而后再拼接上真实的项目中定义好的API接口地址
至此网关就搭建好了!
6、sentinal 服务熔断
一、什么是服务熔断?
服务熔断是一种容错机制,用于在系统中某个服务出现故障或异常时,防止故障蔓延并迅速恢复系统的可用性。熔断器是实现服务熔断的核心组件,它可以监控服务调用的状态,并根据一定的规则进行判断和处理。
二、为什么需要服务熔断?
防止故障蔓延:当某个服务出现故障时,熔断机制可以快速将请求切换到备用服务,避免故障蔓延到整个系统。
提高系统可用性:通过熔断机制,可以在服务不可用时快速响应,减少用户等待时间,提高系统的可用性。
降低系统负载:当大量请求涌入时,服务熔断可以防止系统过载,保证核心服务的正常运行。
三、我该怎么做服务熔断?
常见的熔断器有Hystrix、Resilience4j、sentinal等,这里以sentinal为举例:
- 在服务调用方引入依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <version>2.2.5.RELEASE</version> </dependency>
- 其次书写对应的配置文件
server.port=8081 spring.application.name=order-service spring.cloud.nacos.config.server-addr=xxxx:8848 spring.cloud.nacos.config.namespace=9b289478-8fe8-43de-8f46-06a4306fda70 spring.cloud.nacos.config.group=caiyi #我们需要添加下方这个配置,以启动sentinel熔断 feign.sentinel.enabled=true #这里是服务服务监控控制台的地址,通常会配合着运维工作对系统接口做熔断限流配置 spring.cloud.sentinel.transport.dashboard=localhost:8080
- 然后在我们的FeignClient接口中做出如下修改
//这里注解括号内,是你要赋能此接口向nacos注册的服务名称 @FeignClient(value = "user-service",fallback = UserFeignHystrixImpl.class) public interface UserFeign { //这里采用springMVC的接口风格赋能方法,使得这个方法已经变成了服务生产者 @GetMapping("user/getUserById") User getUserById(@RequestParam("userId") Integer userId); }
- fallback的值,对应的是当你的服务出现异常后,sentinal将服务熔断,并执行的回调方法所在的实现类(这个类需要实现你的FeignClient接口并重写对应的方法),同时这个类也要注册成为被spring所管理的bean对象
@Component public class UserFeignHystrixImpl implements UserFeign { @Override public User getUserById(Integer userId) { //这里书写触发熔断后的业务逻辑 return new User(500,"已触发服务熔断,稍后再试"); } } //下方是对应服务生产者可能会出现的异常接口 @RestController @RequestMapping("/user") public class UserController { @GetMapping("getUserById") public User getUserById(@RequestParam Integer userId) { Random random = new Random(); double v = random.nextDouble(); if (v > 0.5) { //这里模拟了百分之50的异常情况 v = 1 / 0; } return new User(userId, "测试用户"); } }
到这里,sentinal的服务熔断规则我们就书写完毕了,接下来我们可以结合运维工作,对我们的接口实现熔断限流等操作,这里需要使用到sentinal的可视化控制台,下载好后本地使用Java -jar 服务名,就可以启动这个服务,并管理我们的项目熔断机制。记得在服务调用方的配置文件中书写好你的可视化控制台地址
#这里是服务服务监控控制台的地址,通常会配合着运维工作对系统接口做熔断限流配置 spring.cloud.sentinel.transport.dashboard=localhost:8080
至此一个我们的熔断机制也配置完成了,完结撒花!