文章目录
  1. 1. 7天学会使用springcloud(三)
    1. 1.1. 组建通过zuul转发的方式来调用各app
    2. 1.2. zuul简介
    3. 1.3. 集成zuul
  2. 2. 启用zuul
    1. 2.1. zuul指定地址转发
    2. 2.2. 安全验证
    3. 2.3. Static Response handling
    4. 2.4. zuul filter
      1. 2.4.1. Sample Filters

7天学会使用springcloud(三)

组建通过zuul转发的方式来调用各app

上个章节集成了robbin来用service去访问app-client端的服务接口,但是如果我想通过service去访问各个app-client的接口,如果有很多接口,难道我就要在service同样新增几个中间接口去转一下吗?那岂不是很麻烦?!

放心 ,这个坑spring cloud已经给你踩好了,就等你入了。

用zuul这个组件就可以解决这个问题。
你只需要通过:

http://serviceip:port/appname/interfaceName

这样访问就可以了。

zuul简介

在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现、服务消费、负载均衡、断路器、智能路由、配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统。一个简单的微服务系统如下图:

t1

ps:先抄着吧,这张图有些地方画得不对,后面有时间去画一个

Zuul的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如/api/user转发到到user服务,/api/shop转发到到shop服务。zuul默认和Ribbon结合实现了负载均衡的功能。

官方地址:https://docs.openstack.org/infra/zuul/

项目地址:https://github.com/Netflix/zuul

zuul有以下功能:

  • Authentication 鉴权
  • Insights
  • Stress Testing 压力测试
  • Canary Testing 金丝雀测试(首测)
  • Dynamic Routing 动态路由
  • Service Migration 服务迁移
  • Load Shedding 分级卸载
  • Security 密码安全
  • Static Response handling
  • Active/Active traffic management

集成zuul

在Spring Cloud微服务系统中,一种常见的负载均衡方式是,客户端的请求首先经过负载均衡(zuul、Ngnix),再到达服务网关(zuul集群),然后再到具体的服务。服务统一注册到高可用的服务注册中心集群,服务的所有的配置文件由配置服务管理(下一篇文章讲述),配置服务的配置文件放在git仓库,方便开发人员随时改配置。

在service的pom.xml里新增:

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter</artifactId>
                </exclusion>
            </exclusions>
</dependency>

启用zuul

在入口类中加上’EnableZuulProxy’注解:

@SpringBootApplication
@EnableZuulProxy
@RestController
public class AppServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(AppServiceApplication.class, args);
    }


    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

    @Autowired
    HelloService helloService;


    @RequestMapping(value = "/hi")
    public String hi(@RequestParam String name){
        return helloService.hiService(name);
    }
}

然后重启app-service,地址栏输入地址:

http://localhost:9000/appclient/hi?name=11111

访问成功:

paste image

多刷几次发现它的负载均衡也是有效的:

paste image

我们的robbin+zull的集成完成了。

通过这种方式,我们可以无限的给各个app-client注册新的群组实例。

如果有些外部调用的服务不是一个微服务,但是我也想通过service去转发调用他们,那怎么办?

spring集成zuul的官方使用文档:

https://spring.io/guides/gs/routing-and-filtering/

zuul指定地址转发

在配置文件中加入:

application.yml:

zuul:
  sensitiveHeaders:
  addHostHeader: true
  ignored-services: 'protected-*'
  routes:
    otaapp:
      stripPrefix: true
      path: /thirdService/**
      url: http://192.168.1.200:8080
  host:
    maxTotalConnections: 5000
    maxPerRouteConnections: 500
    socket-timeout-millis: 60000
    connect-timeout-millis: 60000
  semaphore:
    maxSemaphores: 2000

那如果要经过网关层访问thirdService时,则只要输入:

http://{app-service的ip}:port/thirdService/接口名

就可以完成转发

安全验证

zuul不仅只是路由,并且还能过滤,做一些安全验证。继续改造工程;

@Component
public class MyFilter extends ZuulFilter{

    private static Logger log = LoggerFactory.getLogger(MyFilter.class);
    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        log.info(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString()));
        Object accessToken = request.getParameter("token");
        if(accessToken == null) {
            log.warn("token is empty");
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            try {
                ctx.getResponse().getWriter().write("token is empty");
            }catch (Exception e){}

            return null;
        }
        log.info("ok");
        return null;
    }
}

filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下:

  • pre:路由之前
  • routing:路由之时
  • post: 路由之后
  • error:发送错误调用
  • filterOrder:过滤的顺序
  • shouldFilter:这里可以写逻辑判断,是否要过滤,本文true,永远过滤。
  • run:过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。

Static Response handling

实现ZuulFallbackProvider这个接口,可以处理返回的值。

ps: 这个ZuulFallbackProvider是’org.springframework.cloud.netflix.zuul’的1.3.1版本有的,目前在最新版本里已经没有这个filter了,看最新的官方例子,应该是用HttpOutboundSyncFilter替代了。

zuul filter

参考官方文档:https://github.com/Netflix/zuul/wiki/Filters

Sample Filters

  • DebugRequest - look for a query param to add extra debug logging for a request

  • Healthcheck - simple static endpoint filter that returns 200, if everything is bootstrapped correctly

  • ZuulResponseFilter - add informational headers to provide extra details on routing, request execution, status and error cause

  • Core Filters
    GZipResponseFilter - can be enabled to gzip outbound responses
    SurgicalDebugFilter - can be enabled to route specific requests to different hosts for debugging

这些作用的filters在github上都有例子:

https://github.com/Netflix/zuul/tree/2.1/zuul-sample
文章目录
  1. 1. 7天学会使用springcloud(三)
    1. 1.1. 组建通过zuul转发的方式来调用各app
    2. 1.2. zuul简介
    3. 1.3. 集成zuul
  2. 2. 启用zuul
    1. 2.1. zuul指定地址转发
    2. 2.2. 安全验证
    3. 2.3. Static Response handling
    4. 2.4. zuul filter
      1. 2.4.1. Sample Filters