SpringCloud(六)学习笔记之Zuul

Zuul 在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架。Zuul 相当于是设备和 Netflix 流应用的 Web 网站后端所有请求的前门

Hystrix+Ribbon(不使用Feign)

一、构建Eureka Server

【基于第二章节创建的Eureka Server】

二、构建Eureka Client提供者

mhb-cloud-zuul-producer【端口:1002】
普通的Eureka Client项目 配置略......

com\applesnt\controller\ProducerController.java

package com.applesnt.controller;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/producer")
public class ProducerController {

    @GetMapping("/get/web")
    public String getId(){
        return "返回值为:producer";
    }
}

三、构建Eureka Client消费者集群

mhb-cloud-zuul-consumer 【端口:1000】
mhb-cloud-zuul-consumer2 【端口:1001】

1:pom文件

<!--eureka客户端环境支持-->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2:application.yml

mhb-cloud-zuul-consumer和mhb-cloud-zuul-consumer2只有端口不一样

debug: false

spring:
  application:
    name: mhb-cloud-zuul-consumer #每一个微服务必须有这个应用名称

server:
  port: 1000 #端口

eureka:
  instance:
    appname: zuul-consumer #eureka application的名称
    prefer-ip-address: true #开启ip显示eureka的主机服务
    #eureka仪表盘的Instances格式
    instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port}

  client:
    service-url:
     defaultZone: http://admin:123456@eureka1.com:8761/eureka/,http://admin:123456@eureka2.com:8762/eureka/,http://admin:123456@eureka3.com:8763/eureka/
    #从eureka服务器注册表中获取注册表信息的时间间隔,默认30s
    registry-fetch-interval-seconds: 30
    #客户端发送变化同步到eureka服务器的时间间隔 默认30s
    instance-info-replication-interval-seconds: 30
    #询问eureka服务url信息的变化的间隔时间 默认300s
    eureka-service-url-poll-interval-seconds: 300
    #最初同步到eureka服务器的时间 默认40s
    initial-instance-info-replication-interval-seconds: 40
    #注册表是否压缩
    g-zip-content: true
    #eureka等待超时时间 默认是5s
    eureka-server-connect-timeout-seconds: 5
    #eureka等待读取时间 默认是8s
    eureka-server-read-timeout-seconds: 8

3:启动类

package com.applesnt;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableEurekaClient
public class MhbCloudZuulConsumer2Application {

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

	@Bean
	@LoadBalanced/* 负载均衡 */
	public RestTemplate balanceRestTemplate(){
		return new RestTemplate();
	}
}

4:消费者controller

两个消费者controller 只有打印信息不同,为了看到集群效果
com\applesnt\controller\ConsumerController.java

package com.applesnt.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class ConsumerController {

    @Autowired
    private RestTemplate balanceRestTemplate;

    @GetMapping("/get/web")
    public String getId(){
        System.out.println("进入comsumer01");
        //eureka方式 需要在启动类的RestTemplate加上@LoadBalanced负载均衡的注解
        String returnId = balanceRestTemplate.getForObject("http://mhb-cloud-zuul-producer/producer/get/web",String.class);
        System.out.println("returnId = "+returnId);

        return returnId;
    }
}

四、构建Zuul网关项目

mhb-cloud-zuul 【提供者 端口:8080】

1:pom文件

<!--eureka客户端环境支持-->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

<!--zuul环境支持-->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>

2:启动类开启Zuul支持

@@EnableEurekaClient
@EnableZuulProxy

package com.applesnt;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@SpringBootApplication
@EnableEurekaClient/*eureka支持*/
@EnableZuulProxy/*Zuul注解*/
public class MhbCloudZuulApplication {

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

}

3:application.yml文件

debug: false

spring:
  application:
    name: mhb-cloud-zuul #每一个微服务必须有这个应用名称

server:
  port: 8080 #端口

eureka:
  instance:
    appname: zuul #eureka application的名称
    prefer-ip-address: true #开启ip显示eureka的主机服务
    #eureka仪表盘的Instances格式
    instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port}
  client:
    service-url:
     defaultZone: http://admin:123456@eureka1.com:8761/eureka/,http://admin:123456@eureka2.com:8762/eureka/,http://admin:123456@eureka3.com:8763/eureka/

#zuul自定义写法
zuul:
  routes:
    zuul-consumer: #自定义名称 必须要写path和serviceId
      path: /web/** #只要路径上有web 就会自动定位到mhb-cloud-zuul-consumer服务器上
      serviceId: mhb-cloud-zuul-consumer #服务名称  默认就支持负载均衡

4:zuul测试访问

http://127.0.0.1:8080/web/get/web
请求从zuul网关服务器上转发到消费者服务器上,在远程调用提供者的controller

日志信息:负载均衡

5:zuul路由规则

1》精简写法:http://127.0.0.1:8080/web/get/web

#精简写法:
zuul:
  routes:
      mhb-cloud-zuul-consumer: /web/** #路由名称如果是服务器名 就可以不用写path和serviceId

2》静态路由:http://127.0.0.1:8080/web/get/web

#静态url
zuul:
  routes:
    my-routes: #名称自定义
      path: /web/**
      url: http://127.0.0.1:1000

3》静态路由负载均衡:http://127.0.0.1:8080/web/get/web

zuul:
  routes:
    my-routes: #名称自定义
      path: /web/**
      serviceId: myurl
ribbon:
  eureka:
    enabled: false
myurl:
  ribbon:
    listOfServers: http://127.0.0.1:1000,http://127.0.0.1:1001

4》忽略服务

zuul:
  ignored-services: '*' #忽略所有默认的隐射机制 只路由指定的服务
  ignored-services: mhb-cloud-zuul-producer #忽略指定的服务

5》忽略请求:http://127.0.0.1:8080/web/get/web (无法访问)

zuul:
  ignoredPatterns: /**/get/** #过滤路径中有get请求的
  routes:
    zuul-consumer: #自定义名称 必须要写path和serviceId
      path: /web/** #只要路径上有web 就会自动定位到mhb-cloud-zuul-consumer服务器上
      serviceId: mhb-cloud-zuul-consumer

6》请求前缀

访问zuul网关:http://127.0.0.1:8080/api/web/get/web?token=123
转发后请求地址:http://mhb-cloud-zuul-consumer/web/get/web?token=123

strip-prefix: true 转发后会把前缀去掉

zuul:
  routes:
    zuul-consumer: #自定义名称 必须要写path和serviceId
      path: /web/** #只要路径上有web 就会自动定位到mhb-cloud-zuul-consumer服务器上
      serviceId: mhb-cloud-zuul-consumer
  prefix: /api
  strip-prefix: true

访问zuul网关:http://127.0.0.1:8080/api/web/get/web?token=123
转发后请求地址:http://mhb-cloud-zuul-consumer/api/web/get/web?token=123

strip-prefix: false 转发后会把前缀也一并带上

zuul:
  routes:
    zuul-consumer: #自定义名称 必须要写path和serviceId
      path: /web/** #只要路径上有web 就会自动定位到mhb-cloud-zuul-consumer服务器上
      serviceId: mhb-cloud-zuul-consumer
  prefix: /api
  strip-prefix: false

四:Zuul过滤器

mhb-cloud-zuul项目中构建AccessFilter 并继承 ZuulFilter
com\applesnt\filter\AccessFilter.java

示例:
访问网关请求的时候必须传递一个token,否则就返回拦截信息

package com.applesnt.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;

@Component /*不要忘记此注解*/
@Slf4j
public class AccessFilter extends ZuulFilter{

    /**
     * 过滤器类型选择:
     * pre 为路由前
     * route 为路由过程中
     * post 为路由过程后
     * error 为出现错误的时候
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * 用来过滤器排序执行的
     * @return 排序的序号
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 返回true表示执行这个过滤器
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * 过滤器的逻辑
     */
    @Override
    public Object run() {
        //获取当前请求上下文
        RequestContext ctx = RequestContext.getCurrentContext();
        //取出当前请求
        HttpServletRequest request = ctx.getRequest();
        String token = request.getParameter("token");
        if(StringUtils.isEmpty(token)){
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            ctx.getResponse().setContentType("text/html;charset=UTF-8");
            ctx.setResponseBody("请求异常 token为空");
        }
        log.info("进入访问过滤器,访问的url:{},访问的方法:{}",request.getRequestURL(),request.getMethod());
        return null;
    }
}

测试访问:
http://127.0.0.1:8080/web/get/web (不带token参数)

http://127.0.0.1:8080/web/get/web?token=123(带token参数)

posted @ 2020-04-01 16:06  努力的校长  阅读(208)  评论(0)    收藏  举报