SpringCloud--声明式调用:Feign

1.1 Feign调用WebApi

1.1.1 配置pom.xml

<dependency>

<groupid>org.springframework.cloud/<groupid>

<artifactid>spring-cloud-starter-openfeign/<artifactid>

1.1.2 客户端--启动设置:@EnableFeignClients

@EnableFeignClients

@SpringBootApplication

public class SpringBootConsulApplication {

public static void main(String[] args) {

SpringApplication.run(SpringBootConsulApplication.class, args);

}

}

1.1.3 Feign服务类

@FeignClient(name= "service-provider")

public interface HelloRemoteService {

@RequestMapping(value = "/hello")

public User hello(@RequestParam(value = "id") int id);

}

1.1.4 测试调用类

@Autowired

private HelloRemoteService userService;

/**

* 使用Feign,调用远程接口

* @return

*/

@RequestMapping("/FeignCall")

public User FeignCall(@RequestParam(value = "id") int id) {

User callServiceResult = userService.hello(id);

System.out.println(callServiceResult);

return callServiceResult;

}

1.2 Feign添加OAuth2 AuthorizatinHeader

1.2.1 实现feign.RequestInterceptor接口

import feign.RequestInterceptor;

import feign.RequestTemplate;

import lombok.extern.slf4j.Slf4j;

import org.springframework.security.core.Authentication;

import org.springframework.security.core.context.SecurityContext;

import org.springframework.security.core.context.SecurityContextHolder;

import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;

import org.springframework.context.annotation.Configuration;

@Configuration

public class FeignOauth2RequestInterceptor implements RequestInterceptor {

private final String AUTHORIZATION_HEADER = "Authorization";

private final String BEARER_TOKEN_TYPE = "Bearer";

@Override

public void apply(RequestTemplate requestTemplate) {

SecurityContext securityContext = SecurityContextHolder.getContext();

Authentication authentication = securityContext.getAuthentication();

if (authentication != null && authentication.getDetails() instanceof OAuth2AuthenticationDetails) {

OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails();

requestTemplate.header(AUTHORIZATION_HEADER, String.format("%s %s", BEARER_TOKEN_TYPE, details.getTokenValue()));

}

}

}

1.2.2 调用接口时,Feign自动添加Token

1.3 Feign调用时添加熔断器Hystrix

SpringCloud--声明式调用:Feign

1.3.1 服务端--添加超时及异常API

@RestController

public class HelloController {

private static Logger LOGGER = LoggerFactory.getLogger(HelloController.class);

@RequestMapping("/hello")

public @ResponseBody User hello(@RequestParam(value = "id") int id) {

LOGGER.info("invoking hello endpoint");

return new User(id, "hello consul from provider 1");

}

@RequestMapping("/timeout")

public String timeout() throws InterruptedException {

LOGGER.info("invoking timeout endpoint");

Thread.sleep(10000L);

return "timeout from provider 1";

}

@RequestMapping("/exception")

public String exception() {

LOGGER.info("invoking exception endpoint");

if (System.currentTimeMillis() % 2 == 0) {

throw new RuntimeException("random exception from provider 1");

}

return "exception from provider 1";

}

}

1.3.2 客户端--启动设置

@EnableFeignClients

@EnableHystrixDashboard

@EnableCircuitBreaker

@SpringBootApplication

public class SpringBootConsulApplication {

public static void main(String[] args) {

SpringApplication.run(SpringBootConsulApplication.class, args);

}

}

1.3.3 客户端--Yaml配置

server:

port: 8504

spring:

application:

name: service-consumer

cloud:

consul:

discovery:

register: false

host: 192.168.56.10

port: 8500

feign:

httpclient:

connection-timeout: 5000

connection-timer-repeat: 5000

enabled: true

max-connections: 200

max-connections-per-route: 50

hystrix:

enabled: true

ribbon:

# 暂不开启熔断机制

hystrix:

enabled: false

# 配置ribbon默认的超时时间

ConnectTimeout: 5000

ReadTimeout: 5000

# 是否开启重试

OkToRetryOnAllOperations: true

# 每个实例重试次数

MaxAutoRetries: 2

# 重试的时候实例切换次数

MaxAutoRetriesNextServer: 3

## hystrix相关配置

## hystrix默认会读取classpath下的config.properties文件,application会覆盖config.properties中的属性

hystrix:

threadpool:

# 指定服务的配置

user-service:

coreSize: 20

maxQueueSize: 200

queueSizeRejectionThreshold: 3

# userThreadPool是UserTimeOutCommand中配置的threadPoolKey

userThreadPool:

coreSize: 20

maxQueueSize: 20

queueSizeRejectionThreshold: 3

# 这是默认的配置

default:

coreSize: 10

maxQueueSize: 200

queueSizeRejectionThreshold: 2

command:

# 指定feign客户端中具体的方法

HelloRemoteService#timeout():

execution:

isolation:

thread:

timeoutInMilliseconds: 5000

userCommandKey:

execution:

isolation:

thread:

timeoutInMilliseconds: 1000

# 这是默认的配置

default:

execution:

timeout:

enabled: true

isolation:

strategy: THREAD

thread:

timeoutInMilliseconds: 15000

interruptOnTimeout: true

interruptOnFutureCancel: false

semaphore:

maxConcurrentRequests: 2

fallback:

enabled: true

isolation:

semaphore:

maxConcurrentRequests: 10

circuitBreaker:

enabled: true

forceOpen: false

forceClosed: false

requestVolumeThreshold: 4

errorThresholdPercentage: 50

sleepWindowInMilliseconds: 10000

metrics:

rollingStats:

timeInMilliseconds: 5000

numBuckets: 10

rollingPercentile:

enabled: true

timeInMilliseconds: 60000

numBuckets: 6

bucketSize: 100

healthSnapshot:

intervalInMilliseconds: 500

1.3.4 客户--消费接口设置

@Component

@FeignClient(name= "service-provider", fallback = HelloRemoteFallbackService.class)

public interface HelloRemoteService {

@RequestMapping(value = "/hello")

public User hello(@RequestParam(value = "id") int id);

@RequestMapping(value = "/timeout", method = RequestMethod.GET)

public String timeout();

@RequestMapping(value = "/exception", method = RequestMethod.GET)

public String exception();

}

1.3.5 客户端--Fallback设置

@Component

public class HelloRemoteFallbackService implements HelloRemoteService {

@Override

public User hello(int id)

{

System.out.println("调用服务失败--hello");

return null;

}

@Override

public String timeout() {

System.out.println("调用服务失败--timeout");

return "timeout 降级";

}

@Override

public String exception() {

System.out.println("调用服务失败--exception");

return "exception 降级";

}

}

1.3.6 客户端--相关配置

# 线程池大小

hystrix.threadpool.default.coreSize=1

# 缓冲区大小, 如果为-1,则不缓冲,直接进行降级 fallback

hystrix.threadpool.default.maxQueueSize=200

# 缓冲区大小超限的阈值,超限就直接降级

hystrix.threadpool.default.queueSizeRejectionThreshold=2

# 执行策略

# 资源隔离模式,默认thread。 还有一种叫信号量

hystrix.command.default.execution.isolation.strategy=THREAD

# 是否打开超时

hystrix.command.default.execution.timeout.enabled=true

# 超时时间,默认1000毫秒

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=15000

# 超时时中断线程

hystrix.command.default.execution.isolation.thread.interruptOnTimeout=true

# 取消时候中断线程

hystrix.command.default.execution.isolation.thread.interruptOnFutureCancel=false

# 信号量模式下,最大并发量

hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests=2

# 降级策略

# 是否开启服务降级

hystrix.command.default.fallback.enabled=true

# fallback执行并发量

hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests=100

# 熔断策略

# 启用/禁用熔断机制

hystrix.command.default.circuitBreaker.enabled=true

# 强制开启熔断

hystrix.command.default.circuitBreaker.forceOpen=false

# 强制关闭熔断

hystrix.command.default.circuitBreaker.forceClosed=false

# 前提条件,一定时间内发起一定数量的请求。 也就是5秒钟内(这个5秒对应下面的滚动窗口长度)至少请求4次,熔断器才发挥起作用。 默认20

hystrix.command.default.circuitBreaker.requestVolumeThreshold=4

# 错误百分比。达到或超过这个百分比,熔断器打开。 比如:5秒内有4个请求,2个请求超时或者失败,就会自动开启熔断

hystrix.command.default.circuitBreaker.errorThresholdPercentage=50

# 10秒后,进入半打开状态(熔断开启,间隔一段时间后,会让一部分的命令去请求服务提供者,如果结果依旧是失败,则又会进入熔断状态,如果成功,就关闭熔断)。 默认5秒

hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=10000

# 度量策略

# 5秒为一次统计周期,术语描述:滚动窗口的长度为5秒

hystrix.command.default.metrics.rollingStats.timeInMilliseconds=5000

# 统计周期内 度量桶的数量,必须被timeInMilliseconds整除。作用:

hystrix.command.default.metrics.rollingStats.numBuckets=10

# 是否收集执行时间,并计算各个时间段的百分比

hystrix.command.default.metrics.rollingPercentile.enabled=true

# 设置执行时间统计周期为多久,用来计算百分比

hystrix.command.default.metrics.rollingPercentile.timeInMilliseconds=60000

# 执行时间统计周期内,度量桶的数量

hystrix.command.default.metrics.rollingPercentile.numBuckets=6

# 执行时间统计周期内,每个度量桶最多统计多少条记录。设置为50,有100次请求,则只会统计最近的10次

hystrix.command.default.metrics.rollingPercentile.bucketSize=100

# 数据取样时间间隔

hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds=500

# 设置是否缓存请求,request-scope内缓存

hystrix.command.default.requestCache.enabled=false

# 设置HystrixCommand执行和事件是否打印到HystrixRequestLog中

hystrix.command.default.requestLog.enabled=false

# 限流策略

#如果没有定义HystrixThreadPoolKey,HystrixThreadPoolKey会默认定义为HystrixCommandGroupKey的值

hystrix.threadpool.userGroup.coreSize=1

hystrix.threadpool.userGroup.maxQueueSize=-1

hystrix.threadpool.userGroup.queueSizeRejectionThreshold=800

hystrix.threadpool.userThreadPool.coreSize=1

hystrix.threadpool.userThreadPool.maxQueueSize=-1

hystrix.threadpool.userThreadPool.queueSizeRejectionThreshold=800

hystrix.command.userCommandKey.execution.isolation.thread.timeoutInMilliseconds=5000

1.3.7 资料

Hystrix属性配置详情:https://github.com/Netflix/Hystrix/wiki/Configuration

SpringCloud的限流、熔断和降级:https://blog.csdn.net/chenxyz707/article/details/80913725

Feign、Hystrix使用时的超时时间(timeout)设置问题:https://blog.csdn.net/mxmxz/article/details/84633098


分享到:


相關文章: