微服务架构
- SpringCloud
服务注册发现:Nacos
服务限流降级:Sentinel
分布配置中⼼:Nacos
分布式事务保证数据一致性:Seata
分布式定时任务:Spring Scheduling Tasks
服务⽹关:SpringCloud Gateway
异步消息削峰填谷:RocketMQ
服务之间调⽤:OpenFeign、Ribbon
链路追踪:Sleuth+Zipkin
技术栈版本控制
序号 | 名称 | 版本 | 用途 | 备注 |
---|---|---|---|---|
1 | openJDK | 21 | Java JDK | |
2 | postgresSQL | 17.4 | 基础数据库 | |
3 | Maven | 3.9.9 | Java第三方依赖包管理工具 | |
4 | springboot | 3.4.3 | Java MVC框架 | |
5 | springcloud | 2024.0.1 | 微服务框架 | |
6 | springcloud Alibaba | 2023.0.3.2 | 阿里巴巴微服务框架扩展 |
组件版本控制
序号 | 名称 | 版本 | 用途 | 备注 |
---|---|---|---|---|
1 | Nacos | 2.5.1 | 服务注册发现、分布配置中⼼ | |
2 | Sentinel | 1.8.8 | 服务限流降级 | 面向云原生微服务的高可用流控防护组件 |
3 | Seata | 2.3.0 | 分布式事务保证数据一致性 |
什么是注册中心(服务治理)
- 服务注册:服务提供者provider,启动的时候向注册中心上报自己的网络信息
- 服务发现:服务消费者consumer,启动的时候向注册中心上报自己的网络信息,拉取provider的相关网络信息
- 核心:服务管理,是有个服务注册表,心跳机制动态维护,服务实例在启动时注册到服务注册表,并在关闭时注销。
为什么要用
微服务应用和机器越来越多,调用方需要知道接口的网络地址,如果靠配置文件的方式去控制网络地址,对于动态新增机器,维护带来很大问题
主流的注册中心:zookeeper、Eureka、consul、etcd、Nacos
AlibabaCloud搭配最好的是Nacos,且服务的注册发现之外,还支持动态配置服务
这里我买了一个云服务器。
nacos下载二进制包即可。
https://nacos.io/download/nacos-server/
这里我用的是最新稳定版2.5.1。
把zip包放到云服务器,并解压:
安装openjdk21(java8以上都行)
unzip ./nacos-server-2.5.1.zip
sudo apt update
sudo apt install openjdk-21-jdk -y
java -version
下载nacos-server-2.5.1.tar.gz
https://github.com/alibaba/nacos/tags
解压安装包
解压Nacos压缩包。
tar -zxvf nacos-server-2.5.1.tar.gz
进入Nacos目录。
cd /home/ubuntu/nacos
启动Nacos,可以选择单机模式运行。
bash bin/startup.sh -m standalone -Dnacos.home=/home/ubuntu/nacos
如果是云服务记得把防火墙打开:
访问 localhost:8848/nacos(我的是http://106.55.xxx.xxx:8848/nacos)
默认账号密码 nacos/nacos
这里只需要用到nacos的服务管理功能。
设置nacos鉴权
Nacos自2.2.2版本开始,在未开启鉴权时,默认控制台将不需要登录即可访问,同时在控制台中给予提示,提醒用户当前集群未开启鉴权。
https://nacos.io/zh-cn/docs/v2/guide/user/auth.html
打开服务器/home/ubuntu/nacos/conf中的application.properties:
修改如下:
### The auth system to use, currently only 'nacos' and 'ldap' is supported:
nacos.core.auth.system.type=nacos
### 开启鉴权
nacos.core.auth.enabled=true
### The default token (Base64 String):
nacos.core.auth.plugin.nacos.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789
### 关闭使用user-agent判断服务端请求并放行鉴权的功能
nacos.core.auth.enable.userAgentAuthWhite=false
### 配置自定义身份识别的key(不可为空)和value(不可为空)
nacos.core.auth.server.identity.key=nacos
nacos.core.auth.server.identity.value=nacos
重启nacos:
bash /home/ubuntu/nacos/bin/shutdown.sh
cd /home/ubuntu/nacos && bash /home/ubuntu/nacos/bin/startup.sh -m standalone
登录:
基于nacos——实现实现订单-视频服务之间的调用
视频服务集成Nacos
添加依赖
<!--添加nacos客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
因为一些我搞不清楚的原因 ,idea的maven无法install依赖包,一直红色,但install又成功无报错。
解决办法:单独拉取
用管理员权限打开命令提示符,demo如下:
mvn dependency:get -DremoteRepositories=https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-nacos-discovery -DgroupId=com.alibaba.cloud -DartifactId=spring-cloud-starter-alibaba-nacos-discovery -Dversion=2023.0.1.2
mvn dependency:get -DremoteRepositories=https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter -DgroupId=com.github.pagehelper -DartifactId=pagehelper-spring-boot-starter -Dversion=2.1.0
然后idea右击项目名称,maven->重新加载项目即可。
接下来报错
yml中添加
spring:
cloud:
nacos:
config:
import-check:
enabled: false
加上后仍然报错
2024-09-01T20:58:12.607+08:00 WARN 42708 --- [online-edu-video-service] [ing.grpc.redo.0] com.alibaba.nacos.client.naming : Grpc Connection is disconnect, skip current redo task
2024-09-01T20:58:12.909+08:00 ERROR 42708 --- [online-edu-video-service] [ main] c.a.n.c.remote.client.grpc.GrpcClient : Server check fail, please check server 106.55.179.127 ,port 9848 is available , error ={}
还需要把7848、9848都暴露出来。(这里我暴露了7848,8848,8849,9848,9849五个接口)
然后又报错use is null等错误。
最后解决如下:
实际在我们父项目引入spring-cloud-alibaba-dependencies后,相当于引入了一系列版本管控好的包。
所以只要是其中的包,都不需要单独引入,子项目用的2时候,单独引入下面的子依赖包即可。
因此优化online-edu\pom.xml
这里我开始删除lombok包,因为他的一些缺陷并不想用,因此去掉。
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>org.online_edu</groupId>
<artifactId>online-edu</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>online-edu-common</module>
<module>online-edu-video-service</module>
<module>online-edu-user-service</module>
<module>online-edu-order-service</module>
<module>online-edu-generator</module>
</modules>
<!-- 一般来说父级项目的packaging都为pom,packaging默认类型jar类型-->
<packaging>pom</packaging>
<properties>
<java.version>21</java.version>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- **************************** 分布式核心 **************************** -->
<spring-boot-dependencies.version>3.3.4</spring-boot-dependencies.version>
<spring-cloud-dependencies.version>2023.0.5</spring-cloud-dependencies.version>
<spring-cloud-alibaba-dependencies.version>2023.0.3.2</spring-cloud-alibaba-dependencies.version>
<spring-cloud-starter-loadbalancer.version>4.2.1</spring-cloud-starter-loadbalancer.version>
<spring-cloud-starter-openfeign.version>4.2.1</spring-cloud-starter-openfeign.version>
<!-- **************************** 分布式核心 **************************** -->
<!-- **************************** 数据库依赖 **************************** -->
<mybatis-plus-spring-boot3-starter.version>3.5.10.1</mybatis-plus-spring-boot3-starter.version>
<mybatis-plus-generator.version>${mybatis-plus-spring-boot3-starter.version}</mybatis-plus-generator.version>
<postgresql.version>42.7.5</postgresql.version>
<druid-spring-boot-3-starter.version>1.2.24</druid-spring-boot-3-starter.version>
<pagehelper-spring-boot-starter.version>2.1.0</pagehelper-spring-boot-starter.version>
<!-- **************************** 数据库依赖 **************************** -->
<!-- **************************** 工具类 **************************** -->
<org.mapstruct.version>1.6.0</org.mapstruct.version>
<commons-collections4.version>4.5.0-M3</commons-collections4.version>
<guava.version>33.4.5-jre</guava.version>
<hutool-all.version>5.8.36</hutool-all.version>
<!-- **************************** 工具类 **************************** -->
</properties>
<!--锁定版本-->
<dependencyManagement>
<dependencies>
<!-- **************************** 分布式核心 **************************** -->
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot-dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud-dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-alibaba-dependencies -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba-dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-loadbalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<version>${spring-cloud-starter-loadbalancer.version}</version>
</dependency>
<!-- 负载均衡-openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>${spring-cloud-starter-openfeign.version}</version>
</dependency>
<!-- **************************** 分布式核心 **************************** -->
<!-- **************************** 数据库依赖 **************************** -->
<!-- MyBatis-Plus启动器,增强版MyBatis,提供更高效的操作和动态SQL能力 -->
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-spring-boot3-starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>${mybatis-plus-spring-boot3-starter.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-generator -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>${mybatis-plus-generator.version}</version>
</dependency>
<!-- PostgreSQL的JDBC驱动 -->
<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql.version}</version>
</dependency>
<!-- Druid组件 -->
<!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-3-starter -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
<version>${druid-spring-boot-3-starter.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper-spring-boot-starter.version}</version>
</dependency>
<!-- **************************** 数据库依赖 **************************** -->
<!-- **************************** 工具类 **************************** -->
<!-- 一个用于在 Java Bean 之间转换的代码生成工具。-->
<!-- 官网:https://mapstruct.org/ -->
<!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct-processor -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<!-- commons-lang3: 通用的、可复用的 Java 组件,已其他包引入-->
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<!--(Map、List、Set集合全覆盖)集合开发工具-->
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>${commons-collections4.version}</version>
</dependency>
<!-- Java增强器,像Java Next版本-->
<!-- 集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、
并发库 [concurrency libraries] 、通用注解 [common annotations] 、
字符串处理 [string processing] 、I/O 等等-->
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<!-- Java必备工具库 -->
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool-all.version}</version>
</dependency>
<!-- JSON序列化和反序列化 :已由别的包引入-->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<!-- **************************** 工具类 **************************** -->
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
online-edu-order-service/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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.online_edu</groupId>
<artifactId>online-edu</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>online-edu-order-service</artifactId>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.online_edu</groupId>
<artifactId>online-edu-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.alibaba.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>-->
<!-- </dependency>-->
<!-- 添加nacos客户端——服务注册 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
</dependency>
<!-- PostgreSQL的JDBC驱动 -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
</dependency>
</dependencies>
</project>
online-edu-order-service/src/main/resources/application.yml
server:
port: 8000
spring:
application:
name: online-edu-order-service
cloud:
nacos:
discovery:
server-addr: xxx.xxx.xxx.xxx:8848
username: nacos
password: xxxx8848
datasource:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:postgresql://localhost:5432/online_edu?currentSchema=video_order
username: postgres
password: 123456
driver-class-name: org.postgresql.Driver
druid:
# 数据库
# 连接池-初始化大小
initial-size: 10
# 连接池-最大连接数
max-active: 100
# 最大等待时间
max-wait: 60000
# 连接池-最小空闲数
min-idle: 10
# 检测空闲连接
test-while-idle: true
# 最小空闲时间
min-evictable-idle-time-millis: 300000
mybatis-plus:
# Mapper XML文件路径
mapper-locations: classpath:/mapper/**/*.xml
# 实体类别名包路径
type-aliases-package: org.online_edu.domain
configuration:
# MyBatis底层日志实现
# 控制台输出sql、下划线转驼峰
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
map-underscore-to-camel-case: true
# PageHelper分页插件
pagehelper:
# 数据库类型
helperDialect: postgresql
# 是否合理处理count查询
reasonable: true
# 支持通过Map传入分页参数
supportMethodsArguments: true
# 自定义参数
params: count=countSql
online-edu-order-service/src/main/java/org/online_edu/OrderApplication.java
package org.online_edu;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* @Author: bobokaka
* @Date: 2024-08-23 00:18:14
* @LastEditors: bobokaka
* @Description: desc
**/
@SpringBootApplication()
@MapperScan("org.online_edu.dao")
@EnableDiscoveryClient
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
运行,没问题。
其他几个服务一样配置。
服务相互调用——视频订单调用视频。
@RestController
@RequestMapping("/api/v1/video_order")
public class VideoOrderController {
/**
* 服务对象
*/
@Autowired
private VideoOrderService videoOrderService;
@Autowired
private RestTemplate restTemplate;
@RequestMapping("save")
public Object save(@RequestParam(name="videoId") int videoId) {
Video video = restTemplate.getForObject(
"http://localhost:9000/api/v1/video/find_by_id?videoId=" + videoId, Video.class);
VideoOrder videoOrder = new VideoOrder();
if (video != null) {
videoOrder.setVideoId(video.getId());
videoOrder.setVideoTitle(video.getTitle());
videoOrder.setCreateTime(new Date());
}
return videoOrder;
}
}
改成
@RestController
@RequestMapping("/api/v1/video_order")
public class VideoOrderController {
/**
* 服务对象
*/
@Autowired
private VideoOrderService videoOrderService;
@Autowired
private RestTemplate restTemplate;
/**
* 可以拉到注册服务的列表
*/
@Autowired
private DiscoveryClient discoveryClient;
@RequestMapping("save")
public Object save(@RequestParam(name = "videoId") int videoId) {
// Video video = restTemplate.getForObject(
// "http://localhost:9000/api/v1/video/find_by_id?videoId=" + videoId, Video.class);
// 传入在nacos注册的服务名
List<ServiceInstance> list = discoveryClient.getInstances("online-edu-video-service");
ServiceInstance serviceInstance = list.get(0);
Video video = restTemplate.getForObject(
"http://" + serviceInstance.getHost() +":"+serviceInstance.getPort()+ "/api/v1/video/find_by_id?videoId=" + videoId, Video.class);
VideoOrder videoOrder = new VideoOrder();
if (video != null) {
videoOrder.setVideoId(video.getId());
videoOrder.setVideoTitle(video.getTitle());
videoOrder.setCreateTime(new Date());
}
return videoOrder;
}
}
浏览器打开http://localhost:8000/api/v1/video_order/save?videoId=40
:
断点: