微服务架构中,整个系统由各个服务组成,由于在实用中这些微服务的地址都有可能发送变化,无法直接对外公布这些服务地址。这时,就需要一个独立的组件专门用来处理外部请求,将外部系统和内部系统进行切割,这个组件就叫做服务网关。
服务网关主要功能:
- 权限问题统一处理
- 数据剪裁和聚合
- 简化客户端调用
- 可以针对不同客户端提供不同网关支持
Spring Cloud中,网关主要有两种实现方案:Zuul和Spring Cloud Gateway
Zuul
Zuul是Netflix公司提供的动态路由网关服务。
Zuul功能:
- 权限控制,可以做认证和授权
- 监控
- 动态路由
- 负载均衡
- 静态资源处理
这些功能基本上都是基于过滤器来实现的,它的过滤器有几种不同类型:
- PRE:前置过滤器可用作身份校验
- ROUTING:将请求路由到微服务上
- POST:请求的微服务执行之后执行
- ERROR:过滤器执行出错时进入到此过滤器
路由配置
创建zuul模块,添加如下依赖
在配置文件中将该模块注册到Eureka
spring.application.name=zuul
server.port=2020
eureka.client.service-url.defaultZone=http://localhost:1111/eureka
在启动类上添加@EnableZuulProxy注解,开启网关代理
配置完成后,在浏览器中通过zuul就可以访问provider中的接口
访问地址:http://localhost:2020/provider/hello
(地址中provider就是访问服务名称,hello是provider中的接口。)
Zuul也支持通过配置文件自己配置路由规则
zuul.routes.helloZuul.path=/helloZuul/**
zuul.routes.hellZuul.service-id=provider
上面这个配置表示/helloZuul/**,满足这个匹配规则的请求,将被转发到provider上
匹配规则
假设有consumer和consumer-hello两个服务,在设置路由规则时做了如下配置
zuul.routes.consumer=/consumer/**
zuul.routes.consumer-hello=/consumer/hello/**
此时,若访问localhost:2020/consumer/hello/123
,就会出现冲突,若希望该地址与consumer-hello服务匹配,这时需要将配置文件改为yml格式。
请求过滤
对应来自客户端的请求,可以在Zuul中进行预处理,例如权限判断等。
定义一个简单的过滤器,重启Zuul:
@Component
public class PermissionFilter extends ZuulFilter {
/**
* 过滤器类型,一般为pre
* @return
*/
@Override
public String filterType() {
return "pre";
}
/**
* 过滤器优先级
* @return
*/
@Override
public int filterOrder() {
return 0;
}
/**
* 是否过滤
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 配置过滤逻辑
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String username = request.getParameter("username");
String password = request.getParameter("password");
if(!"admin".equals(username)||!"123".equals(password)){
//请求条件不满足时,在这里响应
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
ctx.addZuulResponseHeader("content-type","text/html;charset=utf-8");
ctx.setResponseBody("非法访问");
}
return null;
}
}
之后发送请求必须带上username和password,否则请求不通过。
忽略路径
在Zuul注册到Eureka上时会自动代理所以已经注册的服务,若不想给某一个服务做代理,也可以选择忽略该服务,只需要做如下配置
zuul.ignored-services=provider
该配置表示zuul会忽略provider服务,不对它进行代理。
也可以忽略某一类地址:
zuul.ignored-patterns=/**/hello/**
表示若路径中含hello则不进行代理
Spring Cloud Gateway
Gateway功能:
- 限流
- 路径重写
- 动态路由
- 集成Spring Cloud DiscoveryClient
- 集成Hystrix断路器
首先创spring boot项目,添加Spring Cloud Gateway依赖(注意:不要添加web依赖),项目创成功后在启动类中注入一个RouteLocator的bean就可以实现请求转发
@Bean
RouteLocator routeLocator(RouteLocatorBuilder builder){
return builder.routes()
.route("admin_route",r->r.path("/get").uri("http://httpbin.org"))
.build();
}
之后,启动项目,访问localhost:8080/get,可以看到请求被转发到指定地址
给项目添加依赖,使gateway注册到Eureka上
spring.application.name=gateway
eureka.client.service-url.defaultZone=http://localhost:1111/eureka
spring.cloud.gateway.discovery.locator.enabled=true
logging.level.org.springframework.cloud.gateway=debug
配置完成后就可以用Gateway访问到其他注册在Eureka上的服务
网友评论