(四)springcloud 生产消费-Spring Cloud OpenFeign

相对概念,生产者:被调用方;消费者:调用方

服务生产:

依赖:

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>

配置:

server:
  port: 2000
spring:
  application:
    name: provider-server
  profiles:
    active: dev
  cloud:
    config:
      label: master
      profile: ${spring.profiles.active}
      discovery:
        service-id: config-server
        enabled: true
        
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka/

启动类:

/**
 * 不用再声明开启注册中心,自动配置了
 */
@SpringBootApplication
public class ProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}

服务:

@RestController
@RequestMapping("/api/v1/provider")
public class ProviderController {

    @Value("${server.port}")
    private String port;

    @GetMapping("/port")
    public String port() {
        return port;
    }
  
}

服务消费(Ribbon):

依赖:

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>

配置:

server:
  port: 3000
spring:
  application:
    name: consumer-server-ribbon
  profiles:
    active: dev
  cloud:
    config:
      label: master
      profile: ${spring.profiles.active}
      discovery:
        service-id: config-server
        enabled: true

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka/

启动类:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

@SpringBootApplication
public class ConsumerRibbonApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerRibbonApplication.class, args);
    }

    // 加载Ribbon,应用负载均衡
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    @RestController
    @RequestMapping("/api/v1/consumer")
    class ProviderController {

        private static final String SERVICE_NAME = "provider-server";
      
        private static final String GET_PORT = "/api/v1/provider/port";

        @Resource
        private RestTemplate restTemplate;

        @GetMapping
        public String consumer() {
            // 调用生产者服务
            ResponseEntity<String> forEntity = restTemplate
              .getForEntity("http://" + SERVICE_NAME + GET_PORT, String.class, (Object) null);
            return forEntity.getBody();
        }
    }

}

验证:

访问消费者:http://localhost:3000/api/v1/consumer

获得响应:2000

Ribbon主要包含如下组件:

IRule:

根据特定算法中从服务列表中选取一个要访问的服务

  • RoundRobinRule:轮询规则,默认规则。同时也是更高级rules的回退策略
  • AvailabilityFilteringRule:优先过滤掉由于多次访问故障而处于断路器跳闸状态,并发的连接数量超过阈值
  • WeightedResponseTimeRule:根据平均响应时间计算所有服务的权重,响应时间越快,服务权重越重、被选中的概率越高
  • RetryRule:先按照RoundRobinRule的策略获取服务,如果获取服务失败,则在指定时间内会进行重试,获取可用的服务
  • BestAvailableRule:此负载均衡器会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
  • RandomRule:随机获取一个服务

IPing:

在后台运行的一个组件,用于检查服务列表是否都可用

  • NIWSDiscoveryPing:不执行真正的ping。如果Discovery Client认为是在线,则程序认为本次心跳成功,服务可用
  • PingUrl:此组件会使用HttpClient调用服务的一个URL,如果调用成功,则认为本次心跳成功,表示此服务活着
  • NoOpPing:永远返回true, 即认为服务永远活着
  • DummyPing:默认实现,默认返回true,即认为服务永远活着

ServerList:

存储服务列表。分为静态和动态。如果是动态的,后台有个线程会定时刷新和过滤服务列表

  • ConfigurationBasedServerList:从配置文件中获取所有服务列表
sample-client.ribbon.listOfServers=www.microsoft.com:80,www.yahoo.com:80,www.google.com:80
  • DiscoveryEnabledNIWSServerList:从服务注册表中获取服务列表。此值必须通过属性中的VipAddress来标识服务器集群。DynamicServerListLoadBalancer会调用此对象动态获取服务列表
  • DomainExtractingServerList:代理类,根据ServerList的值实现具体的逻辑

ServerListFilter:

该接口允许过滤配置或动态获取的具有所需特性的服务器列表。ServerListFilter是DynamicServerListLoadBalancer用于过滤从ServerList实现返回的服务器的组件。

  • ZoneAffinityServerListFilter:过滤掉所有的不和客户端在相同zone的服务,如果和客户端相同的zone不存在,才不过滤不同zone有服务。
<clientName>.ribbon.EnableZoneAffinity=true
  • ZonePreferenceServerListFilter:是比较的zone是发布环境里面的zone。过滤掉所有和客户端环境里的配置的zone的不同的服务,如果和客户端相同的zone不存在,才不进行过滤。
  • ServerListSubsetFilter:此过滤器确保客户端仅看到由ServerList实现返回的整个服务器的固定子集。 它还可以定期用新服务器替代可用性差的子集中的服务器

其他配置:

consumer-server-ribbon:
  ribbon:
    # 请求连接的超时时间
    ConnectTimeout: 250 
    # 请求处理的超时时间
    ReadTimeout: 1000
    # 对所有操作请求都进行重试
    OkToRetryOnAllOperations: true  
    # 切换实例的重试次数
    MaxAutoRetriesNextServer: 2 
    # 对当前实例的重试次数
    MaxAutoRetries: 1 
        # 定义负载均衡规则
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

服务消费(Feign):

依赖:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>

配置:

server:
  port: 3001
spring:
  application:
    name: consumer-server-feign
  profiles:
    active: dev
  cloud:
    config:
      label: master
      profile: ${spring.profiles.active}
      discovery:
        service-id: config-server
        enabled: true

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka/

声明调用生产者的接口:

@FeignClient(name = "provider-server")
@RequestMapping("/api/v1/provider")
public interface ProviderClient {

    @GetMapping("/port")
    String port();

}

启动类:

@EnableFeignClients:开启Feign功能

@SpringBootApplication
@EnableFeignClients
public class ConsumerFeignApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerFeignApplication.class, args);
    }

    @RestController
    @RequestMapping("/api/v1/consumer")
    public class OrderController {

        @Resource
        private ProviderClient providerClient;

        @GetMapping
        public String productInfo() {
            return providerClient.port();
        }
    }

}
# feign 配置
feign:
  hystrix:
    enabled: true
  okhttp:
    enabled: true
  httpclient:
    enabled: false
  client:
    config:
      default:
        connectTimeout: 10000
        readTimeout: 10000
  # 请求和响应GZIP压缩支持
  compression:
    request:
      enabled: true
    response:
      enabled: true

验证:

访问消费者:http://localhost:3000/api/v1/consumer

获得响应:2000

配置:

1、请求响应压缩配置

feign.compression.request.enabled=true
feign.compression.response.enabled=true
# 设置支持的 mime-types
feign.compression.request.mime-types=text/xml,application/xml,application/json
# 选择压缩介质类型和最小请求阈值长度。
feign.compression.request.min-request-size=2048

feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
        loggerLevel: basic
    compression:
        request: 
            enabled: true
            mime-types: text/xml,application/xml,application/json
            min-request-size: 2048
        response:
            enabled: true

日志:

记录器的名称是用于创建Feign客户端的接口的完整类名。Feign日志记录仅响应DEBUG级别。

logging: 
    level:
        project.user.UserClient: DEBUG

Logger.Level配置:

  • NONE,没有记录(DEFAULT)。
  • BASIC,仅记录请求方法和URL以及响应状态代码和执行时间。
  • HEADERS,记录基本信息以及请求和响应标头。
  • FULL,记录请求和响应的标题,正文和元数据。
@Configuration
public class FooConfiguration {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}

@QueryMap:

OpenFeign @QueryMap注释为POJO提供了对用作GET参数映射的支持。不幸的是,默认的OpenFeign QueryMap注释与Spring不兼容,因为它缺少value属性。

Spring Cloud OpenFeign提供等效@SpringQueryMap注释,用于将POJO或Map参数注释为查询参数映射。

@FeignClient("demo")
public class DemoClient {

    @GetMapping(path = "/demo")
    String demoEndpoint(@SpringQueryMap Params params);
}

转载于:https://www.cnblogs.com/zuier/p/10757117.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值