网站首页 > 博客文章 正文
环境:Springboot2.3.10.RELEASE + SpringCloud Hoxton.SR11 + SpringCloud Alibaba2.2.5.RELEASE + Redis
依赖
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
- 工程机构
- service-consumer子模块接口
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@Resource
private RestTemplate restTemplate ;
@Resource
private HttpServletRequest request ;
@GetMapping("/get")
public Object invoke(String serviceName) {
try {
TimeUnit.SECONDS.sleep(3) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
return restTemplate.getForObject("http://service-producer/discovery/get?serviceName=" + serviceName, Object.class);
}
}
- service-producer子模块接口
@RestController
@RequestMapping("discovery")
public class DiscoveryController {
@NacosInjected
private NamingService namingService;
@Resource
private DiscoveryClient discoverClient ;
@GetMapping(value = "/get")
public Object get(@RequestParam String serviceName) throws Exception {
Map<String, Object> res = new HashMap<>() ;
res.put("services", discoverClient.getServices()) ;
res.put("instances", discoverClient.getInstances(serviceName)) ;
res.put("port", 9000) ;
return res ;
}
}
服务发现配置(访问中直接服务名访问)
方式一(不推荐):
spring:
cloud:
gateway:
discovery:
locator:
# 如:http://localhost:9999/service-consumer/consumer/get?serviceName=service-producer
enabled: true
lower-case-service-id: true
通过上面的配置,我们可以直接通过服务名(spring.application.name)来访问服务。实际在生产环境应该不会这样用吧,所以这样的功能应该是关闭的。
访问:
方式二:
spring:
cloud:
gateway:
routes:
- id: gw001
#当前如果配置的路由被匹配,这里的uri就是被转发的地址
uri: lb://service-consumer
# 这里的name(Path)是GatewayPredicate接口实现类对应的前缀。如:PathRoutePredicateFactory => Path
predicates:
#下面两种写法都OK。XXX=xxx 这种写法与谓词工厂中的shortcutFieldOrder方法是对应的Pattern是List集合,那么多个配置就用逗号分割。
- Path=/api/**, /api-a/**, /api-b/**
filters:
#截取请求路径的第一段(http://xxx:port/api/demo) 这里会自动的截取掉/api
#最后的转发地址为: http://service-consumer/demo
- StripPrefix=1
访问:
这里可以分别通过/api, /api-a, /api-b三个前缀访问。
整合Hystrix
这里需要引入Hystrix依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
spring:
cloud:
gateway:
routes:
- id: gw001
#当前如果配置的路由被匹配,这里的uri就是被转发的地址
uri: lb://service-consumer
# 这里的name(Path)是GatewayPredicate接口实现类对应的前缀。如:PathRoutePredicateFactory => Path
predicates:
#下面两种写法都OK。XXX=xxx 这种写法与谓词工厂中的shortcutFieldOrder方法是对应的Pattern是List集合,那么多个配置就用逗号分割。
- Path=/api/**, /api-a/**, /api-b/**
filters:
- StripPrefix=1
- name: Hystrix
args:
name: gatewayfallback
fallbackUri: forward:/gateway/error
注意:Hystrix Filter的name必须填写,名称随意。fallbackUri属性是在降级的时候调用的接口。
@RestController
@RequestMapping("/gateway")
public class DefaultController {
@RequestMapping("/error")
public Object error() {
Map<String, Object> result = new HashMap<>() ;
result.put("code", -1) ;
result.put("message", "服务不可用,请稍候再试") ;
result.put("data", null) ;
return result ;
}
}
hysrix默认的熔断时间是1s,所以在service-consumer接口中通过睡眠3s来模拟
访问:
hysrix相关的配置还是按照常规的配置即可。
自定义过滤器
- 全局过滤器
@Component
public class GlobalExecutionTimeFilter implements GlobalFilter {
private static Logger logger = LoggerFactory.getLogger(GlobalExecutionTimeFilter.class) ;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
long start = System.currentTimeMillis() ;
Mono<Void> result = chain.filter(exchange) ;
logger.info("本次任务执行时间:{}", (System.currentTimeMillis() - start) + "毫秒") ;
return result ;
}
}
只需要实现GlobalFilter并且注册成Bean即可。全局过滤器会自动的应用到所有的路由上并且还不同配置任何东西。
访问:
- 自定义路由过滤器
该过滤器必须配置到具体的路由才能生效。
下面自定义一个验证token的过滤器。
@Component
public class TokenGatewayFilterFactory extends AbstractGatewayFilterFactory<TokenGatewayFilterFactory.TokenConfig> {
public static final String ENABLE_KEY = "enable";
public static final String EXCLUDE_KEY = "exclude" ;
public TokenGatewayFilterFactory() {
super(TokenConfig.class);
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList(ENABLE_KEY, EXCLUDE_KEY);
}
@Override
public GatewayFilter apply(TokenConfig config) {
return (exchange, chain) -> {
if (!config.isEnable()) {
return chain.filter(exchange) ;
}
ServerHttpRequest request = exchange.getRequest() ;
ServerHttpResponse response = exchange.getResponse() ;
String token = request.getHeaders().getFirst("access-token") ;
if (token == null || "".equals(token)) {
token = request.getQueryParams().getFirst("access-token") ;
}
if (token == null || "".equals(token)) {
DataBuffer data = setErrorInfo(response, "请检查Token是否填写");
return response.writeWith(Mono.just(data)) ;
}
return chain.filter(exchange) ;
};
}
private DataBuffer setErrorInfo(ServerHttpResponse response, String msg) {
//设置headers
HttpHeaders httpHeaders = response.getHeaders();
httpHeaders.add("Content-Type", "application/json; charset=UTF-8");
httpHeaders.add("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");
//设置body
String body = "{\"code\":-1, \"message\": \"" + msg + "\"}";
DataBuffer data = response.bufferFactory().wrap(body.getBytes());
return data;
}
public static class TokenConfig {
private boolean enable ;
private String exclude ;
public String getExclude() {
return exclude;
}
public void setExclude(String exclude) {
this.exclude = exclude;
}
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
}
}
配置:
spring:
cloud:
gateway:
routes:
- id: gw001
#当前如果配置的路由被匹配,这里的uri就是被转发的地址
uri: lb://service-consumer
# 这里的name(Path)是GatewayPredicate接口实现类对应的前缀。如:PathRoutePredicateFactory => Path
predicates:
#下面两种写法都OK。XXX=xxx 这种写法与谓词工厂中的shortcutFieldOrder方法是对应的Pattern是List集合,那么多个配置就用逗号分割。
- Path=/api/**, /api-a/**, /api-b/**
filters:
- StripPrefix=1
- name: Hystrix
args:
name: gatewayfallback
fallbackUri: forward:/gateway/error
- name: Token
args:
enable: true
访问:
如果请求header中不包含access-token
限流
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
spring:
cloud:
gateway:
routes:
- id: gw001
#当前如果配置的路由被匹配,这里的uri就是被转发的地址
uri: lb://service-consumer
# 这里的name(Path)是GatewayPredicate接口实现类对应的前缀。如:PathRoutePredicateFactory => Path
predicates:
#下面两种写法都OK。XXX=xxx 这种写法与谓词工厂中的shortcutFieldOrder方法是对应的Pattern是List集合,那么多个配置就用逗号分割。
- Path=/api/**, /api-a/**, /api-b/**
filters:
- StripPrefix=1
- name: RequestRateLimiter
args:
keyResolver: '#{@redisKeyResolver}' #SpringEL表达式
redis-rate-limiter.replenishRate: 1 #补充率,每秒产生多少令牌
redis-rate-limiter.burstCapacity: 2 #令牌桶容量
@Component
public class RedisKeyResolver implements KeyResolver {
// 限流策略,根据IP等信息进行限流,同一IP每秒访问次数
@Override
public Mono<String> resolve(ServerWebExchange exchange) {
String address = exchange.getRequest().getRemoteAddress().getHostString() ;
return Mono.just(address) ;
}
}
访问:
当访问过快就会返回429状态码,太多的请求。
完毕!!!
给个关注+转发呗谢谢
关注公众:Springboot实战案例锦集
SpringCloud Alibaba 之 Nacos 服务
猜你喜欢
- 2024-09-11 Spring整体架构和环境搭建(spring体系结构)
- 2024-09-11 项目spring boot实践系列2——spring security
- 2024-09-11 缓存管理方案 AutoLoadCache(缓存管理的功能是什么)
- 2024-09-11 可能是最全的Thymeleaf参考手册(四):标准表达式语法(三)
- 2024-09-11 缓存注解@Cacheable、@CacheEvict、@CachePut使用及注解失效时间
- 2024-09-11 SpringBoot进阶-缓存击穿,缓存穿透,缓存雪崩(八)
- 2024-09-11 Spring WebFlow 远程代码执行漏洞分析
- 2024-09-11 Spring 最常用的 7 大类注解,史上最强整理
- 2024-09-11 Spring常用的7大类注解(spring 常用的注解)
- 2024-09-11 Springboot常用注解(springboot常用注解和用法)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- powershellfor (55)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- vue数组concat (56)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)