为什么要有服务网关:
我们都知道在微服务架构中,系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢?难道要一个个的去调用吗?很显然这是不太实际的,我们需要有一个统一的接口与这些微服务打交道,这就是我们需要服务网关的原因。
在微服务架构中,不同的微服务可以有不同的网络地址,各个微服务之间通过互相调用完成用户请求,客户端可能通过调用N个微服务的接口完成一个用户请求。比如:用户查看一个商品的信息,它可能包含商品基本信息、价格信息、评论信息、折扣信息、库存信息等等,而这些信息获取则来源于不同的微服务,诸如产品系统、价格系统、评论系统、促销系统、库存系统等等,那么要完成用户信息查看则需要调用多个微服务,这样会带来几个问题:
- 客户端多次请求不同的微服务,增加客户端代码或配置编写的复杂性
- 认证繁杂,访问每个服务都要进行一次认证
- 每个服务都通过http访问,导致http请求增加,效率不高拖慢系统性能
- 多个服务存在跨域请求问题,处理起来比较复杂
- Zuul实现了两个功能,路由转发和过滤器:
- 路由转发:接受请求,转发到后端服务
- 过滤器:提供一系列过滤器完成权限、日志、限流等切面任务。
- 可以说路由+过滤器=Zuul
网关简要的配置
(1)pom.xml配置的依赖如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yun</groupId>
<artifactId>springcloud-eureka-zuul</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
</dependencies>
</project>
(2)application.yml 文件内容
server:
port: 8705
spring:
application:
name: eureka-gateway
#把服务注册到eureka注册中心
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8700/eureka/
zuul:
routes:
product-services:
eureka-consumer:
path: /Hello/**
url: http://127.0.0.1:8702/
(3)在启动类中,加上@EnableZuulProxy
注解,代码如下
@EnableZuulProxy
@SpringBootApplication
public class SpringbootZuulApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootZuulApplication.class, args);
}
}
(4)zuul过滤器
/**
* Zuul过滤器,必须继承ZuulFilter父类。
* 当前类型的对象必须交由Spring容器管理。使用@Component注解描述。
* 继承父类后,必须实现父类中定义的4个抽象方法。
* shouldFilter、 run、 filterType、 filterOrder
*/
@Component
public class LoggerFilter extends ZuulFilter {
private static final Logger logger = LoggerFactory.getLogger(LoggerFilter.class);
/**
* 返回boolean类型。代表当前filter是否生效。
* 默认值为false。
* 返回true代表开启filter。
*/
public boolean shouldFilter() {
return true;
}
/**
* run方法就是过滤器的具体逻辑。
* return 可以返回任意的对象,当前实现忽略。(spring-cloud-zuul官方解释)
* 直接返回null即可。
*/
public Object run() throws ZuulException {
// 通过zuul,获取请求上下文
RequestContext rc = RequestContext.getCurrentContext();
HttpServletRequest request = rc.getRequest();
logger.info("LogFilter1.....method={},url={}",
request.getMethod(),request.getRequestURL().toString());
// 可以记录日志、鉴权,给维护人员记录提供定位协助、统计性能
return null;
}
/**
* 过滤器的类型。可选值有:
* pre - 前置过滤
* route - 路由后过滤
* error - 异常过滤
* post - 远程服务调用后过滤
*/
public String filterType() {
return "pre";
}
/**
* 同种类的过滤器的执行顺序。
* 按照返回值的自然升序执行。
*/
public int filterOrder() {
return 0;
}
}
总结:
网关主要作用是,将客户端或移动端,不同请求转发到不同的服务,多个服务存在跨域请求问题,处理起来比较复杂