栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Feign 微服务调用 (nacos 作为注册中心)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Feign 微服务调用 (nacos 作为注册中心)

Feign 微服务调用 (nacos 作为注册中心)

Feign 是 spring Cloud Netflix 组件中的一量级 Restful的HTTP 服务客户端,实现了负载均衡和 Rest 调用的开源框架,封装了Ribbon和RestTemplate,实现WebService的面向接口编程。

Feign 简化了RestTemplate代码,是声明式服务调用组件:核心就是像调用本地方法一样调用远程方法。让开发者无需关注,远程调用过程,和交互细节。

Feign 本身并不支持spring MVC注解,它有一套自己的注解,为了更方便使用Spring Cloud孵化OpenFeign。并且支持spring mvc的注解,例如:@RequestMapping、@PathVariable。

openFeign 的@FeignClient可以解析Spring MVC的@RequestMapping注解下的接口,并通过动态代理方式产生实现类,实现类中做负载均衡调用服务。

soringboot 2.0 以后基本使用 OpenFeign

官网

特性

  • Hystrix 和它的 Fallback
  • HTTP 请求响应的压缩
  • Ribbon 负载均衡客户端
  • 可拔插的HTTP编码器和解码器
  • 拔插的注解支持,包括Feign 注解 和JAX-RS 注解

文章目录
  • Feign 微服务调用 (nacos 作为注册中心)
    • 快速开始
    • 项目
      • pom 文件
      • goods
      • order
      • 测试
    • @FeignClient ‼️
    • Feign 日志开启
    • HTTP Client 替换
      • 修改
      • 如果使用 okhttp 的可以自定义配置
    • 参数传递
      • 特殊需求,Get方法传递了多参数
    • 实现Token 传递
  • 底部

快速开始

项目预览

项目 pom 文件

父项目

    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.3.RELEASE
         
    
    
    
    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            com.alibaba.cloud
            spring-cloud-alibaba-nacos-discovery
            2.0.1.RELEASE
        
    

    
    
        
            
                org.springframework.cloud
                spring-cloud-dependencies
                Finchley.RELEASE
                pom
                import
            
        
    

    
    
        
            spring-milestones
            Spring Milestones
            https://repo.spring.io/libs-milestone
            
                false
            
        
    

goods 消费者

    
        springcloud-openfeig
        org.example
        1.0-SNAPSHOT
    
    4.0.0

    openfeig-goods
    商品服务

    
        8
        8
    

order 生产者

    
        springcloud-openfeig
        org.example
        1.0-SNAPSHOT
    
    4.0.0

    openfeig-order

    
        8
        8
    

    

        
            org.springframework.cloud
            spring-cloud-starter-openfeign
        
    
goods
server:
  port: 8081
spring:
  application:
    name: openfeig-goods
  cloud:
    nacos:
      server-addr: ...:8848
@RestController
public class GoodsController {

    @GetMapping("hello/{message}")
    public String hello(@PathVariable String message){
        return "来自goods的消息 =="+ message;
    }
}
order
server:
  port: 8080
spring:
  application:
    name: openfeig-order
  cloud:
    nacos:
      server-addr: ....:8848
@SpringBootApplication
//开启远程调用的注解 扫描,可以扫描 @FeignClient
@EnableFeignClients
public class OpenFeigOrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OpenFeigOrderApplication.class,args);
    }
}
// 准备远程调用的接口
@FeignClient(name = "openfeig-goods")
public interface  GoodsClienService {

    @GetMapping("hello/{message}")
    String hello(@PathVariable String message);
}
//提供对外暴露的 api
@RestController
public class OrderController  {

    //nacos 客户端信息
    @Autowired
    private LoadBalancerClient loadBalancerClient;

    //调用的 service
    @Autowired
    private GoodsClienService cartService;

    @GetMapping("add/{message}")
    public String add(@PathVariable String message){
        ServiceInstance choose = loadBalancerClient.choose("openfeig-goods");
        return cartService.hello(message) +"  "+ choose.getHost() + "--" + choose.getPort();
    }
}
测试

@FeignClient ‼️

需要 @EnableFeignClients来开启扫描

当定义的Feign接口中的方法被调用时,通过JDK的代理方式,生成具体的 RequestTemplate。这个对象中,封装了http需要的全部信息。参数、方法名等等

属性说明
name指定FeignClient等名称,如果项目使用了Ribbon,那么name属性会作为微服务等名称,用于服务发现
url一般用于调试,可以手动指定@FeignClient调用的服务地址
decode404当发生404错误时,如果该字段值为true,会调用decoder进行编码,否则抛出FeignException
configurationFeign 配置列,可以自定义Feign 的 Encoder、Decoder、LogLevel、Contract
也可以在配置文件中配置
fallback定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现 @FeignClient标记的接口
fallbackFactory工厂类,用于生成fallback类实例,通过这个属性可以实现每个接口通用的容错逻辑,减少重复的代码
path定义当前FeignClient 的统一前缀
Feign 日志开启

需要在配置文件中 logback.xml 把日志级别改为debug

# open feign 日志设置
logging:
  level:
    com.springcloud.study.service.ProviderClientService: debug
//全局的配置 日志配置类
@Configuration
public class FeignServiceConfig {

    
    @Bean
    Logger.Level feignLogger(){
        return Logger.Level.FULL;
    }
}
//指定单独的配置 MyFeignConfig 是一个 日志的配置类
@FeignClient(configurtion = MyFeignConfig.class)
HTTP Client 替换

Feign 默认使用的是JDK原生的 URLConnection发送HTTP请求,没有用链接池。对每个地址都会建立一个长链接。

feign 的HTTP客户端支持3中框架HttpURLConnection、HttpClient、OkHttp

默认是 HttpURLConnection

修改


    io.github.openfeign
    feign-httpclient





    io.github.openfeign
    feign-okhttp

feign:
  httpclient:
    # 开启httpclient
    enabled: true

如果使用 okhttp 的可以自定义配置

okHttp 优势

  1. 支持SPDY,合并多个请求到同一个主机
  2. 使用链接池
  3. 使用GZIP压缩减少传输数据体积
  4. 缓存响应结果,减少重复请求
@Configuration
@ConditionalOnClass(Feign.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
public class FeignOkHttpConfig {

    @Bean
    public okhttp3.OkHttpClient okHttpClient() {
        return new OkHttpClient.Builder()
                .connectTimeout(60, TimeUnit.SECONDS) //链接超时时间
                .readTimeout(60,TimeUnit.SECONDS)     //读超时
                .writeTimeout(60,TimeUnit.SECONDS)     //写超时
                .retryOnConnectionFailure(true)                 //自动重试
                .connectionPool(new ConnectionPool())           //创建链接池 okhttp包的
                .build();
    }
}
参数传递

get 方式,@PathVariable、@RequestParm注解来接收

post 方式 ,@RequestBody接收请求参数

特殊需求,Get方法传递了多参数

需要时实现Feign 的RequestInterceptor中的pally进行统一处理

TODO 还是用 post 方法发送省事

实现Token 传递

认证鉴权的时候,使用JWT,或spring security 都需要拿到token

RequestInterceptor 拦截器,在feign 调用的时候,向请求头里添加需要传递的token

基于上面的代码改动 注意token 大小写的问题

//生产端
@Component
public class FeignTokenAddInterceptor  implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate requestTemplate) {
        if(null==getHttpServletRequest()){
            //此处省略日志记录
            return;
        }
        //将获取Token对应的值往下面传
        requestTemplate.header("oauthToken", getHeaders(getHttpServletRequest()).get("oauthtoken"));
    }

    private HttpServletRequest getHttpServletRequest() {
        try {
            return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        } catch (Exception e) {
            return null;
        }
    }

    
    private Map getHeaders(HttpServletRequest request) {
        Map map = new LinkedHashMap<>();
        Enumeration enumeration = request.getHeaderNames();
        while (enumeration.hasMoreElements()) {
            String key = enumeration.nextElement();
            String value = request.getHeader(key);
            map.put(key, value);
        }

        System.out.println("模拟token " +  map.get("oauthtoken"));

        return map;
    }
}

    @GetMapping("hello/{message}")
    public String hello(@PathVariable("message") String message, HttpServletRequest req){

        String oauthToken = req.getHeader("oauthToken");
        System.out.println( "token =" + oauthToken);

        return "来自goods的消息 =="+ message + oauthToken;
    }

底部
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/867867.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号