Spring cloud Feign(服务调用) Netflix

原博客:https://www.cnblogs.com/knowledgesea/p/11208013.html

序言

Spring Cloud Netflix的微服务都是以HTTP接口的形式暴露的,所以可以用Apache的HttpClient或Spring的RestTemplate去调用

Feign是一个使用起来更加方便的HTTP客户端,它用起來就好像调用本地方法一样,完全感觉不到是调用的远程方法

Feign是一个声明式的Web Service客户端,它的目的就是让Web Service调用更加简单。Feign提供了HTTP请求的模板,通过编写简单的接口和插入注解,就可以定义好HTTP请求的参数、格式、地址等信息。

Feign会完全代理HTTP请求,我们只需要像调用方法一样调用它就可以完成服务请求及相关处理。

Feign整合了Ribbon和Hystrix(关于Hystrix我们后面再讲),可以让我们不再需要显式地使用这两个组件。

总起来说,Feign具有如下特性:

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

https://github.com/Netflix/feign

微服务提供方注册服务到Eureka实例代码

pom.xml

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
 <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>       
        </dependencies>
    </dependencyManagement>

资源配置文件

## server
server.port=8082

##eureka
eureka.client.serviceUrl.defaultZone=http://localhost:8081/eureka/
eureka.instance.instance-id=${spring.application.name}:${server.port}
# 设置微服务调用地址为IP优先(缺省为false)
eureka.instance.prefer-ip-address=true
# 心跳时间,即服务续约间隔时间(缺省为30s)
eureka.instance.lease-renewal-interval-in-seconds=30
# 发呆时间,即服务续约到期时间(缺省为90s)
eureka.instance.lease-expiration-duration-in-seconds=9

起始文件

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

接口controller,可以没有facade层的接口,这里是为拉给java其他客户端调用设计的。

//controller层
@RestController
@RequestMapping(value = "/Promotion",method = RequestMethod.GET) public class PromotionController implements PromotionFacade {
    @Override
    @RequestMapping(value = "/delete") public String releasePromotion(@RequestParam int orderID){ return orderID+"-- hello!";
    }
} //facade层
public interface PromotionFacade { /** * 释放门店优惠券 */ String releasePromotion(@RequestParam int orderID);
}

好啦,这个启动起来之后,就注册到啦eureka中啦,等待被调用吧。

image

Feign调用简单示例

pom.xml

<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>
<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>       
        </dependencies>
    </dependencyManagement>

资源配置文件

## server
server.port=8083
##eureka
eureka.instance.instance-id=${spring.application.name}:${server.port}
eureka.client.serviceUrl.defaultZone=http://localhost:8081/eureka/
#租期更新时间间隔(3)
eureka.instance.leaseRenewalIntervalInSeconds=30
#租期到期时间(默认90秒)
eureka.instance.leaseExpirationDurationInSeconds=90

起始文件

@SpringBootApplication
@EnableFeignClients(basePackages = { "trade.order.remote" })
@EnableEurekaClient public class StartMain { public static void main(String[] args) {
        SpringApplication.run(StartMain.class, args);
    }
}

调用类

//remote层
@FeignClient(name = "trade-promotion") public interface PromotionClient {
     @RequestMapping(value = "/Promotion/delete",method = RequestMethod.GET)
     String  releasePromotion(@RequestParam int orderID) ;
} //controller 层
@RestController
@RequestMapping(value = "/promotion", method = RequestMethod.GET) public class PromotionController {
    @Autowired
    PromotionClient promotionClient;

    @RequestMapping(value = "/delete") public String delete(@RequestParam int orderID) { return promotionClient.releasePromotion(orderID);
    }
}

note:

1.上述调用只又remote就可以啦。

2.注意路由地址大小写规范,不要以为自己很牛逼,一会大一会小,要我说,你很挫,一直小就可以啦。。

Feign 工作原理

  • 在开发微服务应用时,我们会在主程序入口添加 @EnableFeignClients 注解开启对 Feign Client 扫描加载处理。根据 Feign Client 的开发规范,定义接口并加 @FeignClients 注解。
  • 当程序启动时,会进行包扫描,扫描所有 @FeignClients 的注解的类,并将这些信息注入 Spring IOC 容器中。当定义的 Feign 接口中的方法被调用时,通过JDK的代理的方式,来生成具体的 RequestTemplate。当生成代理时,Feign 会为每个接口方法创建一个 RequetTemplate 对象,该对象封装了 HTTP 请求需要的全部信息,如请求参数名、请求方法等信息都是在这个过程中确定的。
  • 然后由 RequestTemplate 生成 Request,然后把 Request 交给 Client 去处理,这里指的 Client 可以是 JDK 原生的 URLConnection、Apache 的 Http Client 也可以是 Okhttp。最后 Client 被封装到 LoadBalanceclient 类,这个类结合 Ribbon 负载均衡发起服务之间的调用。

@FeignClient 注解

  • name:指定 Feign Client 的名称,如果项目使用了 Eureka,name 属性会作为微服务的名称,用于服务发现。
  • url:url 一般用于调试,可以手动指定 @FeignClient 调用的地址。
  • decode404:当发生404错误时,如果该字段为 true,会调用 decoder 进行解码,否则抛出 FeignException。
  • configuration:Feign 配置类,可以自定义 Feign 的 Encoder、Decoder、LogLevel、Contract。
  • fallback:定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback 指定的类必须实现 @FeignClient 标记的接口。
  • fallbackFactory:工厂类,用于生成 fallback 类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码。
  • path:定义当前 FeignClient 的统一前缀。

Feign参数绑定

@PathVariable

   /** * 在服务提供者我们有一个方法是用直接写在链接,SpringMVC中用的@PathVariable
     * 这里边和SpringMVC中有些有一点点出入,SpringMVC中只有一个参数而且参数名的话是不用额外指定参数名的,而feign中必须指定 */ @RequestMapping(value = "/greet/{dd}",method = RequestMethod.GET)
    String greetFeign(@PathVariable("dd") String dd);

@RequestParam

    /** * 这里说下@RequestParam 注解和SpringMVC中差别也是不大,我认为区别在于Feign中的是参数进入URL或请求体中,
     * 而SpringMVC中是参数从请求体中到方法中
     * @param ids id串,比如“1,2,3”
     * @return
     */ @RequestMapping(value = "/users",method = RequestMethod.GET) public List<User> getUsersByIds(@RequestParam("ids") List<Long> ids);

@RequestHeader

 /** * 这里是将参数添加到Headers中
     * @param name 参数 */ @RequestMapping(value = "/headers")
    String getParamByHeaders(@RequestHeader("name") String name);

@RequestBody

 /** * 调用服务提供者的post方法,接收回来再被服务提供者丢回来
     * @param user User对象 */ @RequestMapping(value = "/user", method = RequestMethod.POST)
    User getUserByRequestBody(@RequestBody User user);

Feign压缩与日志

1.请求压缩(Feign request/response compression)

##这两行即可开启压缩
feign.compression.request.enabled=true
feign.compression.response.enabled=true
## 配置压缩具体信息
feign.compression.request.enabled=true
feign.compression.request.mime-types=text/xml,application/xml,application/json
feign.compression.request.min-request-size=2048

2. Feign日志(Feign logging)

Feign对日志的处理非常灵活,可为每个Feign客户端指定日志记录策略,每个Feign客户端都会创建一个logger。默认情况下,logger的名称是Feigh接口的完整类名。需要注意的是,Feign的日志打印只会对Debug级别做出响应。

我们可以为每个Feign客户端配置各种的Logger.Level对象,告诉Feign记录哪些日志。Logger.Level的值有以下选择。

  • NONE,无记录(DEFAULT)。
  • BASIC,只记录请求方法和URL以及响应状态代码和执行时间。
  • HEADERS,记录基本信息以及请求和响应标头。
  • FULL,记录请求和响应的头文件,正文和元数据。

开启记录

logging.level.com.cnblogs.hellxz.client.EurekaServiceFeign: DEBUG
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343