目录
一、微服务、分布式概念
分布式思想与基本概念
二、SpringCloud 概述
三、SpringCloud 微服务环境搭建 (RestTemplate应用)
1、服务提供者 (8001) 复制粘贴即可。
2、服务消费者 (80)
RestTemplate
Hutool工具包
postman 模拟发起请求
热部署Devtools
四、Eureka:服务注册与发现
1、IDEA生成eurekaServer端服务注册中心 (7001)
2、服务提供者8001 注册到7001
3、服务消费者 注册到7001
五、Ribbon:负载均衡服务调用 ★
如何替换策略?
六、OpenFeign:服务接口远程调用 ★
Ribbon 超时设置
OpenFeign 日志打印功能
Day85.Dubbo分布式RPC框架、Zookeeper、provider | consumer 开发、管理控制台、事物问题_焰火青年·的博客-CSDN博客
https://www.martinfowler.com/articles/microservices.html 微服务microservices
微服务|YYGCui's blog
什么是微服务?
简单来说,微服务架构风格[1]是一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级(restful风格)通信机制(通常用HTTP资源API)。这些服务围绕业务能力构建并且可通过全自动部署机制独立部署。这些服务共用一个最小型的集中式的管理,服务可用不同的语言开发,使用不同的数据存储技术。
总结:
1. 微服务需要根据业务模块拆分,做到单一职责,不要重复开发相同
务。2. 微服务可以将业务暴露为接口,供其它微服务使用
3. 不同微服务都应该有自己独立的数据库
分布式服务架构
分布式一定是集群的(防止单点故障)。 而集群并不一定就是分布式的。
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。
RPC【Remote Procedure Call】是指远程过程调用,是一种进程间通信方式,他是一种技术的思想,而不是规范。
它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。
即程序员无论是调用本地的还是远程的函数,本质上编写的调用代码基本相同。
高并发
通过设计保证系统可以并行处理很多请求。应对大量流量与请求
Tomcat最多支持并发多少用户?
Tomcat 默认配置的最大请求数是 150,也就是说同时支持 150 个并发,当然了,也可以将其改大。
当某个应用拥有 250 个以上并发的时候,应考虑应用服务器的集群。
具体能承载多少并发,需要看硬件的配置,CPU 越多性能越高,分配给 JVM 的内存越多性能也就越高,但也会加重 GC 的负担。
操作系统对于进程中的线程数有一定的限制:
Windows 每个进程中的线程数不允许超过 2000
Linux 每个进程中的线程数不允许超过 1000
另外,在 Java 中每开启一个线程需要耗用 1MB 的 JVM 内存空间用于作为线程栈之用。
Tomcat 默认的 HTTP 实现是采用阻塞式的 Socket 通信,每个请求都需要创建一个线程处理。这种模式下的并发量受到线程数的限制,但对于 Tomcat 来说几乎没有 BUG 存在了。
Tomcat 还可以配置 NIO 方式的 Socket 通信,在性能上高于阻塞式的,每个请求也不需要创建一个线程进行处理,并发能力比前者高。但没有阻塞式的成熟。
这个并发能力还与应用的逻辑密切相关,如果逻辑很复杂需要大量的计算,那并发能力势必会下降。如果每个请求都含有很多的数据库操作,那么对于数据库的性能也是非常高的。
对于单台数据库服务器来说,允许客户端的连接数量是有限制的。
并发能力问题涉及整个系统架构和业务逻辑。
系统环境不同,Tomcat版本不同、JDK版本不同、以及修改的设定参数不同。并发量的差异还是满大的。
- maxThreads="1000" 最大并发数 ,默认值为200
- minSpareThreads="100"//初始化时创建的线程数,默认值为10
- acceptCount="700"// 指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理,默认值为100
Apache Tomcat 8 Configuration Reference (8.0.53) - The HTTP Connector
高并发衡量指标
- 响应时间(RT)
- 请求做出响应的时间,即一个http请求返回所用的时间
- 吞吐量
- 系统在单位时间内处理请求的数量
- QPS(Query/Request Per Second)、 TPS(Transaction Per Second)
- 每秒查询(请求)数、每秒事务数
- 专业的测试工具:Load Runner
- Apache ab
- Apache JMeter
- 并发用户数
- 承载的正常使用系统功能的用户的数量
高可用
服务集群部署
数据库主从+双机热备
- 主-备方式(Active-Standby方式)
主-备方式即指的是一台服务器处于某种业务的激活状态(即Active状态),另一台服务器处于该业务的备用状态(即Standby状态)。
- 双主机方式(Active-Active方式)
双主机方式即指两种不同业务分别在两台服务器上互为主备状态(即Active-Standby和Standby-Active状态)
注册中心
保存某个服务所在地址等信息,方便调用者实时获取其他服务信息
提供者和消费者是相对而言的
- 服务注册:服务提供者
- 服务发现:服务消费者
负载均衡
动态将请求派发给比较闲的服务器
策略:
- 轮询(Round Robin)
- 加权轮询(Weighted Round Robin)
- 随机Random
- 哈希Hash
- 最小连接数LC
- 最短响应时间LRT
服务雪崩
限流
API网关
API网关要做很多工作,它作为一个系统的后端总入口,承载着所有服务的组合路由转换等工作,除此之外,我们一般也会把安全,限流,缓存,日志,监控,重试,熔断等放到 API 网关来做。
服务跟踪
追踪服务的调用链,记录整个系统执行请求过程。如:请求响应时间,判断链中的哪些服务属于慢服务(可能存在问题,需要改善)。
弹性云
Elastic Compute Service(ECS)弹性计算服务
动态扩容,压榨服务器闲时能力
例如:双11,618,高峰时多配置些服务器,平时减少多余的服务器配置(用于其他服务应用),避免资源浪费
SpringCloud 是微服务一站式服务解决方案,微服务全家桶。它是微服务开发的主流技术栈。它采用了名称,而非数字版本号。
springCloud 和 springCloud Alibaba 目前是最主流的微服务框架组合。
SpringCloud版本选择
选用 springboot 和 springCloud 版本有约束,不按照它的约束会有冲突。
官方版本的对应信息:https://start.spring.io/actuator/info
SpringBoot2.3.6版和SpringCloud Hoxton.SR9版
SpringCloud Alibaba 2.2.6
与springboot搭建基本相同 服务提供者(cloud-provider-payment8001)、服务消费者(cloud-consumer-order80)
父工程xml
com.atguigu.springcloud
springcloud
1.0-SNAPSHOT
pom
UTF-8
1.8
1.8
4.12
1.2.17
1.16.18
8.0.26
1.1.16
1.3.0
org.springframework.boot
spring-boot-dependencies
2.3.6.RELEASE
pom
import
org.springframework.cloud
spring-cloud-dependencies
Hoxton.SR9
pom
import
com.alibaba.cloud
spring-cloud-alibaba-dependencies
2.2.6.RELEASE
pom
import
mysql
mysql-connector-java
${mysql.version}
com.alibaba
druid
${druid.version}
org.mybatis.spring.boot
mybatis-spring-boot-starter
${mybatis.spring.boot.version}
junit
junit
${junit.version}
log4j
log4j
${log4j.version}
org.projectlombok
lombok
${lombok.version}
true
org.springframework.boot
spring-boot-maven-plugin
true
true
1. 创建项目cloud-provider-payment8001,引入依赖
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
org.mybatis.spring.boot
mybatis-spring-boot-starter
com.alibaba
druid-spring-boot-starter
1.1.10
mysql
mysql-connector-java
org.springframework.boot
spring-boot-starter-jdbc
org.springframework.boot
spring-boot-devtools
runtime
true
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
2. YML配置文件
server:
port: 8001
spring:
application:
name: cloud-payment-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/cloud2022?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
username: root
password: *******
mybatis:
mapperLocations: classpath:/mapper/*.xml
type-aliases-package: com.atguigu.springcloud.entities
3. 主启动类
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan(basePackages = "com.atguigu.springcloud.dao") //扫描dao包,创建代理对象
@SpringBootApplication
public class PaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class,args);
}
}
4. 业务类
数据库表
主实体Payment
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {
private Long id;
private String serial;
}
Json封装体CommonResult
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult implements Serializable{
private Integer code;
private String message;
private T data;
public CommonResult(Integer code,String message){
this(code,message,null);//如果这行报错,请安装lombok插件
}
}
接口PaymentDao
@Component //代替@Repository声明bean
@Mapper //mybatis提供的,等价:@MapperScan("com.atguigu.springcloud.dao")
//@Repository //spring提供的。在此,只是为了声明bean对象
public interface PaymentDao {
public int create(Payment payment);
public Payment getPaymentById(@Param("id") Long id);
}
映射
insert into payment(serial) values(#{serial});
Service 接口与实现
public interface PaymentService {
public int create(Payment payment); //写
public Payment getPaymentById(Long id); //读取
}
@Service
@Transactional
public class PaymentServiceImpl implements PaymentService {
@Autowired
PaymentDao paymentDao;
@Override
public int create(Payment payment) {
return paymentDao.create(payment);
}
@Override
public Payment getPaymentById(Long id) {
return paymentDao.getPaymentById(id);
}
}
Controller
@RestController
@Slf4j
public class PaymentController {
@Resource
private PaymentService paymentService;
@PostMapping(value = "/payment/create")
public CommonResult create(Payment payment){ //埋雷
int result = paymentService.create(payment);
log.info("*****插入结果:"+result);
if (result>0){ //成功
return new CommonResult(200,"插入数据库成功",result);
}else {
return new CommonResult(444,"插入数据库失败",null);
}
}
@GetMapping(value = "/payment/get/{id}")
public CommonResult getPaymentById(@PathVariable("id") Long id){
Payment payment = paymentService.getPaymentById(id);
log.info("*****查询结果:"+payment);
if (payment!=null){ //说明有数据,能查询成功
return new CommonResult(200,"查询成功",payment);
}else {
return new CommonResult(444,"没有对应记录,查询ID:"+id,null);
}
}
}
1. 创建项目cloud-consumer-order80,引入依赖
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
org.mybatis.spring.boot
mybatis-spring-boot-starter
com.alibaba
druid-spring-boot-starter
1.1.10
mysql
mysql-connector-java
org.springframework.boot
spring-boot-starter-jdbc
org.springframework.boot
spring-boot-devtools
runtime
true
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
2. YML文件
server:
port: 80
spring:
application:
name: cloud-consumer-order80
3. 主启动
@SpringBootApplication
//@EnableEurekaClient//声明当前应用80为Eureka(7001)的客户端
//在哪个请求上,采用哪种规则
//@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class)
public class OrderMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderMain80.class,args);
}
}
4. 业务类
创建entities
(将cloud-provider-payment8001工程下的entities包下的两个实体类复制过来)
由于没有引入OpenFeign,所以暂时使用RestTemplate 类远程调用
RestTemplate提供了多种便捷访问远程Http服务的方法,是一种简单便捷的访问Restful服务模板类,是Spring 提供的用于访问Rest服务的客户端模板工具集
官网地址: RestTemplate (Spring Framework 5.2.2.RELEASE API)
使用RestTemplate访问Restful接口非常的简单粗暴无脑。(url,requestMap,ResponseBean.class)这三个参数分别代表 REST请求地址、请求参数、Http响应转换被转换成的对象类型。
缺点:面向模板类编程,不是面向接口编程
config配置类
@SpringBootConfiguration//声明一个配置类
public class ApplicationContextConfig {
//重点 模板类
//@RestTemplate 只能进行远程调用
@Bean
//@LoadBalanced //RestTemplate + Ribbon 实现远程调用和负载均衡(轮询)
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
创建controller
@RestController
public class OrderController {
//基于 RestTemplate 模板类进行远程调用
@Autowired
RestTemplate restTemplate;
public static final String PATH = "http://localhost:8001";
@RequestMapping("/consumer/payment/get/{id}")
public CommonResult get(@PathVariable("id") Long id){
CommonResult commonResult = restTemplate.getForObject(PATH + "/payment/get/" + id, CommonResult.class);
System.out.println("commonResult = " + commonResult);
return commonResult;
}
@RequestMapping("/consumer/payment/create")
public CommonResult create(@RequestBody Payment payment) {
System.out.println("payment = " + payment);
CommonResult commonResult = restTemplate.postForObject(PATH + "/payment/create", payment, CommonResult.class);
return commonResult;
}
/* //面向接口编程:推荐 使用OpenFeign组件
@Autowired
PaymentService paymentService; //注入代理对象
@RequestMapping("/consumer/payment/get/{id}")
public CommonResult get(@PathVariable("id") Long id){
Payment payment = paymentService.getPaymentById(id);
System.out.println("payment = " + payment);
return new CommonResult(200,"操作成功",payment);
}
@RequestMapping("/consumer/payment/create")
public CommonResult create(@RequestBody Payment payment){
System.out.println("payment = " + payment);
paymentService.create(payment);
return new CommonResult(200,"操作成功");
}*/
}
测试
封装实体类代码 (在弄一个工具项目,通过Maven继承传递。略)
糊涂工具包:Hutool — A set of tools that keep Java sweet.
cn.hutool
hutool-all
5.1.0
1. 子工程添加依赖、插件
org.springframework.boot
spring-boot-devtools
runtime
true
2. 父工程添加插件
下一段配置黏贴到父工程当中的pom里
org.springframework.boot
spring-boot-maven-plugin
true
true
3. Enabling automatic build
4. Ctrl+Shift+Alt+/选择Registry…,重启idea
compiler.automake.allow.when.app.running -> 自动编译
compile.document.save.trigger.delay -> 自动更新文件;它主要是针对静态文件如JS CSS的更新,将延迟时间减少后,直接按F5刷新页面就能看到效果!
热部署:2021idea找不到 Registry中没有找到compiler.automake.allow.when.app.running选项?
SpringCloud封装了Netflix公司开发的Eureka模块来实现服务治理。
在传统的RPC远程调用框架中,管理每个服务与服务之间依赖关系比较复杂、所以需要进行服务治理,管理服务与服务之间依赖关联,以实现服务调用,负载均衡、容错等,实现服务发现与注册。
Eureka Client通过注册中心进行访问
是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、默认使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会在Eureka Server发送心跳(默认周期30秒,zookeeper为10秒)。如果Eureka Server在多个心跳周期内没有收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移出(默认90秒)
Eureka两组件
- Eureka Server提供服务注册服务
各个微服务节点通过配置启动后,会在Eureka Server中进行注册,这样Eureka Server中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。
- Eureka Client通过注册中心进行访问
是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会在Eureka Server发送心跳(默认周期30秒)。如果Eureka Server在多个心跳周期内没有收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移出(默认90秒)
1.新建项目 cloud-eureka-server7001,导入依赖
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
com.atguigu.springcloud
cloud-api-commons
${project.version}
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
org.springframework.boot
spring-boot-devtools
runtime
true
org.projectlombok
lombok
org.springframework.boot
spring-boot-starter-test
test
junit
junit
2. 配置application.yml 文件
server:
port: 7001
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false
fetchRegistry: false
service-url:
defaultZone: http://localhost:7001/eureka
3. 启动类,添加@EnableEurekaServer注解
@SpringBootApplication
@EnableEurekaServer //声明当前应用为Eureka服务器端
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class,args);
}
4. 测试访问 http://localhost:7001/
1. 修改项目 cloud-provider-payment8001,导入依赖
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
2. 修改 YML配置文件
#8001 向 7001进行注册
eureka:
client:
register-with-eureka: true
fetchRegistry: true
service-url:
defaultZone: http://localhost:7001/eureka
3.主启动 加入@EnableEurekaClient注解
@SpringBootApplication
@MapperScan(basePackages = "com.atguigu.springcloud.dao") //扫描dao包,创建代理对象
@EnableEurekaClient //声明当前应用8001为Eureka(7001)的客户端
public class PaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class,args);
}
}
1. 新建Module:cloud-consumer-order80,导入依赖
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
2. 添加YML配置文件
eureka:
client:
register-with-eureka: true
fetchRegistry: true
service-url:
defaultZone: http://localhost:7001/eureka
3.主启动类 加入@EnableEurekaClient注解
@SpringBootApplication
@EnableEurekaClient//声明当前应用80为Eureka(7001)的客户端
//在哪个请求上,采用哪种规则(ribbon)
//@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class)
public class OrderMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderMain80.class,args);
}
}
测试
http://localhost/consumer/payment/get/31
测试8001服务和80服务效果一样
Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。
简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。
Ribbon客户端组件提供一系列完善的配置项,如:连接超时,重试等。
简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。
Ribbon目前也进入维护模式,未来替换方案: Spring Cloud LoadBalancer
注:Feign、Nacos 默认集成了 Ribbon
- Ribbon的本地负载均衡客户端 VS Nginx服务端负载均衡区别:
- Nginx是服务器负载均衡,客户端所有请求都会交给Nginx,然后,由nginx实现转发请求。即负载均衡是由服务器端完成的。
- Ribbon本地负载均衡,在调用微服务接口时候,会在注册中心上获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程服务调用。
- 集中式LB
- 即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5,也可以是软件,如Nginx),由该设施负责把访问请求通过某种策略转发至服务的提供方;
- 进程内LB
- 将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。
- Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。
- Ribbon=负载均衡+RestTemplate调用
1. 引入依赖
2. 服务消费者80 配置类中 模板对象加入注解 @LoadBalanced
@SpringBootConfiguration//声明一个配置类
public class ApplicationContextConfig {
//重点 模板类
//RestTemplate 只能进行远程调用
@Bean
@LoadBalanced //RestTemplate + Ribbon 实现远程调用和负载均衡(轮询)
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
3. 修改地址
//public static final String PATH = "http://localhost:8001";
//修改接收请求地址: 从7001订阅服务,获取三个实例
public static final String PATH = "http://CLOUD-PAYMENT-SERVICE";
@RequestMapping("/consumer/payment/get/{id}")
public CommonResult get(@PathVariable("id") Long id){
CommonResult commonResult = restTemplate.getForObject(PATH + "/payment/get/" + id, CommonResult.class);
System.out.println("commonResult = " + commonResult);
return commonResult;
}
4. 构建支付服务提供者集群环境
启动三个服务,设置不同端口。测试轮询效果
Ribbon 底层使用了 Irule 接口,实现各种负载均衡策略
IRule:根据特定算法从服务列表中选取一个要访问的服务
- com.netflix.loadbalancer.RoundRobinRule 轮询,默认策略。
- com.netflix.loadbalancer.RandomRule 随机
- com.netflix.loadbalancer.RetryRule 先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务
- WeightedResponseTimeRule 对RoundRobinRule的扩展,响应速度越快的实例选择权重越大,越容易被选择
- BestAvailableRule 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
- AvailabilityFilteringRule 先过滤掉故障实例,再选择并发较小的实例
- ZoneAvoidanceRule 默认规则,复合判断server所在区域的性能和server的可用性选择服务器
自定义配置类不能放在@ComponentScan所扫描的当前包下以及子包下,否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,达不到特殊化订制的目的了。
1. 在启动类上一级新建MySelfRule规则类
@Configuration
public class MySelfRule {
@Bean
public IRule myRule(){
return new RandomRule();//定义为随机
}
}
2. 主启动类添加@RibbonClient
@SpringBootApplication
@EnableEurekaClient//声明当前应用80为Eureka(7001)的客户端
//在哪个请求上,采用哪种规则
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class)
public class OrderMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderMain80.class,args);
}
}
Feign是一个声明式的web服务客户端,让编写web服务客户端变得非常容易,只需创建一个接口并在接口上添加注解即可。(上面的例子使用了RestTemplate)
SpringCloud 对Feign 进行了封装,使其支持了SpringMVC标准注解和HttpMessageConverters。Feign 可以与 Eureka 和 Ribbon 组合使用以支持 负载均衡。
接口定义:狭义:interface声明的类 广义:对外暴露的类、方法也可称为接口
Feign 集成了 Ribbon
利用Ribbon维护了Payment的服务列表信息,并且通过轮询实现了客户端的负载均衡。而与Ribbon不同的是,通过Feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用。
Feign和OpenFeign两者区别
使用方式:微服务调用接口+@FeignClient
1. 新建Module:cloud-consumer-feign-order80,导入依赖
org.springframework.cloud
spring-cloud-starter-openfeign
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
com.atguigu.springcloud
cloud-api-commons
${project.version}
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
org.springframework.boot
spring-boot-devtools
runtime
true
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
2. YML文件
server:
port: 80
spring:
application:
name: cloud-consumer-feign-order80
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:7001/eureka
3. 主启动类 添加注解@EnableFeignClients
@SpringBootApplication
@EnableEurekaClient //声明当前应用80为Eureka(7001)的客户端
@EnableFeignClients //启用OpenFeign组件远程调用功能
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class);
}
}
4. 业务层 创建接口并新增注解 @FeignClient
//远程调用接口:
@Component //声明bean对象,创建代理对象,进行远程调用
@FeignClient("CLOUD-PAYMENT-SERVICE") //指定调用微服务的名称
public interface PaymentFeignService {
//接口方法声明要求:需要与被调用的服务的controller方法声明保持一致
@GetMapping(value = "/payment/get/{id}")
public CommonResult getPaymentById(@PathVariable("id") Long id);
@PostMapping(value = "/payment/create")
public CommonResult create(@RequestBody Payment payment);
}
4. 控制层Controller
@RestController
public class OrderFeignController {
//远程调用微服务接口(默认集成Ribbon 轮询),实现原原理: 代理
@Autowired
PaymentFeignService paymentFeignService;
@RequestMapping("/consumer/payment/get/{id}")
public CommonResult getPaymentById(@PathVariable("id") Long id){
CommonResult commonResult = paymentFeignService.getPaymentById(id);
return commonResult;
}
}
5. 测试
OpenFeign远程调用 默认一秒超时,有时候我们需要设置Feign客户端的超时控制,即Ribbon的超时时间,因为Feign集成了Ribbon进行负载均衡。
如果不配置ribbon的重试次数,默认会重试一次。
注意:
默认情况下,GET方式请求无论是连接异常还是读取异常,都会进行重试
非GET方式请求,只有连接异常时,才会进行重试
如果对增删改进行重试,应通过乐观锁机制,进行幂等处理,防止重复提交
1、修改yml配置文件
ribbon:
ReadTimeout: 3000
ConnectTimeout: 3000
MaxAutoRetries: 1 #同一台实例最大重试次数,不包括首次调用
MaxAutoRetriesNextServer: 1 #重试负载均衡其他的实例最大重试次数,不包括首次调用
OkToRetryOnAllOperations: false #是否所有操作都重试(false时只对get重试)
#hystrix(降级熔断)的超时时间
hystrix:
command:
default:
execution:
timeout:
enabled: true
isolation:
thread:
timeoutInMilliseconds: 9000
一般情况下 都是 ribbon 的超时时间(<)hystrix的超时时间(因为涉及到ribbon的重试机制)
日志级别
NONE:默认的,不显示任何日志
BASIC:仅记录请求方法、RUL、响应状态码及执行时间
HEADERS:除了BASIC中定义的信息之外,还有请求和响应的头信息
FULL:除了HEADERS中定义的信息之外,还有请求和响应的正文及元数据
1. 配置类,配置日志bean,指定日志级别
@Configuration //用哪个都可以,一个SpringBoot提供,一个spring提供
//@SpringBootConfiguration
public class FeignConfig {
@Bean
public Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
}
2. YML配置需要开启日志的Feign客户端
logging:
level:
com.atguigu.springcloud.service.PaymentFeignService: debug