第四篇: 路由网关(zuul)

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

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

一、Zuul简介

Zuul的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如/api/user转发到到user服务,/api/shop转发到到shop服务。zuul默认和Ribbon结合实现了负载均衡的功能。(本篇講解feign,暫不使用Ribbon)

zuul有以下功能:

  • Authentication
  • Insights
  • Stress Testing
  • Canary Testing
  • Dynamic Routing
  • Service Migration
  • Load Shedding
  • Security
  • Static Response handling
  • Active/Active traffic management

二、准备工作

继续使用上一节的工程。在原有的工程上,创建一个新的工程。

三、创建zuul工程

其pom.xml文件如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>com.leopard</groupId>
		<artifactId>leopard-parent</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<groupId>com.leopard</groupId>
	<artifactId>leopard-zuul</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>
	<name>leopard-zuul</name>
	<url>http://maven.apache.org</url>


	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>

		<!-- eureka -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>

		<!-- 上边引入 parent,因此 下边无需指定版本 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!-- zuul -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-zuul</artifactId>
		</dependency>

	</dependencies>


</project>

在其入口applicaton类加上注解@EnableZuulProxy,开启zuul的功能:

package com.leopard.service.zuul;

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;

@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class ZuulServiceApplication {

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

}

加上配置文件application.yml加上以下的配置代码:

spring:
  application:
    name: leopard-service-zuul

server:
  port: 8282

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
      
zuul:
  routes:
    api-a:
      path: /api-a/**
      serviceId: leopard-service
    api-b:
      path: /api-b/**
      serviceId: leopard-service-feign

首先指定服务注册中心的地址为http://localhost:8761/eureka/,服务的端口为8282,服务名为leopard-service-zuul;以/api-a/ 开头的请求都转发给端口号为8081 的leopard-service服务;以/api-b/开头的请求都转发给端口号为8181 的leopard-service-feign服务;

依次打开 eureka、service、feign、zuul四个服务。

访问链接: http://localhost:8282/api-a/test/getObject

hi leopard,this port is :8081

访问链接: http://localhost:8282/api-b/test/getObject

hi leopard,this port is :8181

这说明zuul起到了路由的作用

四、服务过滤

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

创建过滤器

package com.leopard.service.zuul.filter;

import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;

@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去判断该请求到底有没有权限访问。

 这时访问: http://localhost:8282/api-a/test/getObject 或 http://localhost:8282/api-b/test/getObject ,网页都显示:

token is empty

 加入过滤器中的 token 再次访问: http://localhost:8282/api-a/test/getObject?token=leopard

hi leopard,this port is :8081

说明过滤器应用成功。

文章转载: https://blog.csdn.net/forezp/article/details/81041012 

猜你喜欢

转载自blog.csdn.net/u014799292/article/details/81395498
今日推荐