开始学习微服务(五)

1. zuul

功能:请求的路由和过滤

场景:请求校验等

2. zuul实现路由

使用:

加入依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.SR2</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

yml文件

server:
  port: 9000
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:3000/eureka/  #eureka服务端提供的注册地址 参考服务端配置的这个路径
  instance:
    instance-id: zuul-0 #此实例注册到eureka服务端的唯一的实例ID
    prefer-ip-address: true #是否显示IP地址
    leaseRenewalIntervalInSeconds: 10 #eureka客户需要多长时间发送心跳给eureka服务器,表明它仍然活着,默认为30 秒 (与下面配置的单位都是秒)
    leaseExpirationDurationInSeconds: 30 #Eureka服务器在接收到实例的最后一次发出的心跳后,需要等待多久才可以将此实例删除,默认为90秒

spring:
  application:
    name: zuul #此实例注册到eureka服务端的name

启动项和以往一样

@SpringBootApplication
@EnableZuulProxy
public class AppZuul {
    public static void main(String[] args) {
        SpringApplication.run(AppZuul.class);
    }

}

跑起来

测试一波

开始进入正题了

目的:不能通过服务名访问服务

方法:

在yml中加入

zuul:
  ignored-services: server-power
  routes:
    power:
      serviceId: server-power
      path: /power/**

power是自己定义的名字

/**代表所有层级

ignored-services不给通过这个服务名调用,ignored-services: '*'

禁止所有服务通过服务名调用

测试:

zuul:
  prefix: /api

加入前缀

如果路径为@RequestMapping("/api/getPower.do")可以选择不清楚api前缀,需要加入以下配置

zuul:
  prefix: /api
  strip-prefix: false

经过路由后的路径将会带上前缀api

3. 过滤器

种类:PRE(请求被路由之前调用), ROUTING(将请求路由到微服务), POST(路由到微服务以后执行), ERROR(其他阶段发生错误时)

禁用默认过滤器:zuul.LogFilter.pre.disable=true(yml中设置)

使用方法:需要继承ZuulFilter类 实现其中方法

请求对象怎么来?

//过滤器的具体逻辑
    //请求对象怎么来?
    @Override
    public Object run() throws ZuulException {
        //RequestContext.getCurrentContext()得到一个threadLocal<? extends RequestContext>
        RequestContext ctx = RequestContext.getCurrentContext();
        ...
        return null;
    }

小点:ThreadLocal(自己了解)

@Component
public class LogFilter extends ZuulFilter {
    //过滤器类型
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    //优先级
    @Override
    public int filterOrder() {
        return 0;
    }

    //判断该过滤器是否要执行
    @Override
    public boolean shouldFilter() {
        return true;
    }

    //过滤器的具体逻辑
    //请求对象怎么来?
    @Override
    public Object run() throws ZuulException {
        //RequestContext.getCurrentContext()得到一个threadLocal<? extends RequestContext>
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        System.out.println(request.getRemoteAddr()+"访问了"+request.getRequestURI());
        return null;
    }
}

访问http://localhost:9000/api/power/getPower.do会在控制台显示

0:0:0:0:0:0:0:1访问了/api/power/getPower.do

4. zuul容错和回退

 zuul默认是整合了hystrix和ribbon的,要使用hystrix需要实现FallbackProvider 类重写里面的方法

package com.lulu.provider;


import com.netflix.hystrix.exception.HystrixTimeoutException;
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

@Component
public class FallBackProvider implements FallbackProvider {
    
    @Override
    public String getRoute() {
        //制定为哪个微服务提供回退(这里写微服务名 写*代表所有微服务)
        return "*";
    }

    //此方法需要返回一个ClientHttpResponse对象  ClientHttpResponse是一个接口,具体的回退逻辑要实现此接口
    //route:出错的微服务名     cause:出错的异常对象
    @Override
    public ClientHttpResponse fallbackResponse(String route, final Throwable cause) {
        //这里可以判断根据不同的异常来做不同的处理, 也可以不判断
        //完了之后调用response方法并根据异常类型传入HttpStatus
        if (cause instanceof HystrixTimeoutException) {
            return response(HttpStatus.GATEWAY_TIMEOUT);
        } else {
            return response(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }



    private ClientHttpResponse response(final HttpStatus status) {
        //这里返回一个ClientHttpResponse对象 并实现其中的方法,关于回退逻辑的详细,便在下面的方法中
        return new ClientHttpResponse() {
            @Override
            public HttpStatus getStatusCode() throws IOException {
                //返回一个HttpStatus对象 这个对象是个枚举对象, 里面包含了一个status code 和reasonPhrase信息
                return status;
            }

            @Override
            public int getRawStatusCode() throws IOException {
                //返回status的code  比如 404,500等
                return status.value();
            }

            @Override
            public String getStatusText() throws IOException {
                //返回一个HttpStatus对象的reasonPhrase信息
                return status.getReasonPhrase();
            }

            @Override
            public void close() {
                //close的时候调用的方法, 讲白了就是当降级信息全部响应完了之后调用的方法
            }

            @Override
            public InputStream getBody() throws IOException {
                //吧降级信息响应回前端
                return new ByteArrayInputStream("降级信息".getBytes());
            }

            @Override
            public HttpHeaders getHeaders() {
                //需要对响应报头设置的话可以在此设置
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                return headers;
            }
        };
    }

}

停掉power测试

5. zuul集群

1. 思想

yml配置

zuul

server:
  port: 9000
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:3000/eureka/  #eureka服务端提供的注册地址 参考服务端配置的这个路径
  instance:
    instance-id: zuul-0 #此实例注册到eureka服务端的唯一的实例ID
    prefer-ip-address: true #是否显示IP地址
    leaseRenewalIntervalInSeconds: 10 #eureka客户需要多长时间发送心跳给eureka服务器,表明它仍然活着,默认为30 秒 (与下面配置的单位都是秒)
    leaseExpirationDurationInSeconds: 30 #Eureka服务器在接收到实例的最后一次发出的心跳后,需要等待多久才可以将此实例删除,默认为90秒

spring:
  application:
    name: zuul #此实例注册到eureka服务端的name

zuul:
  ignored-services: "*"
  routes:
    power:
      serviceId: zuul-server
      path: /zuul/**
  prefix: /api
#  strip-prefix: false
#    order:
#      serviceId: server-order
#      path: /order/**

zuul9001

server:
  port: 9001
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:3000/eureka/  #eureka服务端提供的注册地址 参考服务端配置的这个路径
  instance:
    instance-id: zuul-server-1 #此实例注册到eureka服务端的唯一的实例ID
    prefer-ip-address: true #是否显示IP地址
    leaseRenewalIntervalInSeconds: 10 #eureka客户需要多长时间发送心跳给eureka服务器,表明它仍然活着,默认为30 秒 (与下面配置的单位都是秒)
    leaseExpirationDurationInSeconds: 30 #Eureka服务器在接收到实例的最后一次发出的心跳后,需要等待多久才可以将此实例删除,默认为90秒

spring:
  application:
    name: zuul-server #此实例注册到eureka服务端的name

zuul:
  ignored-services: "*"
  routes:
    power:
      serviceId: server-power
      path: /power/**
#  prefix: /api
#    order:
#      serviceId: server-order
#      path: /order/**

zuul9002

server:
  port: 9002
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:3000/eureka/  #eureka服务端提供的注册地址 参考服务端配置的这个路径
  instance:
    instance-id: zuul-server-2 #此实例注册到eureka服务端的唯一的实例ID
    prefer-ip-address: true #是否显示IP地址
    leaseRenewalIntervalInSeconds: 10 #eureka客户需要多长时间发送心跳给eureka服务器,表明它仍然活着,默认为30 秒 (与下面配置的单位都是秒)
    leaseExpirationDurationInSeconds: 30 #Eureka服务器在接收到实例的最后一次发出的心跳后,需要等待多久才可以将此实例删除,默认为90秒

spring:
  application:
    name: zuul-server #此实例注册到eureka服务端的name

zuul:
  ignored-services: "*"
  routes:
    power:
      serviceId: server-power
      path: /power/**
#  prefix: /api
#  strip-prefix: false
#    order:
#      serviceId: server-order
#      path: /order/**

启动eureka3000,zuul,zuul9001,zuul9002,power

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值