htvxjl0 2015-12-31
Zuul 是在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架。Zuul 相当于是设备和 Netflix 流应用的 Web 网站后端所有请求的前门。Zuul 可以适当的对多个 Amazon Auto Scaling Groups 进行路由请求。
其架构如下图所示:

Zuul提供了一个框架,可以对过滤器进行动态的加载,编译,运行。过滤器之间没有直接的相互通信。他们是通过一个RequestContext的静态类来进行数据传递的。RequestContext类中有ThreadLocal变量来记录每个Request所需要传递的数据。
过滤器是由Groovy写成。这些过滤器文件被放在Zuul Server上的特定目录下面。Zuul会定期轮询这些目录。修改过的过滤器会动态的加载到Zuul Server中以便于request使用。
下面有几种标准的过滤器类型:
过滤器的生命周期如下所示:

Zuul可以通过加载动态过滤机制,从而实现以下各项功能:
除此之外,Netflix公司还利用Zuul的功能通过金丝雀版本实现精确路由与压力测试。
其核心代码为:
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
try {
init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);
try {
preRouting();
} catch (ZuulException e) {
error(e);
postRouting();
return;
}
filterChain.doFilter(servletRequest, servletResponse);
try {
routing();
} catch (ZuulException e) {
error(e);
postRouting();
return;
}
try {
postRouting();
} catch (ZuulException e) {
error(e);
return;
}
} catch (Throwable e) {
error(new ZuulException(e, 500, "UNCAUGHT_EXCEPTION_FROM_FILTER_" + e.getClass().getName()));
} finally {
RequestContext.getCurrentContext().unset();
}
}Zuul加载Groovy过滤器:
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import static org.junit.Assert.*;
import static org.mockito.Mockito.spy;
public class GroovyCompiler {
private static final Logger LOG = LoggerFactory.getLogger(GroovyCompiler.class);
/**
* Compiles Groovy code and returns the Class of the compiles code.
*
* @param sCode
* @param sName
* @return
*/
public Class compile(String sCode, String sName) {
GroovyClassLoader loader = getGroovyClassLoader();
LOG.warn("Compiling filter: " + sName);
Class groovyClass = loader.parseClass(sCode, sName);
return groovyClass;
}
/**
* @return a new GroovyClassLoader
*/
GroovyClassLoader getGroovyClassLoader() {
return new GroovyClassLoader();
}
/**
* Compiles groovy class from a file
*
* @param file
* @return
* @throws java.io.IOException
*/
public Class compile(File file) throws IOException {
GroovyClassLoader loader = getGroovyClassLoader();
Class groovyClass = loader.parseClass(file);
return groovyClass;
}
@RunWith(MockitoJUnitRunner.class)
public static class UnitTest {
@Test
public void testLoadGroovyFromString() {
GroovyCompiler compiler = spy(new GroovyCompiler());
try {
String code = "class test { public String hello(){return \"hello\" } } ";
Class clazz = compiler.compile(code, "test");
assertNotNull(clazz);
assertEquals(clazz.getName(), "test");
GroovyObject groovyObject = (GroovyObject) clazz.newInstance();
Object[] args = {};
String s = (String) groovyObject.invokeMethod("hello", args);
assertEquals(s, "hello");
} catch (Exception e) {
assertFalse(true);
}
}
}
} 2、架构图zuul 像其他微服务一样作为一个微服务向eureka server注册,并且能够通过注册列表获取所有的可用服务,其内部默认实现了ribbon,可达到负载均衡的目的,此时的微服务架构图如下: