网上很多资源都把API网关,是什么,能做什么解释得十分分明,然而对于初学者来说我感觉是不够敌对的,Zuul就是SpringCloud微服务中的网关。
对于初学者入门来说,只须要晓得Zuul就是当服务增多之后,就要对API进行一个对立的治理,某个类型的API就会调用某个类型的服务,除此之外还能对申请过去的API进行一个过滤。更进一步才是Zuul其它作用,具体有哪些作用如图所示:
本文重点解说的是路由转发 和过滤器 。
1 如何引入Zuul
一样的,建设一个Zuul模块,本例中没有什么生产端,所以就没有采取之前建设空父模块再建设具体子模块的办法。而后往Zuul中的pom文件中增加依赖:
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency></dependencies>
到当初整个我的项目的目录构造如图所示:
2 主启动类和配置文件
因为不波及服务生产等,只是做api的解决,所以主启动类还是比较简单的
@SpringBootApplication@EnableZuulProxy //开启Zuul@EnableEurekaClientpublic class ZuulMain9401 { public static void main(String[] args) { SpringApplication.run(ZuulMain9401.class, args); }}
配置文件的话和惯例的Eureka客户端是一样的
spring: application: name: zuul9401server: port: 9401eureka: client: fetch-registry: true register-with-eureka: true service-url: defaultZone: http://localhost:8001/eureka/ instance: instance-id: zuul9401
3 路由转发
路由转发次要是通过配置文件来批改,往上面配置文件中减少内容 ,上面会讲3种形式的转发路由。
设置注册Eureka的服务id
减少第一波配置文件,是在原有的配置文件上减少了以下内容。
zuul: routes: user-a: path: /api-a/** serviceId: eureka-provide
user-a
是轻易定义 ,path
是内部拜访的门路,serviceId是微服务配置文件的spring.application.name
的值。
所以下面减少的配置文件整体意思是,当内部拜访/api-a/
相干门路时候,会转发给名字为eureka-provid
的服务提供服务。
开启Eureka服务注册核心EurekaServer8001
,服务提供者EurekaProvide7001/2/3
,API网关ZuulMain9401
:
接着拜访http://localhost:9401/api-a/e...eureka-provide
服务里的eureka/provide门路。
为了避免有点混,贴一次第一个我的项目的代码,详情请看本系列的第一篇文章。
@SpringBootApplication@RestController@EnableEurekaClientpublic class EurekaProvide7001 { @Value("${server.port}") int port; @GetMapping("/eureka/provide") public String getInfo() { return "hello, i am eureka provide, the provide service. My port: " + port; } @GetMapping("/eureka/delayProvide") public String delayGetInfo() throws InterruptedException { Thread.sleep(3000); return "hello, delay to do something"; } public static void main(String[] args) { SpringApplication.run(EurekaProvide7001.class, args); }}
能够看到可能胜利转发路由
设置URL
减少第二波配置文件
zuul: routes:# user-a:# path: /api-a/**# serviceId: eureka-provide user-b: path: /api-b/** url: http://localhost:7101/
其它如上,url
须要转发到哪个服务
通过Edit Configurations
更改端口以及服务名以模仿新的服务,具体操作同样在第一篇文章中有清晰的gif图。
其它服务不必敞开,持续开启刚新建的Provide7101
,重启ZuulMain9401
服务,拜访http://localhost:9401/api-b/e...
设置非注册Eureka的服务id
之前在学习Ribbon的时候也说过,咱们能够通过Ribbon设置拜访一些没有注册进Eureka的服务,同样在API网关也能通过配置文件设置Ribbon来达到一样的成果。
减少第三波配置文件
zuul: routes:# user-a:# path: /api-a/**# serviceId: eureka-provide# user-b:# path: /api-b/**# url: http://localhost:7101/ user-c: path: /api-c/** serviceId: provide-without-eureka#肯定须要这个才行ribbon: eureka: enabled: falseprovide-without-eureka: ribbon: ServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList listOfServers: localhost:7201, localhost:7202 ConnectTimeout: 1000 ReadTimeout: 3000 MaxTotalHttpConnections: 500 MaxConnectionsPerHost: 100
如果勾销user-a
的相干正文,此时拜访user-a是无奈转发的,会报500的谬误,我猜是因为设置了ribbon.eureka.enabled = false
的缘故。
serviceId同样是微服务的名称,而后对这个微服务设置,所以是设置微服务名[provid-without-eureka].ribbon
,其它属性都是相干属性,最重要的同样是listOfServers
,示意这个拜访这个服务名会在这些服务列表中进行调配。
为了简略还是用同一个服务,用下面的办法批改配置文件即可,批改端口号7201,批改eureka.client.register.with.eureka = false
来模仿没有注册进Eureka的服务。
接着再复制一份配置,其它都不遍,把端口号改成7202,总共是新建了端口为7201,7202的两个服务。
其它服务不必关,开启ProvideWithoutEureka7201/2
服务,重启ZuulMain9401
服务,此时所有的服务开启如下
拜访http://localhost:9401/api-c/e...
4 查看路由状态
顺便简略说下查看路由状态,首先还是须要减少配置文件,是肯定要减少
management: endpoints: web: exposure: include: "*" endpoint: health: show-details: ALWAYS
接着拜访http://localhost:9401/actuato...
如果想得到详细信息,那么只须要拜访http://localhost:9401/actuato...
5 转发路由时的Fallback
和Hystrix,当转发路由发现服务不可能失常提供服务的时候,就能够fallback。
新建一个类MyFallbackProvider
实现FallbackProvider
接口
@Componentpublic class MyFallbackProvider implements FallbackProvider { @Override public String getRoute() { //为所有的路由提供回退 return "*"; } @Override public ClientHttpResponse fallbackResponse(String route, Throwable throwable) { return new ClientHttpResponse() { @Override public HttpStatus getStatusCode() throws IOException { return HttpStatus.OK; } @Override public int getRawStatusCode() throws IOException { return 200; } @Override public String getStatusText() throws IOException { return "OK"; } @Override public void close() { } @Override public InputStream getBody() throws IOException { //回退后显示进去 return new ByteArrayInputStream("something wrong, fallback now".getBytes()); } @Override public HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); return headers; } }; }}
当初来手动敞开ProvideWithoutEureka7201/2
服务模仿服务宕机,来看看是否能回退
6 过滤器
之所以Zuul能实现验证、受权、动态资源解决等,就是得益于上面要讲的过滤器,然而次要是讲最根本的过滤,当前可能当前进阶的时候可能再深刻讲。
创立过滤器
首先创立filter包,而后创立一个过滤器类MyPreFilter
,须要实现ZuulFilter
接口
public class MyPreFilter extends ZuulFilter { @Override public String filterType() { //过滤器类型 return FilterConstants.PRE_TYPE; //申请前解决 } @Override public int filterOrder() { //过滤器程序,越小越优先 return 0; } @Override public boolean shouldFilter() { //是否开启过滤 return true; } @Override public Object run() throws ZuulException { //执行逻辑 RequestContext currentContext = RequestContext.getCurrentContext(); HttpServletRequest request = currentContext.getRequest(); System.out.println("[ PreFilter" + " ]" + String.format("send %s request to %s",request.getMethod(),request.getRequestURL())); return null; }}
在FilterConstants
类中定义了一系列常量,其中对于过滤器就是以下几种
public static final String ERROR_TYPE = "error"; //出错时执行public static final String POST_TYPE = "post"; //申请后申请public static final String PRE_TYPE = "pre"; //申请前申请public static final String ROUTE_TYPE = "route"; //解决指标申请
同时再建设一个后置申请
public class MyPostFilter extends ZuulFilter { @Override public String filterType() { return FilterConstants.POST_TYPE; } @Override public int filterOrder() { return 0; } @Override public boolean shouldFilter() { return true; } @Override public Object run() throws ZuulException { RequestContext currentContext = RequestContext.getCurrentContext(); HttpServletRequest request = currentContext.getRequest(); //这里把PreFilter改为PostFilter System.out.println("[ PostFilter" + " ]" + String.format("send %s request to %s",request.getMethod(),request.getRequestURL())); return null; }}
注入容器中
新建一个config包,在包下创立一个类ZuulConfiguration
@Configurationpublic class ZuulConfiguration { @Bean public MyPreFilter getZuulPreFilterBean() { return new MyPreFilter(); } @Bean public MyPostFilter getZuulPostFilterBean() { return new MyPostFilter(); }}
此时Zuul模块的目录构造如下
留神,这里有个坑,就是当开启了过滤器后,会发现前一大节的fallback生效。
重启ZuulMain9401
服务,并且清空idea输入控制台
如果是接着下面一节的内容,那么此时应该是转发的是非注册进Eureka服务的路由
拜访http://localhost:9401/api-c/e...
创作不易,如果对你有帮忙,欢送点赞,珍藏和分享啦!
上面是集体公众号,有趣味的能够关注一下,说不定就是你的宝藏公众号哦,根本2,3天1更技术文章!!!