<?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"> <parent> <artifactId>spring-cloud-microservice-study</artifactId> <groupId>com.clsaa.learn.springcloud</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>microservice-gateway-zuul</artifactId> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> </dependencies> </project>
package com.clsaa.learn.zuul; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; /** 使用@EnableZuulProxy註解激活zuul。 * 跟進該註解能夠看到該註解整合了@EnableCircuitBreaker、@EnableDiscoveryClient,是個組合註解,目的是簡化配置。 * Created by Egg on 2017/7/25 */ @SpringBootApplication @EnableZuulProxy public class ZuulApplication { public static void main(String[] args) { SpringApplication.run(ZuulApplication.class,args); } }
配置文件:application.ymlhtml
spring: application: name: microservice-gateway-zuul server: port: 8040 eureka: instance: hostname: localhost # 指定該Eureka實例的主機名 prefer-ip-address: true client: serviceUrl: defaultZone: http://username:password@localhost:8761/eureka
咱們如今訪問http://localhost:8050/microservice-provider-user/1試試。會驚人地看到:java
{"id":1,"username":"Tom","age":12}
這不正是microservice-provider-user服務中id=1的用戶信息嗎?web
因此咱們能夠總結出規律:訪問正則表達式
將會訪問到 http://GATEWAY:GATEWAY_PORT/想要訪問的Eureka服務id的小寫/**http://想要訪問的Eureka服務id的小寫:該服務端口/**
上文咱們已經完成了經過API Gateway去訪問微服務的目的,是經過http://GATEWAY:GATEWAY_PORT/想要訪問的Eureka服務id的小寫/**
的形式訪問的,那麼若是咱們想自定義在API Gateway中的路徑呢?譬如想使用http://localhost:8050/user/1
就可以將請求路由到http://localhost:8000/1呢?spring
只須要作一點小小的配置便可:apache
spring:
application:
name: microservice-api-gateway
server:
port: 8050
eureka:
instance:
hostname: gateway
client:
serviceUrl:
defaultZone: http://discovery:8761/eureka/
# 下面整個樹都非必須,若是不配置,將默認使用 http://GATEWAY:GATEWAY_PORT/想要訪問的Eureka服務id的小寫/** 路由到:http://想要訪問的Eureka服務id的小寫:該服務端口/**
zuul:
routes:
user: # 能夠隨便寫,在zuul上面惟一便可;當這裏的值 = service-id時,service-id能夠不寫。
path: /user/** # 想要映射到的路徑
service-id: microservice-provider-user # Eureka中的serviceId
若是咱們如今只想將microservice-consumer-movie-ribbon服務暴露給外部,microservice-provider-user不想暴露,那麼應該怎麼辦呢?後端
依然只是一點小小的配置便可:api
spring:
application:
name: microservice-api-gateway
server:
port: 8050
eureka:
instance:
hostname: gateway
client:
serviceUrl:
defaultZone: http://discovery:8761/eureka/
zuul:
ignored-services: microservice-provider-user # 須要忽視的服務(配置後將不會被路由)
routes:
movie: # 能夠隨便寫,在zuul上面惟一便可;當這裏的值 = service-id時,service-id能夠不寫。
path: /movie/** # 想要映射到的路徑
service-id: microservice-consumer-movie-ribbon-with-hystrix # Eureka中的serviceId
zuul:
routes:
users:
path: /myusers/**
url: http://example.com/users_service
zuul:
routes:
users:
path: /myusers/**
serviceId: users
ribbon:
eureka:
enabled: false
users: #這是ribion要請求的serviceID
ribbon:
listOfServers: http://localhost:7900,http://localhost:7901
@Bean public PatternServiceRouteMapper serviceRouteMapper() { return new PatternServiceRouteMapper( "(?<name>^.+)-(?<version>v.+$)", "${version}/${name}"); }
zuul:
ignoredPatterns: /**/admin/**
routes:
users: /myusers/**
This means that all calls such as 「/myusers/101」 will be forwarded to 「/101」 on the 「users」 service. But calls including 「/admin/」 will not resolve.安全
若是你須要你的路由以保留它們的順序,你須要使用YAML文件,由於使用屬性文件將會丟失順序。 例如:若是要使用屬性文件,則舊路徑可能會在用戶路徑前面顯示,致使用戶路徑沒法訪問。服務器
zuul:
routes:
first:
path: /first/**
url: http://first.example.com
second:
path: /second/**
url: forward:/second
third:
path: /third/**
url: forward:/3rd # 本地的轉發
legacy:
path: /**
url: http://legacy.example.com
package com.clsaa.learn.zuul.fallback; import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.client.ClientHttpResponse; import org.springframework.stereotype.Component; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @Component public class MyFallbackProvider implements ZuulFallbackProvider { @Override public String getRoute() { //route 如 return "microservice-provider-user"; } @Override public ClientHttpResponse fallbackResponse() { 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(("fallback"+MyFallbackProvider.this.getRoute()).getBytes()); } @Override public HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); return headers; } }; } }
Zuul大部分功能都是經過過濾器來實現的。Zuul中定義了四種標準過濾器類型,這些過濾器類型對應於請求的典型生命週期。
package com.clsaa.learn.zuul; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; @Component public class PreZuulFilter extends ZuulFilter{ private final static Logger LOGGER = LoggerFactory.getLogger(PreZuulFilter.class); @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 1;//數字越大越靠後 } @Override public boolean shouldFilter() { return true; } @Override public Object run() { HttpServletRequest servletRequest = RequestContext.getCurrentContext().getRequest(); String host = servletRequest.getRemoteHost(); PreZuulFilter.LOGGER.info("request host : " + host); return null; } }
479/5000
Zuul for Spring Cloud在代理和服務器模式下默認啓用了一些ZuulFilter bean。 有關已啓用的可能過濾器,請參閱zuul過濾器包。 若是你想禁用一個,只需設置:
zuul.<SimpleClassName>.<filterType>.disable=true
按照慣例,過濾器以後的包是Zuul過濾器類型。 例如,禁用
org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter set zuul.SendResponseFilter.post.disable = true