Spring Cloud
微服务
1.不同的微服务,不要重复开发相同的业务
2.微服务数据独立,不要访问其它微服务的数据库。
3.微服务可以将自己的业务暴露为接口,供其它微服务调用。
实现
开发环境
- 开发工具:IntelliJ IDEA 2023.2.5 Ultimate
- 开发框架:Spring boot 3.0.9
- 语言:Java 21
- 微服务框架:Spring cloud 2022.0.4
- 数据库:mysql5.7.4
- 持久层框架:mybatis3.0.3
- Java增强工具:lombok 1.18.30
构建工程
1. 创建父工程
使用"Spring Initializr"构建Spring boot项目cloud-service。
删除其他不必要的文件,只留"pom.xml"文件。
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>3.0.9</version>
<relativePath/>
</parent>
<packaging>pom</packaging>
<modules>
<module>user-service</module>
<module>order-service</module>
<module>eureka-server</module>
</modules>
<groupId>cn.zyz</groupId>
<artifactId>cloud-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>cloud-service</name>
<description>cloud-service</description>
<properties>
<java.version>21</java.version>
<spring-cloud.version>2022.0.4</spring-cloud.version>
<lombok.version>1.18.30</lombok.version>
</properties>
<dependencyManagement>
<dependencies>
<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>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>3.0.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
packaging:表示打包方式为pom
modules:表示包含的子模块
dependencies:父工程中此处的依赖都会被子模块继承
dependencyManagement:表示此处依赖不被子模块继承
groupId:子模块和父工程相同时,子模块中无需指定
2. 用户微服务
用户微服务:user-service
数据库:cloud_user,位于本地
表:tb_user(id int auto_increment primary key,name varchar(20),address varchar(100))
2.1 构建子模块
右击父工程"cloud-service"->"New Module"->"New Module"
2.2 配置
application.yml
server:
port: 8081
spring:
datasource:
url: jdbc:mysql://localhost:3306/cloud_user?useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: root
application:
name: userservice
2.3 实体类
cn.zyz.user.pojo.User
@Data
public class User {
private int id;
private String username;
private String address;
}
2.4 DAO
cn.zyz.user.mapper.UserMapper
@Mapper
public interface UserMapper {
@Select("select * from tb_user where id=#{id}")
public User getUser(int id);
}
2.5 服务类
cn.zyz.user.service.UserService
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User getUser(int id){
return userMapper.getUser(id);
}
}
2.6 控制器类
cn.zyz.user.web.UserController
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/{id}")
public User getUser(@PathVariable int id) {
User user = userService.getUser(id);
System.out.println(user);
return user;
}
}
3.订单微服务
订单微服务:order-service
数据库:cloud_order,位于虚拟机Centos上
表:tb_order(id int auto_increment primary key,name varchar(50),price decimal(10,2),num int,user_id int)
3.1 构建子模块
右击父工程"cloud-service"->"New Module"->"New Module"
3.2 配置
application.yml
server:
port: 8091
spring:
datasource:
url: jdbc:mysql://10.10.0.100:3306/cloud_order?useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: root
application:
name: orderservice
mybatis:
configuration:
map-underscore-to-camel-case: true
map-underscore-to-camel-case: true 表示将下划线命名映射为camel命名法
如:字段"user_id"映射到属性"userId"
3.3 实体类
cn.zyz.order.pojo.Order
@Data
public class Order {
private int id;
private String name;
private double price;
private int num;
private int userId;
private User user;
}
3.4 DAO
cn.zyz.order.mapper.OrderMapper
@Mapper
public interface OrderMapper {
@Select("select * from tb_order where id=#{id}")
public Order getOrder(int id);
}
3.5 服务类
cn.zyz.order.service.OrderService
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private RestTemplate restTemplate;
public Order getOrder(int id){
Order order = orderMapper.getOrder(id);
String url = "http://localhost:8081/user/";
User user = restTemplate.getForObject(url + order.getUserId(), User.class);
order.setUser(user);
return order;
}
}
3.6 控制器类
cn.zyz.order.web.OrderController
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private OrderService orderService;
@RequestMapping("/{id}")
public Order getOrder(@PathVariable int id){
return orderService.getOrder(id);
}
}
4.Eureka
服务端:记住并管理所有的微服务和心跳监控
客户端:
(1)各种服务向eureka注册服务信息
(2)消费者从eureka拉取所需的服务
(3)消费者利用负载均衡算法,从服务列表中挑选一个
(4)远程调用
说明:
消费者如何感知提供者的健康状况?
服务提供者每隔30秒会向Eureka Server发送心跳请求,报告自己的健康状态,eureka会更新记录服务列表信息,心跳不正常的会被剔除,这样消费都就可以拉取到最新的信息。
4.1 搭建Eureka Server
(1)创建子模块"eureka-server",引入依赖
pom.xml
```(2)编写启动类,添加@EnableEurekaServer注解
EurekaApplication.java
@EnableEurekaServer
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class,args);
}
}
(3)配置
application.yml
server: port: 10086 spring: application: name: eurekaserver eureka: client: service-url: defaultZone: http://127.0.0.1:10086/eureka ``` server: port: 10086 spring: application: name: eurekaserver eureka: client: service-url: defaultZone: http://127.0.0.1:10086/eureka ```(4)启动
启动后,访问"localhost:10086",就可以看到Eureka服务中心的web界面
4.2 服务注册
注册user-service服务
(1)引入eureka-client依赖
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
(2)配置eureka地址
application.yml
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
模拟多实例部署:
右键"UserApplication"服务->copy configuration->Enviroment VM options->-Dserver.port=8082
4.3 服务发现
在order-service中完成服务拉取
服务拉取是基于服务名称获得服务列表,然后在服务列表中作负载均衡
(1)引入eureka-client依赖
(2)配置eureka地址
(3)给OrderApplication中的RestTemplate作负载均衡注解
OrderApplication.java
@LoadBalanced
@Bean(name = "restTemplate")
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
String url = "http://userservice/user/";
5. Nacos
Nacos是Alibaba的产品,现在是Spring Cloud的一个组件。
Nacos致力于帮助您发现、配置和管理微服务。
5.1 安装nacos服务
下载"nacos-server-2.2.3.zip",解压后在命令行终端运行"starup.cmd -m standalone",管理页面的地址:http://localhost:8848
5.2 配置微服务
(1)父工程"cloud-service"引入Spring Cloud Alibaba管理依赖
pom.xml
<!-- alibaba的管理依赖-->
<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>
PS:
Spring boot 3.0.9
Spring Cloud 2022.0.0
Spring Cloud Alibaba 2022.0.0.0.RC1
(2)微服务"user-service"引入nacos客户端依赖
pom.xml
<!-- nacos客户端依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
PS:删除Eureka客户端依赖
(3)微服务"user-service"配置nacos服务地址
application.yml
spring:
cloud:
nacos:
server-addr: localhost:8848
(4)微服务"order-service"引入nacos客户端依赖
和(2)相同
(5)微服务"order-service"配置nacos服务地址
和(3)相同
(6)启动微服务实例
在nacos管理页面中可以发现微服务