Springcloud zuul 实现API 网关
1,https://github.com/Netflix/zuul zuul 网关文档
2,什么是网关
网关就是客户端进行访问的时候,先经过网关服务器,再由网关服务器进行转发到真实的服务器。类似于Nginx
Nginx也可以搭建网关,但是由于Nginx是C语言开发的,在网关上添加一些功能比较麻烦。
Zuul 是java 写的网关框架,所以实现功能比较简单。
Nginx 也可以实现转发,做负载均衡,不过是服务器端的负载均衡。
zuul 网关进行负载均衡,是依赖Ribbon和Eureka,实现本地的负载均衡。
3,网关的作用
一般来说,公司搭建的内网网关就是微服务网关,是基于整个微服务项目。所以可以做一些去权限,日志打印,负载均衡,监控等作用。
4,和过滤器的区别
之前在安全架构的时候,实现防盗链等技术,或者是url 转码。都是共同过滤器,或者拦截器来实现的,是基于单个服务应用。如果每个服务都要写这些功能,还是要放在网关里面比较好。
5,
,
zuul,projectA,projectB 全都要注册到注册中心eureka上,让eureka 来管控:
step1: 建立eureka 服务
server:
port: 8100
eureka:
instance:
hostname: server1
client:
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
register-with-eureka: false
fetch-registry: false
启动类:
package com.aiyuesheng; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class EurekaApplication { public static void main(final String[] args) { SpringApplication.run(EurekaApplication.class, args); } }
step2: projectA
server:
port: 8000
spring:
application:
name: projectA
eureka:
client:
service-url:
defaultZone: http://localhost:8100/eureka
启动类:
@SpringBootApplication @EnableDiscoveryClient public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
controller:
@RestController public class Index { @RequestMapping("/") public String index() { return "PROJECTA"; } }
step2: projectB
server:
port: 8001
spring:
application:
name: projectB
eureka:
client:
service-url:
defaultZone: http://localhost:8100/eureka
启动类:
@SpringBootApplication @EnableDiscoveryClient public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
controller:
@RestController
public class Index {
@RequestMapping("/")
public String index() {
return "PROJECTB";
}
}
step4: zuul 配置网关
maven:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.1.RELEASE</version> </parent> <!-- 管理依赖 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.M7</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency> <!-- SpringBoot整合eureka客户端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> <!-- 注意: 这里必须要添加, 否者各种依赖有问题 --> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/libs-milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
配置文件:
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8100/eureka/
server:
port: 8080
spring:
application:
name: service-zuul
zuul:
routes:
projectA:
path: /projectA/**
serviceId: projectA
projectB:
path: /projectB/**
serviceId: projectB
启动类:
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; import org.springframework.context.annotation.Bean; @EnableZuulProxy @SpringBootApplication @EnableDiscoveryClient public class ZuulApplication { public static void main(String[] args) { SpringApplication.run(ZuulApplication.class, args); } // @Bean // public TokenFilter accessFilter() { // return new TokenFilter(); // } }
先启动eureka 注册中心,再启动其他三个服务,启动之后,可以web 页面查看服务是否注册上去:
我就可以通过网关配置的routes
routes:
projectA:
path: /projectA/**
serviceId: projectA
projectB:
path: /projectB/**
serviceId: projectB
127.0.0.1/projectA 就自动跳到A项目
127.0.0.1/projectB 就自动跳到B项目
6,zuul 网关默认整合了Ribbon
7, zuul 网关,由权限控制,拦截的功能,ZuulFilter
public class TokenFilter extends ZuulFilter { public Object run() throws ZuulException { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); Object accessToken = request.getParameter("accessToken"); if (accessToken == null) { // 返回错误信息 ctx.setSendZuulResponse(false); ctx.setResponseStatusCode(401); ctx.setResponseBody("accessToken is null"); return null; } return null; } public boolean shouldFilter() { return true;// 是否执行该过滤器,此处为true,说明需要过滤 } @Override public int filterOrder() { return 0;// 优先级为0,数字越大,优先级越低 } @Override public String filterType() { System.out.println("sss"); return "pre"; // 前置过滤器 } }