2.3.4.多模块项目创建
- 第一步:创建父项目,在父项目中导入Jar包
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
<mysql.version>5.1.47</mysql.version>
<mybatis.version>2.1.1</mybatis.version>
</properties>
<!--1.管理 SpringBoot的jar包-->
<!--SpringBoot-->
<parent>
<groupId> org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<!--2. 统一管理相关依赖,供子项目直接引入使用-->
<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>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<!--3.这里是所有子项目都可以用的jar包-->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
-
第二步:创建其他微服务项目
-
POM坐标导入
<dependencies>
<!--springboot web开发组件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--数据库连接驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--springboot集成mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!--springboot maven构建插件-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
mysql、mybatis的yml配置
server:
port: 8080
spring:
application:
name: order-server
datasource:
url: jdbc:mysql://localhost:3306/****?useSSL=false
username: root
password: ****
driver-class-name: com.mysql.jdbc.Driver
eureka:
client:
serviceUrl: # Eureka客户端配置,指向注册中心地址
defaultZone: http://localhost:****/eureka/
instance:
prefer-ip-address: true # 开启使用IP地址进行注册
instance-id: order-server:8080 # 修改实例Id
mybatis:
type-aliases-package: cn.tan.user.pojo # 数据库别名配置
configuration:
map-underscore-to-camel-case: true # 数据库表字段名和Java对象属性名之间的映射
logging:
level:
cn.tan: debug
pattern:
dateformat: MM-dd HH:mm:ss:SSS
第一步:抽取公共模块
第二步:打包公共模块,并将Jar包放入到Maven本地仓库中
第三步:在Maven本地仓库中找到刚才打包好的Jar包,Jar包路径就是此模块pom中自己的GAV坐标地址
第四步:在User服务、Order服务中使用GAV坐标引入cloud-common公共模块
2.6.3.订单服务实现远程调用
①注入RestTemplate到IOC容器中
②发起远程调用
2.6.4.结果
启动服务:
3.SpringCloudNetflix-Eureka
3.2.EurekaServer搭建
- **第一步:创建eureka-server模块,并导入依赖 **
<dependencies>
<!--Eureka服务依赖,包含了Eureka客户端包、Springboot-start-web包-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
- 第二步:编写启动类
/**
* @Description EurekaServer服务启动类
*/
@SpringBootApplication
//开启Eureka服务注册中心
@EnableEurekaServer
public class EurekaServerApp {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApp.class,args);
}
}
- **第三步:编写配置文件 application.yml **
server: # Eureka服务端端口号
port: 1010
eureka: # Eureka配置
instance:
hostname: localhost # Eureka服务名称
client: # Eureka客户端配置
registerWithEureka: false # 该服务不注册到到注册中心
fetchRegistry: false # 该服务不拉取注册表
serviceUrl: # 注册中心地址 http://localhost:1001/eureka/
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
- 第四步:启动Eureka服务端,访问Eureka服务可视化页面,看到以下页面说明Eureka服务端搭建成功
3.3.EurekaClient搭建-用户服务【应用】
3.3.1.基本搭建
- 现在我们的注册中心已经搭建好了,那么接下来我们要搭建用户服务注册进注册中心中
- 第一步:导入依赖
<dependencies>
<!--引入Eureka的客户端依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
- 第二步:修改配置文件
eureka:
client:
serviceUrl: # Eureka客户端配置,指向注册中心地址
defaultZone: http://localhost:1010/eureka/
- 第三步:修改启动类
- @EnableEurekaClient :标记为eureka客户端
/**
* @Description 用户服务启动类
* @Author Raymon
* @Date 2023/4/7 10:42
* @Version 1.0
*/
@MapperScan("cn.tan.mapper")
@SpringBootApplication
// 表名此服务是Eureka客户端,开启Eureka客户端功能,不加此注解默认也开启客户端功能
@EnableEurekaClient
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
- 第四步:启动User服务,在Eureka注册中心中查看User服务
3.3.2.服务配置
spring:
application: # 指定此服务的应用名称
name: user-server
eureka:
client: # Eureka客户端配置,指向注册中心地址
serviceUrl:
defaultZone: http://localhost:1010/eureka/
instance:
prefer-ip-address: true # 开启使用IP地址进行注册
- Eureka服务实例Id默认是显示的电脑名称,我们可以进行修改
eureka:
client: # Eureka客户端配置,指向注册中心地址
serviceUrl:
defaultZone: http://localhost:1010/eureka/
instance:
prefer-ip-address: true # 开启使用IP地址进行注册
instance-id: user-server:1020 # 修改实例Id
3.3.3.Eureka自我保护机制
eureka: # Eureka配置
instance: # 定义该服务Ip
hostname: localhost
client: # Eureka客户端配置
registerWithEureka: false # 该服务不注册到到注册中心
fetchRegistry: false # 该服务不拉取注册表
serviceUrl: # 注册中心地址 http://localhost:1001/eureka/
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
server:
enable-self-preservation: false # 关闭Eureka自我保护机制
3.3.4.Eureka其他配置
# 从上一次收到心跳之后,等待下一次心跳的时间,也就是服务剔除时间,默认90秒
lease-expiration-duration-in-seconds: 30
# 发送心跳时间,默认30秒
lease-renewal-interval-in-seconds: 10
# 服务发现时间,默认30秒
registry-fetch-interval-seconds: 10
# 自我保护续约百分比,默认是0.85
renewal-percent-threshold: 0.85
3.4.EurekaClient搭建
- 第一步:导入依赖
<dependencies>
<!--引入Eureka的客户端依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
- 第二步:修改配置文件
# 1.定义当前服务自己的端口号
server:
port: 8080
# 2.定义当前服务自己的服务名
spring:
application:
name: order-server
# 3.定义eureka客户端相关配置项
eureka:
client: # Eureka客户端配置,指向注册中心地址
service-url:
defaultZone: http://localhost:1010/eureka/
instance: # Eureka自身实例配置
instance-id: order-server:1030 # 修改实例Id
prefer-ip-address: true # 开启使用IP地址进行注册
- 第三步:修改启动类
/**
* @Description 订单服务启动类
* @Author Raymon
* @Date 2023/4/7 15:09
* @Version 1.0
*/
@SpringBootApplication
@EnableEurekaClient
public class OrderServerApp {
public static void main(String[] args) {
SpringApplication.run(OrderServerApp.class,args);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
3.5.用户服务集群搭建【掌握】
- 第一步:在右上角的服务启动栏中复制一个我们想要集群的服务,修改端口号、实例Id进行启动
- -Dserver.port=1021 -Deureka.instance.instance-id=user-server:1021
4.SpringCloudNetflix-Ribbon
4.2.集成Ribbon
- 我们使用Ribbon其实就是让我们的RestTemplate拥有负载均衡能力
第一步:导入Jar包
<!--Ribbon依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
第二步:修改RestTemplate的Bean的定义方法,加上Ribbon的负载均衡注解@LoadBalanced赋予RestTemplate有负债均衡的能力
第三步:在调用时,使用应用名称称代替IP地址,这样RestTemplate会在服务下的集群服务中进行轮询选择
第四步:为了方便我们查看到底调用的是user-server中的那个服务,我们在user对象中可以添加一个属性port,然后每次查询的时候设置当前的端口号
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
@Value("${server.port}")
private String port;
@Autowired
private UserService userService;
/**
* 路径: /user/110
* @param id 用户id
* @return 用户
*/
@GetMapping("/{id}")
public User queryById(@PathVariable("id") Long id) {
User user = userService.queryById(id);
user.setPort(port);
return user;
}
}
4.3.负载均衡算法
4.3.1.Ribbon内置算法
4.3.2.配置负载均衡算法
- Ribbon可以进行全局负载均衡算法配置,也可以针对于具体的服务做不同的算法配置,同时可以使用注解方式和yml配置方式来实现上面两种情况
01.注解负载均衡配置
- 随机算法的效果最好演示,我们把负载均衡算法修改成随机算法,只需要RandomRule配置成Bean即可
- 在调用方order-server进行全局配置,配置完成后重启服务,进行测试
/**
* 配置负载均衡为随机算法
*/
@Bean
public IRule randomRule(){
return new RandomRule();
}
02.YML方式配置负载均衡
- 配置全局Ribbon算法,在服务调用方进行配置
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
- 配置某个服务的Ribbon算法,在服务调用方进行配置
user-server:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
4.4.Ribbon调优配置
1.超时配置
ribbon:
ReadTimeout: 3000 #读取超时时间
ConnectTimeout: 5000 #链接超时时间
MaxAutoRetries: 1 #重试机制:同一台实例最大重试次数
MaxAutoRetriesNextServer: 1 #重新负载均衡其他实例的重试次数
OkToRetryOnAllOperations: false #是否所有操作都重试,因为针对post请求如果没做幂等处理可能会造成数据多次添加/修改
2.饥饿加载
ribbon:
eager-load:
enabled: true #开启饥饿加载
clients: user-server #针对于哪些服务需要饥饿加载