Spring Cloud 服务调用与熔断

远程过程调⽤用(RPC)

一个计算机通信协议。该协议允许运⾏行行于⼀一台计算机的程序调⽤用另⼀一台计算机的⼦子程序,⽽而程序员 ⽆无需额外地为这个交互作⽤用编程。如果涉及的软件采⽤用⾯面向对象编程,那么远程过程调⽤用亦可称作 远程调⽤用或远程⽅方法调⽤用

  • 例如
    • Java RMI( ⼆二进制协议)
    • WebServices(⽂文本协议)
  • 消息传递
    RPC 是⼀一种请求-响应协议,⼀一次 RPC在客户端初始化,再由客户端将请求消息传递到远程的服 务器器,执⾏行行指定的带有参数的过程。经过远程服务器器执⾏行行过程后,将结果作为响应内容返回到客 户端。
  • 存根(Stub)
    在⼀一次分布式计算 RPC 中,客户端和服务器器转化参数的⼀一段代码。 由于存根的参数转化,RPC 执⾏行行过程如同本地执⾏行行函数调⽤用。存根必须在客户端和服务器器两端均装载,并且保持兼容

Spring Cloud Feign

  • 依赖

    • org.springframework.cloud:spring-cloud-starter-feign
  • 激活

    • @EnableFeignClients
  • 申明

    • @FeignClient
  • 默认组件

    • Decoder/Encoder : ResponseEntityDecoder / SpringEncoder
    • Logger : Slf4jLogger
    • Contract : SpringMvcContract
    • Feign.Builder : HystrixFeign.Builder
    • Client : LoadBalancerFeignClient(Ribbon 激活的话)

Feign、Spring Cloud Open Feign、JAX-RS、Spring Web MVC 注解驱 动特性

REST 框架使用场景请求映射注解请求参数
Feign客户端声明@RequestLine@Param
Spring Cloud Open Feign客户端声明@RequestMapping@RequestParam
JAX-RS客户端声明、服务端声明@Path@*Param
Spring Web MVC服务端声明@RequestMapping@RequestParam

Spring Cloud Open Feign 利用 Feign 高扩展性,使用标准 Spring Web MVC 来声明客户端 Java 接口

  • Feign
    • 注解扩展性
    • HTTP 请求处理
    • REST 请求元信息解析
  • Spring Cloud Open Feign
    • 提供 Spring Web MVC 注解处理
    • 提供 Feign 自动装配

Spring Cloud Open Feign 是通过 Java 接口的方式来声明 REST 服务提 供者的请求元信息,通过调用 Java 接口的方式来实现 HTTP/REST 通 讯。

实现细节猜想

  • Java 接口(以及方法)与 REST 提供者元信息如何映射
  • @FeignClient 注解所指定的应用(服务)名称可能用到了服务发 现,一个服务可以对应多个服务实例(HOST:PORT)
  • @EnableFeignClients 注解是如何感知或加载标注
  • @FeignClient 的配置类(Bean)
  • Feign 请求和响应的内容是如何序列化和反序列化对应的 POJO 的

Feign 扩展支持 ( Contract 接口扩展)

  • 内建 Feign 注解
  • JAX-RS 1/2 注解
  • JAXB
  • OkHttp

Contract 接口扩展:提供 Feign 接口方法与 REST 请求元信息契 约,解析出相关的方法元信息

基本步骤

service-client -> service-provider( Spring Boot + Web MVC + 服务注 册与发现)

  1. 增加依赖

    org.springframework.cloud:spring-cloud-starteropenfeign

  2. 激活Feign客户端

    @SpringBootApplication 
    @EnableFeignClients 
    public class Application {    
        ... 
    }
    
  3. 定义Feign的接口

    @FeignClient("stores") // "stores" 应用(服务)名称 
    public interface StoreClient {
        @RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json")    
        Store update(@PathVariable("storeId") Long storeId, Store store); 
    }
    

常见一些Spring Boot/Cloud中的坑

@Value(“server.port”)服务端口不一定靠谱,当server.port为0时

@LocalServerPort也不靠谱,因为在注入阶段"local.server.port"也不一定存在

Spring Cloud + Netflix Ribbon 有一个 30 秒延迟

DynamicServerListLoadBalancer
非 Eureka 实现 - com.netflix.loadbalancer.PollingServerListUpdater
Eureka 实现 - com.netflix.niws.loadbalancer.EurekaNotificationServerListUp dater

Spring Cloud 服务调用

  • 服务发现 - DiscoveryClient(Eureka、ZK、Consul、Nacos 等)
  • 负载均衡 - Netflix Ribbon(唯一选择)
  • Feign (唯一选择)

Spring Cloud Open Feign 实现细节

@EnableFeignClients

实现策略:Enable 模块驱动

具体实现:org.springframework.cloud.openfeign.FeignClientsRegistrar

主要工作:

  • 注册默认配置
  • 注册所有标注 @FeignClient 配置类
注册默认配置

源码位置:
org.springframework.cloud.openfeign.FeignClientsRegistrar#regist erDefaultConfiguration

注册所有标注 @FeignClient 配置类

源码位置:
org.springframework.cloud.openfeign.FeignClientsRegistrar#regist erFeignClients

通过 ClassPathScanningCandidateComponentProvider 扫描指定 的 basePackages 集合中的类是否标注 @FeignClient,如果有的 话,作为 AnnotatedBeanDefinition 返回,其中包含 @FeignClient 属性元数据,来自于 AnnotationMetadata,再重新 注册 FeignClientFactoryBean 的 BeanDefinition

@EnableFeignClient -> @Feignclient 元信息 -> 标注接口定义的 FeignClientFactoryBean -> 形成被标注接口的代理对象

Spring Cloud Open Feign 大致流程:

  1. Spring Web MVC 注解元信息解析
    • Contract Feign 内建实现
      • @RequestLine
      • @Headers
    • JAX-RS 1/2 注解
      • @Path
      • @PathParam
      • @HeaderParam
    • Spring Web MVC ( Spring Cloud Open Feign 扩展)
  2. 通过 @FeignClient 所生成代理对象的方法调用实现 HTTP 调用
  3. 通过 SpringDecoder 实现 Response 与接口返回类型的反序列化
  4. 负载均衡
    • Spring Cloud 替换了 Client 实现 - LoadBalancerFeignClient
  5. 重试重试
    • Spring Cloud 在外部包装 Feign 接口
  6. 熔断 feign.hystrix.HystrixFeign

Spring Boot Actuator

JMX

Web Endpint

Enable 模块驱动
  • org.springframework.context.annotation.ImportBeanDefinitionRegistrar
    • @EnableFeignClients
  • org.springframework.context.annotation.ImportSelector
    • @EnableAsync
  • @Configuration 类
    • @EnableWebMvc

Bean 注入的实现(DI 过程)

  • 普通 Bean
    • 编码 BeanDefintion 生成的
    • XML 配置的
    • 注解标注的
    • 直接注册的
    • FactoryBean 生成的
FactoryBean 是如何当做一个 Bean 被注入?
  • 返回 Bean 类型
    • getObjectType()
  • 返回 Bean 对象
    • getObject()
BeanFactory 依赖查找
  • 通过名称查找
    • getBean(String)
  • 通过类型查找
    • getBean(Class)
      • 直接查找 BeanDefinition#getBeanClassName() : String
      • 间接查找 BeanFactory#getObjectType
  • 通过名称 + 类型查找
    • getBean(String,Class)
  • 通过注解查找
    • getBeansWithAnnotation(Annotation)

Spring Cloud 整合

  • 整合负载均衡:Netflix Ribbon
  • 整合服务短路路:Netflix Hystrix
  • 整合服务发现:Netflix Eureka
  • 整合配置服务器器:Config Server
  • 整合配置客户端:Config Client

Spring Cloud Netflix Hystrix

  • Netflix Hystrix

    • Hystrix: Latency and Fault Tolerance for Distributed Systems
    • https://github.com/Netflix/Hystrix
    • Maven 依赖
      • com.netflix.hystrix:hystrix-core
  • Netflix Hystrix

    • 整合 Spring
      • 激活:@EnableHystrix
      • 编程模型
      • 注解⽅方式:@HystrixCommand
      • 编程⽅方式:HystrixComman
问题:设置server.port=0(表示随机端口)
  • Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder ‘local.server.port’ in value “${local.server.port}”
    import org.springframework.core.env.Environment;

	@Autowired
    private Environment environment;
    
    String getPort() {
        return environment.getProperty("local.server.port");
    }	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值