org.springframework.cloud
spring-cloud-starter-netflix-hystrix
添加注解 @EnableCircuitBreaker
这个时候,因为一个springcloud消费方一般都会有下面的三个注解,因此可以使用一个代替 即@SpringCloudApplication
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
服务降级方法,这个方法可以写在方法上,也可以写在类上面
(一),降级方法写在方法上面,这个时候降级方法,必须降级方法,必须跟方法的返回值和参数一致
@RequestMapping("/{id}")
@HystrixCommand(fallbackMethod = "defaultMethod")
public User queryById(@PathVariable("id") long id) {
}
public User defaultMethod(long id) {
User user = new User();
user.setUserName("服务器拥挤");
user.setUserCode("4525");
user.setDetail("hahahahhaha");
return user;
}
(二)降级方法写在类上
在类上面添加注解
@DefaultProperties(defaultFallback = "defaultMethod")
在方法添加注解
@HystrixCommand
编写降级方法,降级方法不能有任何参数,但是返回值必须与上面的方法返回值一样
public User defaultMethod() {
User user = new User();
user.setUserName("服务器忙");
return user;
}
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMillisecond: 6000 # 设置hystrix的超时时间为6000ms
@RequestMapping("/{id}")
//@HystrixCommand(fallbackMethod = "defaultMethod")
@HystrixCommand(commandProperties = {
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1000")
})
public User queryById(@PathVariable("id") long id) {
当服务,一段时间内的请求进入到降级方法的百分比到达一定比例,就会打开服务熔断,这个时候,请求过来,将不在发送请求,而是直接执行降级方法,然后熔断器会开始一段时间,一段时间后,熔断器会尝试请求一定服务,如果这个时候,执行降级方法的百分比还是到达一定比例,将会继续打开熔断器,否则熔断器关闭,服务正常访问,为了方便测试效果可以下面的三个参数进行重新,一般默认就行
这三个参数分别是,统计的次数,熔断器打开的时间,统计进入降级方法的百分比
@HystrixCommand(commandProperties = {
@HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value="10"),
@HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value="10000"),
@HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value="60")
})
public User queryById(@PathVariable("id") long id) {
org.springframework.cloud
spring-cloud-starter-openfeign
启动类上面加入注解
@EnableFeignClients // 开启Feign功能
将请求路径包装成一个接口,类似于spring mvc那样
@FeignClient("user-service")
public interface UserFeignClient {
@GetMapping("/user/{id}")
User queryUserById(@PathVariable("id") Long id);
}
将这个类注入到需要使用的地方,Feign已经帮我们实现了 RestTemplate 和 负载均衡和重试机制,因此我们不需要配置只需要使用就行
Feign对Hystix的支持,若想使用,则需要
(一)。在yml文件中将Hystix的支持打开
feign:
hystrix:
enabled: true # 开启Feign的熔断功能
(二)。实现Feign对请求路径包装的接口类,注意这个类,要交给sping来管理
@Component
public class UserClientImpl implements UserClient {
@Override
public User queryUserById(Long id) {
User user = new User();
user.setUserName("服务器忙");
return user;
}
}
(三)将上面的实现类,配置到接口类上
@FeignClient(value = "user-service",fallback = UserClientImpl.class)
(一),压缩是否开启
feign:
compression:
request:
enabled: true # 开启请求压缩
response:
enabled: true # 开启响应压缩
(二),压缩参数配置
feign:
compression:
request:
enabled: true # 开启请求压缩
mime-types: text/html,application/xml,application/json # 设置压缩的数据类型
min-request-size: 2048 # 设置触发压缩的大小下限
因为我们服务接口默认是对外暴露的,若是让用户直接访问,会有一定得风险,但是如果为每一个服务加上权限验证又过于复杂,因此我们需要使用Zuul,Zuul的作用,是用户所有的请求全部拦截到Zuul,然后Zuul根据访问路径,来决定调用那一个服务
org.springframework.cloud
spring-cloud-starter-netflix-zuul
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
@SpringBootApplication
@EnableZuulProxy // 开启Zuul的网关功能
public class ZuulDemoApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulDemoApplication.class, args);
}
}
server:
port: 10000
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10010/eureka
spring:
application:
name: zuulGetWay
zuul:
routes:
user-service: # 这里是路由id,随意写
path: /user-service/** # 这里是映射路径
serviceId: user-service # 指定服务名称 ,如果不使用eureka可以将路径配置成下面形式
# url: http://127.0.0.1:8001 # 映射路径对应的实际url地址
上面的配置由于太常见,因此zuul对注册中心里面的所有服务全部按照上面的规则注册了一遍,因此上面的
zuul规则可以不写,按照默认规则,所有的访问路径就是类似于下面这样
http:// + zuul的ip和端口号 + 服务id + 具体的拦截路径 + 参数
http://localhost:12306/consumer-service/cunsumer/2
如果我们不想这么麻烦的访问,只想直接http://localhost:12306/cunsumer/2就访问到具体的方法,我们进行如下配置
zuul:
routes:
consumer-service: # 这里是路由id,随意写
path: /consumer/** # 这里是映射路径
serviceId: consumer-service # 指定服务名称
strip-prefix: false # 即映射路径里面的consumer也作为访问路径
因为zuul会默认为所有的服务都配置访问路径,但是对于一些服务我们并不想暴露出去,因此可以使用下面配置进行屏蔽
zuul:
ignored-services:
-user-service
zuul的拦截器
@Component
public class LoginFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
//获取上下文
RequestContext ctx = RequestContext.getCurrentContext();
//获取request
HttpServletRequest request = ctx.getRequest();
//获取请求参数
String token = request.getParameter("access-token");
//判断是否存在
if(TextUtils.isBlank(token)){
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(HttpStatus.FORBIDDEN.value());
}
return null;
}