使用Spring Cloud Netflix中的Eureka实现了服务注册中心以及服务注册与发现;
而服务间通过Ribbon或Feign实现服务的消费以及均衡负载;
通过Spring Cloud Config实现了应用多环境的外部化配置以及版本管理。
为了使得服务集群更为健壮,使用Hystrix的融断机制来避免在微服务架构中个别服务出现异常时引起的故障蔓延。
内部服务Service A和Service B,他们都会注册与订阅服务至Eureka Server,而Open Service是一个对外的服务,通过均衡负载公开至服务调用方
pom.xml依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency>
应用主类使用@EnableZuulProxy
注解开启Zuul
@EnableZuulProxy //开启Zuul @SpringCloudApplication public class Application { public static void main(String[] args) { new SpringApplicationBuilder(Application.class).web(true).run(args); } }
@SpringCloudApplication
注解,它整合了@SpringBootApplication
、@EnableDiscoveryClient
、@EnableCircuitBreaker
,主要目的还是简化配置
application.properties
中配置Zuul应用的基础信息,如:应用名、服务端口等
spring.application.name=api-gateway
server.port=5555
在Zuul中提供了两种映射方式:
# 路由到url 规则定义 zuul.routes.api-a-url.path=/api-a-url/** zuul.routes.api-a-url.url=http://localhost:2222/
该配置,定义了,所有到Zuul的中规则为:/api-a-url/**
的访问都映射到http://localhost:2222/
上,也就是说当我们访问http://localhost:5555/api-a-url/add?a=1&b=2
的时候,Zuul会将该请求路由到:http://localhost:2222/add?a=1&b=2
上。
配置属性zuul.routes.api-a-url.path中的api-a-url部分为路由的名字,可以任意定义,但是一组映射关系的path和url要相同.
通过url映射的方式对于Zuul来说,并不是特别友好,Zuul需要知道我们所有为服务的地址,才能完成所有的映射配置。而实际上,我们在实现微服务架构时,服务名与服务实例地址的关系在eureka server中已经存在了,所以只需要将Zuul注册到eureka server上去发现其他服务,我们就可以实现对serviceId的映射。
zuul.routes.api-a.path=/api-a/** zuul.routes.api-a.serviceId=service-A zuul.routes.api-b.path=/api-b/** zuul.routes.api-b.serviceId=service-B eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
尝试通过服务网关来访问service-A和service-B,根据配置的映射关系,分别访问下面的url
http://localhost:5555/api-a/add?a=1&b=2
:通过serviceId映射访问service-A中的add服务http://localhost:5555/api-b/add?a=1&b=2
:通过serviceId映射访问service-B中的add服务http://localhost:5555/api-a-url/add?a=1&b=2
:通过url映射访问service-A中的add服务推荐使用serviceId的映射方式,除了对Zuul维护上更加友好之外,serviceId映射方式还支持了断路器,对于服务故障的情况下,可以有效的防止故障蔓延到服务网关上而影响整个系统的对外服务
在完成了服务路由之后,我们对外开放服务还需要一些安全措施来保护客户端只能访问它应该访问到的资源。所以我们需要利用Zuul的过滤器来实现我们对外服务的安全控制。
在服务网关中定义过滤器只需要继承ZuulFilter
抽象类实现其定义的四个抽象函数就可对请求进行拦截与过滤。
/** * 利用Zuul的过滤器来实现我们对外服务的安全控制 * * 定义了一个Zuul过滤器 * 实现了在请求被路由之前检查请求中是否有accessToken参数, * 若有就进行路由,若没有就拒绝访问,返回401 Unauthorized错误。 */ public class AccessFilter extends ZuulFilter { private static Logger log = LoggerFactory.getLogger(AccessFilter.class); /** * 返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下: * pre:可以在请求被路由之前调用 * routing:在路由请求时候被调用 * post:在routing和error过滤器之后被调用 * error:处理请求时发生错误时被调用 * * @return */ @Override public String filterType() { return "pre"; } /** * 通过int值来定义过滤器的执行顺序 * @return */ @Override public int filterOrder() { return 0; } /** * 返回一个boolean类型来判断该过滤器是否要执行,所以通过此函数可实现过滤器的开关。 * 直接返回true,所以该过滤器总是生效 * @return */ @Override public boolean shouldFilter() { return true; } /** * 过滤器的具体逻辑 * * 通过ctx.setSendZuulResponse(false)令zuul过滤该请求,不对其进行路由, * 然后通过ctx.setResponseStatusCode(401)设置了其返回的错误码, * 当然我们也可以进一步优化我们的返回, * 比如,通过ctx.setResponseBody(body)对返回body内容进行编辑等。 * @return */ @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); log.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString())); Object accessToken = request.getParameter("accessToken"); if (accessToken == null) { log.warn("access token is empty"); ctx.setSendZuulResponse(false);// 不对其路由 ctx.setResponseStatusCode(401);//返回相应的错误码 return null; } log.info("access token ok"); return null; } }
在实现了自定义过滤器之后,还需要实例化该过滤器才能生效
@EnableZuulProxy @SpringCloudApplication public class Application { public static void main(String[] args) { new SpringApplicationBuilder(Application.class).web(true).run(args); } //在实现了自定义过滤器之后,还需要实例化该过滤器才能生效 @Bean public AccessFilter accessFilter() { return new AccessFilter(); } }
启动该服务网关后,访问:
http://localhost:5555/api-a/add?a=1&b=2
:返回401错误http://localhost:5555/api-a/add?a=1&b=2&accessToken=token
:正确路由到server-A,并返回计算内容filterType
生命周期介绍
原文:http://www.cnblogs.com/zhangjianbin/p/6262538.html