spring cloud 组件介绍

1. openFeign

为了保持向后兼容性,将用作默认负载平衡器实现。然而,Spring Cloud Netflix Ribbon现在处于维护模式,因此我们建议改用Spring Cloud LoadBalancer。为此,将spring.cloud.looadbalancer.ribbon.enabled的值设置为false。

1.1 覆盖默认配置

​ 默认Spring Cloud使用Spring Cloud使用FeignClientsConfiguration按需为每个命名的客户端创建一个新的集成作为ApplicationContext。这包含(除其他外)一个foreign.Decorder、一个foregn.Encoder和一个feign.Contract。可以使用@FeignClient注释的contextId属性重写该集合的名称按需为每个命名的客户端创建一个新的集成作为ApplicationContext。这包含(除其他外)一个foreign.Decorder、一个foregn.Encoder和一个feign.Contract。可以使用@FeignClient注释的contextId属性重写该集合的名称

覆盖默认配置:

1
2
3
4
@FeignClient(name = "stores", configuration = FooConfiguration.class)
public interface StoreClient {
//..
}

注: FooConfiguration.class 不需要 @Configuration,否者会替换全局默认配置

占位符方式支持 :

1
2
3
4
@FeignClient(name = "${feign.name:chen}", url = "${feign.url}")
public interface StoreClient {
//..
}

spring cloud 默认feign配置:

  • Decoder feignDecoder: ResponseEntityDecoder (which wraps a SpringDecoder)
  • Encoder feignEncoder: SpringEncoder
  • Logger feignLogger: Slf4jLogger
  • Contract feignContract: SpringMvcContract
  • Feign.Builder feignBuilder: HystrixFeign.Builder
  • if Ribbon is in the classpath and is enabled it is a LoadBalancerFeignClient, otherwise if Spring Cloud LoadBalancer is in the classpath, FeignBlockingLoadBalancerClient is used. If none of them is in the classpath, the default feign client is used.

    feign.okhttp.enabled: true 支持okHttp

    feign.httpclient.enabled: true 支持httpClient

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
public class FooConfiguration {
@Bean
public Contract feignContract() {
return new feign.Contract.Default();
}

@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor("user", "password");
}
}

feign.Contract.Default代替FeignClientsConfiguration中的contract 并添加 RequestInterceptorRequestInterceptor集合

也可以用配置文件覆盖:

application.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
feign:
client:
config:
contextId:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: full
errorDecoder: com.example.SimpleErrorDecoder
retryer: com.example.SimpleRetryer
requestInterceptors:
- com.example.FooRequestInterceptor
- com.example.BarRequestInterceptor
decode404: false
encoder: com.example.SimpleEncoder
decoder: com.example.SimpleDecoder
contract: com.example.SimpleContract

contentId:未设置时通name相等

image-20230113173432411

对所有feign生效:

1
2
3
4
5
6
7
feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: basic

默认配置文件优先于@Configuration, 你可以通过feign.client.default-to-properties设置false 改变优先级

另外:如果需要在RequestInterceptor中使用ThreadLocal绑定变量,则需要将Hystrix的线程隔离策略设置为“SEMAPHORE”或在Feign中禁用Hystrix。

1
2
3
4
5
6
7
8
9
10
11
12
# To disable Hystrix in Feign
feign:
hystrix:
enabled: false

# To set thread isolation to SEMAPHORE
hystrix:
command:
default:
execution:
isolation:
strategy: SEMAPHORE

如果我们希望创建多个具有相同名称或url的外部客户端,以便它们指向相同的服务器,但每个客户端具有不同的自定义配置,那么我们必须使用@FeignClient的contextId属性,以避免这些配置bean的名称冲突。

1
2
3
4
5
6
7
8
@FeignClient(contextId = "fooClient", name = "stores", configuration = FooConfiguration.class)
public interface FooClient {
//..
}
@FeignClient(contextId = "barClient", name = "stores", configuration = BarConfiguration.class)
public interface BarClient {
//..
}

Hystrix 存在于类路径上,并且 foreign.Hystrix.enabled=true,支持熔断

所有不支持hystrix : 创建一个原型的Feign.Builder

1
2
3
4
5
6
7
8
@Configuration
public class FooConfiguration {
@Bean
@Scope("prototype")
public Feign.Builder feignBuilder() {
return Feign.builder();
}
}

1.2 日志级别

配置类单独定义日志级别

1
2
3
4
5
6
7
8
9
10
11
12
@FeignClient(contextId = "fooClient", name = "stores", configuration = FooConfiguration.class)
public interface FooClient {
//..
}

public class FooConfiguration{

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

配置文件方式 (优先级高于代码配置)

1
2
3
4
5
6
7
8
9
10
@FeignClient(contentId="stores1" name = "stores")
public interface FooClient {
//..
}

feign:
client:
config:
stores1:
logLevel: full

1.3 feign支持配置项

配置文件方式:

image-20230116142927928

2.ribbon

1
2
3
4
@Configuration
@RibbonClient(name = "custom", configuration = CustomConfiguration.class)
public class TestConfiguration {
}

CustomConfiguration 不需要用 @Configuration 注解修饰, 并且不能被@ComponentScan在 application context 环境扫描到.否则 将被所有@RibbonClients 共用,如果你用了@ComponentScan (or @SpringBootApplication),你需要把这个配置排除在外。

默认ribbon配置:

Bean Type Bean Name Class Name
IClientConfig ribbonClientConfig DefaultClientConfigImpl
IRule ribbonRule ZoneAvoidanceRule
IPing ribbonPing DummyPing
ServerList<Server> ribbonServerList ConfigurationBasedServerList
ServerListFilter<Server> ribbonServerListFilter ZonePreferenceServerListFilter
ILoadBalancer ribbonLoadBalancer ZoneAwareLoadBalancer
ServerListUpdater ribbonServerListUpdater PollingServerListUpdater

2.2 自定义默认全局配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@RibbonClients(defaultConfiguration = DefaultRibbonConfig.class)
public class RibbonClientDefaultConfigurationTestsConfig {

public static class BazServiceList extends ConfigurationBasedServerList {

public BazServiceList(IClientConfig config) {
super.initWithNiwsConfig(config);
}

}

}

@Configuration(proxyBeanMethods = false)
class DefaultRibbonConfig {

@Bean
public IRule ribbonRule() {
return new BestAvailableRule();
}

@Bean
public IPing ribbonPing() {
return new PingUrl();
}

@Bean
public ServerList<Server> ribbonServerList(IClientConfig config) {
return new RibbonClientDefaultConfigurationTestsConfig.BazServiceList(config);
}

@Bean
public ServerListSubsetFilter serverListFilter() {
ServerListSubsetFilter filter = new ServerListSubsetFilter();
return filter;
}

}

2.3 自定义client配置通过属性配置

  • <clientName>.ribbon.NFLoadBalancerClassName: Should implement ILoadBalancer

  • <clientName>.ribbon.NFLoadBalancerRuleClassName: Should implement IRule

  • <clientName>.ribbon.NFLoadBalancerPingClassName: Should implement IPing

  • <clientName>.ribbon.NIWSServerListClassName: Should implement ServerList

  • <clientName>.ribbon.NIWSServerListFilterClassName: Should implement ServerListFilter

    属性配置,优先于代码配置

2.4 直接使用api

1
2
3
4
5
6
7
8
9
10
public class MyClass {
@Autowired
private LoadBalancerClient loadBalancer;

public void doStuff() {
ServiceInstance instance = loadBalancer.choose("stores");
URI storesUri = URI.create(String.format("https://%s:%s", instance.getHost(), instance.getPort()));
// ... do something with the URI
}
}

2.5 缓存ribbon配置

​ 每个Ribbon命名的客户端都有一个Spring Cloud维护的相应子应用程序上下文。该应用程序上下文在第一次请求命名客户端时被延迟加载。通过指定Ribbon客户端的名称,可以更改这种延迟加载行为,以在启动时急切地加载这些子应用程序上下文。

1
2
3
4
ribbon:
eager-load:
enabled: true
clients: client1, client2, client3