服务调用---------Ribbon和Feign

目录​​​​​​​

1、Ribbon

[1.1 Ribbon简介](#1.1 Ribbon简介)

[1.2 Ribbon负载均衡](#1.2 Ribbon负载均衡)

负载均衡原理

负载均衡策略

Ribbon和Nginx的区别

[1.3 服务调用和Ribbon负载均衡实现](#1.3 服务调用和Ribbon负载均衡实现)

2、Feign&openFeign

3、Feign支持的配置

日志功能

连接池

feign-api远程包


1、Ribbon

1.1 Ribbon简介

Ribbon是一个用于客户端负载均衡的组件,它是Netflix开源的一个项目。在微服务架构中,系统会拆分为多个小型的服务,每个服务都有自己独立的服务器实例。Ribbon所具有的特点:客户端负载均衡,将请求发送到多个服务实例中的一个。多种负载均衡算法:Ribbon支持多种负载均衡算法,如轮询、随机、权重等,可以根据应用的需求选择适合的算法。服务实例自动发现:Ribbon可以与服务注册中心集成,自动发现可用的服务实例。容错和重试机制:如果某个服务实例不可用,Ribbon会自动选择另一个可用的实例进行请求,提高系统的容错能力。

1.2 Ribbon负载均衡

负载均衡原理

服务提供者order-service通过发起请求localhost:8080/order/101远程调用http://user-service/user/1分别轮询转发到服务消费者user-service和user-service1。

复制代码
//继承客户端请求的负载均衡拦截器
LoadBalancerInterceptor implements ClientHttpRequestInterceptor

@Override
	public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
			final ClientHttpRequestExecution execution) throws IOException {
		final URI originalUri = request.getURI();  //服务的路径
		String serviceName = originalUri.getHost();  // 不同路径的服务名
		Assert.state(serviceName != null,
				"Request URI does not contain a valid hostname: " + originalUri);
		return this.loadBalancer.execute(serviceName,   // 处理不同服务执行路径
				this.requestFactory.createRequest(request, body, execution));
	}

//从服务列表中选择一个去执行
public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint)
			throws IOException {
		ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
		Server server = getServer(loadBalancer, hint);
		if (server == null) {
			throw new IllegalStateException("No instances available for " + serviceId);
		}
		RibbonServer ribbonServer = new RibbonServer(serviceId, server,
				isSecure(server, serviceId),
				serverIntrospector(serviceId).getMetadata(server));

		return execute(serviceId, ribbonServer, request);
	}

负载均衡策略

|---------------------------|----------|-------------------------------------------|
| 实现类 | 名称 | 解释 |
| RoundRobinRule | 轮询策略 | 按照轮询的方式选择可用的服务实例,依次轮流分发请求。 |
| RandomRule | 随机策略 | 随机选择可用的服务实例来处理请求。 |
| WeightedResponseTimeRule | 加权响应时间策略 | 根据每个服务实例的响应时间和权重,来计算一个权重值,选择权重值较小的实例处理请求。 |
| RetryRule | 重试策略 | 在选择可用的服务实例时,会在一定次数内进行重试,以提高容错能力。 |
| BestAvailableRule | 最低并发策略 | 会先过滤出并发连接数量最低的服务实例,然后从中选择一个处理请求。 |
| AvailabilityFilteringRule | 可用性过滤策略 | 首先排除因故障而被标记为不可用的服务实例,然后按照轮询的方式选择可用的服务实例。 |
| ZoneAvoidanceRule | 区域感知策略 | Ribbon会根据服务实例所在的区域以及区域的可用性来选择服务实例。 |

Ribbon和Nginx的区别

架构上:Ribbon是一个客户端负载均衡组件,它通常与服务调用客户端集成在一起,通过轮询、随机等算法选择可用的服务实例。而Nginx是一个独立的反向代理服务器,用于将客户端请求转发给后端服务器。

协议上:Ribbon主要用于HTTP、TCP等通信协议的负载均衡,适用于微服务架构中的服务调用。而Nginx支持更多的协议,如HTTP、HTTPS、SMTP、POP3等,可以用于多场景的负载均衡和反向代理。

功能上:Ribbon提供了更灵活的负载均衡策略、重试机制、服务健康检查等功能,且可以与Spring Cloud等技术栈集成,方便在微服务架构中使用。而Nginx不仅具有负载均衡和反向代理的功能,还支持缓存、gzip压缩、SSL/TLS加密等高级特性。

部署管理上:Ribbon通常作为客户端的一部分集成在应用程序中,可以在应用中灵活配置和管理,适合分布式部署。而Nginx是独立的服务器软件,需要单独部署和配置,可以集中管理多个应用的负载均衡配置。

1.3 服务调用和Ribbon负载均衡实现

Ribbon依赖于spring-cloud-starter-netflix-eureka-client包

  • 自定义创建远程调用对象
java 复制代码
/**
     * 远程调用和负载均衡
     * @return
     */
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

controller发出的请求完成调用并进行负载均衡默认的轮询负载均衡

java 复制代码
//远程调用
User user = restTemplate.getForObject("http://user-service/user/" + order.getUserId(), User.class);

自定义负载均衡策略对象

java 复制代码
/**
     * 自定义负载均衡策略
     */
    @Bean
    public IRule randomRule(){
        return new RandomRule();
    }

application.yml配置负载均衡策略

XML 复制代码
user-service:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则
ribbon:
  eager-load:
    enabled: true
    clients: userservice  # 饥饿加载

以上是Ribbon完成的负载均衡调用远程微服务。

2、Feign&openFeign

Feign是一个受Retrofit、JAXRS-2.0和WebSocket启发的Java到HTTP客户端绑定。是声明式客户端,通过发送Rest接口进行请求。为了维护请求参数,让编程规范更统一使代码更有可读性。

官网

  • pom.xml

    复制代码
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-openfeign</artifactId>
          </dependency>
  • 主启动类OrderApplication

加上@EnableFeignClients开启了远程调用。

java 复制代码
@EnableFeignClients
@MapperScan("com.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
  • 自定义Feign客户端接口

    @FeignClient("userservice")
    public interface UserClient {

    复制代码
      @GetMapping("/user/{id}")
      User findById(@PathVariable("id") Long id);

    }

controller接口注入UserClient接口并使用Feign发出http的Get请求查询用户。

java 复制代码
@GetMapping("{orderId}")
    public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {
        // 根据id查询订单并返回
        Order order = orderService.queryOrderById(orderId);

        //远程调用
//        User user = restTemplate.getForObject("http://user-service/user/" + order.getUserId(), User.class);

        //使用Feign发起http请求,查询用户
        User user = userClient.findById(order.getUserId());

        order.setUser(user);
        return order;
    }

这样代码优雅的可读性,成功调用并实现负载均衡~

3、Feign支持的配置

日志功能

日志级别:

BASIC:仅记录请求的方法,URL以及响应状态码和执行时间。

FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。

HEADERS:记录请求的方法,URL以及响应状态码和执行时间,额外记录了请求和响应的头信息。

NONE:默认值,不记录任何日志信息。

自定义config/DefaultFeignConfiguration日志级别的配置类

java 复制代码
@Configuration
public class DefaultFeignConfiguration {

    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.FULL;   //日志级别
    }

}

局部定义在远程接口上:

java 复制代码
@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration.class)

全局定义主启动类上:

java 复制代码
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class)

application.yml

java 复制代码
feign:
  client:
    config: default # 某个微服务userservice设置的日志, default全局日志
      loggerLevel: FULL # 日志级别

后台打印日志级别FULL效果:

连接池

  • pom.xml
java 复制代码
<!-- httpclient -->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>
  • application.yml
java 复制代码
feign:
  httpclient:  # 连接池
    enabled: true # 开启feign对HttpClient的支持
    max-connections: 200 # 最大的连接数,默认200
    max-connections-per-route: 50  # 每个路径的最大连接数, 默认 50

feign底层通过httpClient进行负载均衡的过程:

feign-api远程包

  • 新建feign-api模块
  • pom.xml
java 复制代码
<!-- openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

指定feign扫描服务包

java 复制代码
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class, basePackages = "com.itcast.feign.client")

指定feign加载client服务接口

java 复制代码
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class, clients = {UserClient.class})
相关推荐
深入技术了解原理13 小时前
eureka-client依赖爆红无法下载
spring cloud·云原生·eureka
ZePingPingZe13 小时前
深入理解网络模型之Spring Cloud微服务通信、Socket、HTTP与RPC
网络协议·spring cloud·rpc·dubbo
叫码农就行14 小时前
spring cloud 笔记
java·笔记·spring cloud
七夜zippoe14 小时前
微服务架构演进实战 从单体到微服务的拆分原则与DDD入门
java·spring cloud·微服务·架构·ddd·绞杀者策略
Leo July1 天前
【Java】Spring Cloud 微服务生态全解析与企业级架构实战
java·spring cloud
李慕婉学姐1 天前
【开题答辩过程】以《基于springcloud的空气质量监控管理系统》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
后端·spring·spring cloud
CV_J2 天前
安装kibana
java·elasticsearch·spring cloud·docker·容器
小马爱打代码3 天前
实时搜索:SpringCloud + Elasticsearch + Redis + Kafka
redis·elasticsearch·spring cloud
努力也学不会java3 天前
【Spring Cloud】环境和工程基本搭建
java·人工智能·后端·spring·spring cloud·容器
爱吃山竹的大肚肚3 天前
达梦(DM)数据库中设置表空间
java·数据库·sql·mysql·spring·spring cloud·oracle