微服务通信之feign的配置隔离
前言
由上文我们知道针对某一个Feign接口,我们可以给他设置特定的配置类。那如果现在有一个服务,我们只想对A服务配置一个拦截器拦截请求而不影响其他服务,那应该怎么做呢?
一、feign接口配置
由前面的文章我们知道了feign的代理过程以及调用过程。现在我们看一下feign都有哪些配置?
- @FeignClient可配置属性列表
| 属性 | 值类型 | 含义 |
|---|---|---|
| value | string | 服务名,无论是否有URL,服务名称都不能为空,它可以设置为属性值${server_name}这种形式 |
| name | string | 同value |
| qualifier | string | 指定feign接口在容器中的bean实例名称(我们知道每一个feign接口最终都会向容器注入一个实例),等同于@Qualifier |
| url | string | 绝对URL或可解析主机名(协议是可选的) |
| decode404 | boolean | 是否应该解码404而不是抛出假异常 |
| fallback | class | 指定一个会退类(比如发生未处理的异常后)。回退类必须实现feign接口,并注册到容器。 |
| fallbackFactory | class | 为指定的外部客户机接口定义回退工厂。回退工厂必须实现FallbackFactory接口,此工厂接口返回一个feign接口对应的回滚类。回退工厂必须注册到容器。 |
| path | string | 指定相对路径 |
| primary | boolean,默认true | 当容器中存在同名的bean的实现,以当前代理对象的bean为主。 |
| configuration | class | 当前feign接口的配置类,他会将配置类注册到当前feign对象的容器中(非应用程序的上下文环境) |
- 配置是何时被加载的
这里直接上核心代码(FeignClientsRegistrar.registerClientConfiguration)
// name @FeignClient的name属性值
// configuration @FeignClient的class对象
private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name,
Object configuration) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition(FeignClientSpecification.class);
builder.addConstructorArgValue(name);
builder.addConstructorArgValue(configuration);
registry.registerBeanDefinition(
name + "." + FeignClientSpecification.class.getSimpleName(),
builder.getBeanDefinition());
}
由上面的代码我们知道,他是将@FeignClient对象的configuration属性对应的配置类作为成员FeignClientSpecification的属性注入到应用上下文。那看到这里我们就会产生一个疑问:configuration对应的配置类到底什么时候被初始化呢?最终发现在为@FeignClient生成代理对象的时候,他初始化了FeignClient对应的配置。如下(NamedContextFactory.createContext):
// 在获取一个@FeignClient接口对应的代理对象前,先为其创建Context对象
protected AnnotationConfigApplicationContext createContext(String name) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
if (this.configurations.containsKey(name)) {
for (Class<?> configuration : this.configurations.get(name)
.getConfiguration()) {
// 注册配置
context.register(configuration);
}
}
for (Map.Entry<String, C> entry : this.configurations.entrySet()) {
if (entry.getKey().startsWith("default.")) {
for (Class<?> configuration : entry.getValue().getConfiguration()) {
// 注册配置
context.register(configuration);
}
}
}
context.register(PropertyPlaceholderAutoConfiguration.class,
this.defaultConfigType);
// 为context注册环境变量
context.getEnvironment().getPropertySources().addFirst(new MapPropertySource(
this.propertySourceName,
Collections.<String, Object>singletonMap(this.propertyName, name)));
if (this.parent != null) {
// Uses Environment from parent as well as beans
context.setParent(this.parent);
// jdk11 issue
// https://github.com/spring-cloud/spring-cloud-netflix/issues/3101
context.setClassLoader(this.parent.getClassLoader());
}
context.setDisplayName(generateDisplayName(name));
context.refresh();
return context;
}
显然,在为@FeignClient接口的代理对象创建了Context后,将配置初始化到了该Context。这里可以明确的是每一个@FeignClient只要name属性不一致,那么他们将拥有不同的上下文。
二、feign调用的沙箱设计思路
在现实中的sandbox,是一种儿童玩具,类如KFC中一个装满小球的容器,儿童可以在随意玩耍,起到保护儿童的作用。(也可以理解为一种安全环境)。同样在网络技术中也是一种按照安全策略限制程序行为的执行环境。在feign的调用过程中,针对不同的服务为其创建一个上下文,我们可以将这个上下文理解为sandbox。执行调用所需要的资源是从各自的沙箱环境中取。整体的职责分工如下图所示。

从中我们可以看到,我们最终调用的执行器来源是来自沙箱,而沙箱的配置可以各不相同,创建不同的Client,这给了我们决定不同的服务怎样去调用高度的自主权。也解决了文章开篇提出的问题。
三、小结
至此,feign调用暂时告一段落。由于后续要花时间做一个开源框架,文章的书写便只能告一段落了。
微服务通信之feign的配置隔离的更多相关文章
- 微服务通信之feign的注册、发现过程
前言 feign 是目前微服务间通信的主流方式,是springCloud中一个非常重要的组件.他涉及到了负载均衡.限流等组件.真正意义上掌握了feign可以说就掌握了微服务. 一.feign的使用 f ...
- 微服务通信之feign集成负载均衡
前言 书接上文,feign接口是如何注册到容器想必已然清楚,现在我们着重关心一个问题,feign调用服务的时候是如何抉择的?上一篇主要是从读源码的角度入手,后续将会逐步从软件构架方面进行剖析. 一.R ...
- 如何将 Redis 用于微服务通信的事件存储
来源:Redislabs作者:Martin Forstner 翻译:Kevin (公众号:中间件小哥) 以我的经验,将某些应用拆分成更小的.松耦合的.可协同工作的独立逻辑业务服务会更易于构建和维护.这 ...
- java架构之路-(微服务专题)feign的基本使用和nacos的配置中心
上次回归: 上次我们说了ribbon的基本使用,包括里面的内部算法,算法的细粒度配置,还有我们自己如何实现我们自己的算法,主要还是一些基本使用的知识,还不会使用ribbon的小伙伴可以回去看一下上一篇 ...
- 【SpringCloud构建微服务系列】Feign的使用详解
一.简介 在微服务中,服务消费者需要请求服务生产者的接口进行消费,可以使用SpringBoot自带的RestTemplate或者HttpClient实现,但是都过于麻烦. 这时,就可以使用Feign了 ...
- 「 从0到1学习微服务SpringCloud 」06 统一配置中心Spring Cloud Config
系列文章(更新ing): 「 从0到1学习微服务SpringCloud 」01 一起来学呀! 「 从0到1学习微服务SpringCloud 」02 Eureka服务注册与发现 「 从0到1学习微服务S ...
- 微服务通信之ribbon实现原理
前言 上一篇我们知道了feign调用实现负载均衡是通过集成ribbon实现的.也较为详细的了解到了集成的过程.现在我们看一下ribbo是如何实现负载均衡的.写到这里我尚未去阅读源代码,我在这里盲猜一下 ...
- SpringCloud微服务(基于Eureka+Feign+Hystrix+Zuul)
一.搭建注册中心 1.1.创建一个cloud-service项目 1.2:POM文件依赖 1 <?xml version="1.0" encoding="UTF-8 ...
- Spring cloud微服务安全实战-6-11sentinel之配置持久化
规则的持久化问题.现在的规则都是在内存里的,我们要写一些代码来编一些规则.启动以后规则在内存里了.如果你配置里面有sentinel的dashboard,有流量经过客户端的时候,它会把规则同步给Dash ...
随机推荐
- ORM查询相关的操作
必知必会13条 import os os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.setti ...
- 【C语言入门学习笔记】如何把C语言程序变成可执行文件!
环境 在ANSI的任何一种实现中,存在两种不同的环境. 翻译环境:在这个环境里,源代码被转换为可执行的机器指令. 执行环境:用于实际执行代码. 翻译环境 组成一个程序的每个源文件通过编译过程分别转成目 ...
- 【UER #1】DZY Loves Graph
UOJ小清新题表 题目内容 UOJ链接 DZY开始有\(n\)个点,现在他对这\(n\)个点进行了\(m\)次操作,对于第\(i\)个操作(从\(1\)开始编号)有可能的三种情况: Add a b: ...
- centos8平台mysql日志的按天切分
一,mysqladmin使用flush-logs的文档: mysql8官网上面针对mysqladmin的文档地址 https://dev.mysql.com/doc/refman/8.0/en/mys ...
- HTML 的属性
HTML 属性赋予元素意义和语境. 下面的全局属性可用于任何 HTML 元 属性 描述 accesskey 规定激活元素的快捷键. class 规定元素的一个或多个类名(引用样式表中的类). cont ...
- 【应用程序见解 Application Insights】在Application Insights中通过自定义查询结果定义指标并显示在Dashboard中
问题情形 通过Application Insights收集到指标数据后,如Request,Trace,Exception.但是默认的Insights图表不能满足业务的需求,需要自定义相应的类SQL语句 ...
- Java安全之Commons Collections2分析
Java安全之Commons Collections2分析 首发:Java安全之Commons Collections2分析 0x00 前言 前面分析了CC1的利用链,但是发现在CC1的利用链中是有版 ...
- update不能直接使用select的返回结果
update不能直接使用select的返回结果,这是会报错的,这是SQL的语法规定的,若想在update中与select结合使用,sql需要这样写: 1.其中field1,field2为表中的字段名 ...
- Redis 入门与 ASP.NET Core 缓存
目录 基础 Redis 库 连接 Redis 能用 redis 干啥 Redis 数据库存储 字符串 订阅发布 RedisValue ASP.NET Core 缓存与分布式缓存 内存中的缓存 ASP. ...
- 一道在输入上有坑点的LCS
原题连接 http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=114&p ...