spring cloud alibaba -远程调用(openFeign)

spring cloud alibaba -远程调用(openFeign)

使用feignClient远程调用案例

/mvc注解的两套使用逻辑

  • 放在controller上 是接受这样的请求
  • 放在FeignClient上 是发送这样的请求`
package com.nie.order;

import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.cloud.nacos.annotation.NacosConfig;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

@EnableFeignClients//开启Feign远程调用功能
@SpringBootApplication
@EnableDiscoveryClient
public class OrderMainApplication {

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

    }

    @Bean
    ApplicationRunner applicationRunner(NacosConfigManager nacosConfigManager) {
        return args -> {
            ConfigService configService = nacosConfigManager.getConfigService();
            configService.addListener("service-order.properties",
                    "DEFAULT_GROUP", new Listener() {
                        @Override
                        public Executor getExecutor() {
                            return Executors.newFixedThreadPool(4);
                        }

                        @Override
                        public void receiveConfigInfo(String configInfo) {
                            System.out.println("变化的配置信息: " + configInfo);
                            //模拟一下
                            System.out.println("进行邮件通知");
                        }
                    });
            System.out.println("=======");
        };
    }

}

package com.nie.order.feign;

import com.nie.product.bean.Product;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;

@FeignClient(value = "service-product") //feign客户端
public interface ProductFeignClient {


    //mvc注解的两套使用逻辑
    //放在controller上  是接受这样的请求
    //放在FeignClient上  是发送这样的请求
    @GetMapping("/product/{id}")
    Product getPoductFeign(@PathVariable("id") Long id);


}


package com.nie.order.service.Impl;

import com.nie.order.bean.Order;
import com.nie.order.feign.ProductFeignClient;
import com.nie.order.service.OrderService;
import com.nie.product.bean.Product;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;

@Slf4j
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @Autowired
    private ProductFeignClient productFeignClient;

    public Order createOrder(Long productId , Long userId) {
        Product product= productFeignClient.getPoductFeign(productId);

        Order order = new Order();
        order.setId(1L);
        //TODO 总金额
        order.setTotalAmount(product.getPrice().multiply(new BigDecimal(product.getNum())));
        order.setUserId(userId);
        order.setNickName("zhangsan");
        order.setAddress("小聂");
        //TODO 远程查询商品列表
        order.setProductList(Arrays.asList(product));

        return order;
    }

    private Product getProduct(Long productId) {
        List<ServiceInstance> instances = discoveryClient.getInstances("service-product");
        ServiceInstance serviceInstance = instances.get(0);
        String url="http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/product/"+productId;

        Product product = restTemplate.getForObject(url, Product.class);
        return product;
    }

    private Product getProduct1(Long productId) {
        String url="http://service-product/product/"+productId;
        Product product = restTemplate.getForObject(url, Product.class);
        return product;
    }
}

运行结果为:在这里插入图片描述
说明他是调用成功的
注意 使用FeignClient是负载均衡的

日志

如果我们要查看远程调用的日志的话我们只需要做两步

第一:写入日志级别

logging:
  level:
    com.nie.order.feign: debug

第二:

@Configuration
public class OrderConfig {

    @Bean
    Logger.Level feignLogLevel(){
        return Logger.Level.FULL;
 		}
    }

这样就可以了 日志输出了get方式的 请求路径
在这里插入图片描述

超时控制

default为默认设置 如果自己没设置则采用默认设置

spring:
  cloud:
    openfeign:
      client:
        config:
          default:
            logger-level: full
            connect-timeout: 3000
            read-timeout: 5000
          service-product:
            logger-level: full
            connect-timeout: 3000
            read-timeout: 5000

重试机制

远程调用超时失败后,还可以进行多次尝试,如果某次成功返回ok,如果多次依然失败则结束调用,返回错误

如果不传参数 采用默认的


@Configuration
public class OrderConfig {

    @Bean
    Retryer retryer(){
        return new Retryer.Default();
    	}
   }

拦截器

package com.nie.order.inertceptor;


import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.stereotype.Component;

import java.util.UUID;

@Component
public class XTokenRequestInterceptor implements RequestInterceptor {

    /**
     * 请求拦截器
     * @param requestTemplate
     */
    @Override
    public void apply(RequestTemplate requestTemplate) {
        System.out.println("XTokenRequestInterceptor .....................");
        requestTemplate.header("X-Token", UUID.randomUUID().toString());

    }
}

当请求后会拦截 生成一个X-Token
在这里插入图片描述

兜底返回(Fallback)

兜底返回的目的是在远程调用失败时 能拿到一个数据 (可能是假数据) 让业务接着运行

package com.nie.order.feign;

import com.nie.order.feign.fallback.ProductFeignClientFallback;
import com.nie.product.bean.Product;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;

@FeignClient(value = "service-product",fallback = ProductFeignClientFallback.class ) //feign客户端
public interface ProductFeignClient {


    //mvc注解的两套使用逻辑
    //放在controller上  是接受这样的请求
    //放在FeignClient上  是发送这样的请求
    @GetMapping("/product/{id}")
    Product getPoductFeign(@PathVariable("id") Long id);



}

package com.nie.order.feign.fallback;

import com.nie.order.feign.ProductFeignClient;
import com.nie.product.bean.Product;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;


@Component
public class ProductFeignClientFallback implements ProductFeignClient {


    @Override
    public Product getPoductFeign(Long id) {
        System.out.println("兜底回调.......");
        Product product = new Product();
        product.setId(id);
        product.setNum(1);
        product.setProductName("苹果");
        product.setPrice(new BigDecimal(3));
        return product;
    }
}

导入sentinel依赖

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
feign:
  sentinel:
    enabled: true

如果远程调用访问错误的时候 那么他会传入我自己构造的Product对象的数据
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值