1.zuul

1.1定义

zuul叫路由网关,它包含对请求的路由和过滤的功能。

路由负责将外部的请求转发到具体的微服务实例上,是实现外部访问统一入口的基础。而过滤是负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能基础。

1.2项目开发

源代码:https://github.com/zhongyushi-git/cloud-zuul.git

1)参考ribbon的项目新建一个项目cloud-zuul,把eureka集群、api以及服务提供者8001拿过来

2)在pom中导入依赖  

    <!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--eureka-client-->
<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>

3)配置yml

server:
port: 9527 spring:
application:
name: cloud-zuul-gateway #把客户端注册到服务列表中
eureka:
client:
#表示是否将自己注册进EurekaServer默认为true
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka/, http://eureka7002.com:7002/eureka/, http://eureka7003.com:7003/eureka/
#设置入驻的服务的名称,是唯一的
instance:
instance-id: gateway-9527.com
#访问路径显示ip
prefer-ip-address: true

4)在hosts文件添加映射

127.0.0.1  myzuul.com

5)在com.zys.cloud包下创建启动类并添加注解@EnableZuulProxy

package com.zys.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @SpringBootApplication
@EnableZuulProxy
public class ZuulMain9527 {
public static void main(String[] args) {
SpringApplication.run(ZuulMain9527.class, args);
}
}

6)启动测试

先启动eureka集群,然后启动微服务提供者8001,最后启动路由9527。

不用路由访问:http://localhost:8001/user/get/1
使用路由访问: http://myzuul.com:9527/cloud-provider/user/get/1,其中cloud-provider是微服务提供者的名称
在使用路由访问的时候,暴露出了微服务的名称,但是一般情况下是不会这样做的,因此需要对微服务名称进行代理。

7)配置服务代理

在路由的yml配置代理的名称并设置不能使用微服务名进行访问。

#配置微服务代理
zuul: routes:
#指定要代理的微服务名称
myuser.serviceId: cloud-provider
#指定代理的路径
myuser.path: /myuser/**
#忽略真实的服务名,即不能使用服务名访问,只能通过代理访问以保证安全
#忽略单个微服务
ignored-services: cloud-provider
#批量忽略微服务
# ignored-services: "*"

重启路由的服务,访问http://myzuul.com:9527/myuser/user/get/1是没有问题的,访问http://myzuul.com:9527/cloud-provider/user/get/1出现404,已达到效果。

实例中设置忽略了单个微服务,如果要批量忽略微服务,给ignored-services设置为"*"即可。

8)设置统一前缀

有时候多个系统之间访问的路径需要相同的前缀,这个时候只需要在yml配置即可。

zuul:
#设置统一的前缀
prefix: /springcloud

然后访问的时候都需要加这个前缀,访问路径是http://myzuul.com:9527/springcloud/myuser/user/get/1。

2.gateway

2.1定义

旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤功能,如熔断、限流、重试等。三大核心概念如下:

Route(路由):是构建网关的基本模块,由ID、URL、一系列断言和过滤器组成。
Predicate(断言):用于匹配Http请求中的所有内容,如果匹配则进行路由。
Filter(过滤):指的是Spring框架中GatewayFilter的实例

2.2zuul与gateway的区别

它是基于WebFlux框架实现的,而WebFlux框架底层使用了高性能的Reactor模式通信框架Netty,是基于异步非阻塞模型开发的。而zuul使用的是阻塞框架。

2.3项目开发

源代码:https://github.com/zhongyushi-git/cloud-gateway.git

2.3.1环境搭建

1)创建maven的父工程cloud-gateway,导入依赖

<!--统一管理jar包版本-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
</properties> <!-- 依赖管理,父工程锁定版本-->
<dependencyManagement>
<dependencies>
<!--spring boot 2.2.2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Hoxton.SR1-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
</dependencies>
</dependencyManagement> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>

2)创建eureka服务子模块cloud-eureka-server7001,导入依赖

<dependencies>
<!--eureka server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!--boot web actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency> </dependencies>

3)eureka的yml配置

server:
port: 7001 eureka:
instance:
#eureka服务端的实例名称
hostname: localhost
client:
#false表示不向注册中心注册自己
register-with-eureka: false
#false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
#设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

4)创建eureka启动类

package com.zys.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication
@EnableEurekaServer
public class EurekaMain7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaMain7001.class, args);
}
}

5)创建服务提供者子模块cloud-provider8001,导入依赖

 <dependencies>
<!--eureka client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--boot web actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>

6)8001的yml配置

server:
port: 8001 spring:
application:
name: cloud-provider #把客户端注册到服务列表中
eureka:
client:
#表示是否将自己注册进EurekaServer默认为true
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://localhost:7001/eureka/
#设置入驻的服务的名称,是唯一的
instance:
instance-id: cloud-provider8001
#访问路径显示ip
prefer-ip-address: true

7)创建8001启动类

package com.zys.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication
@EnableEurekaClient
public class ProviderMain8001 {
public static void main(String[] args) {
SpringApplication.run(ProviderMain8001.class, args);
}
}

8)创建8001的controller接口

package com.zys.cloud.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*; import java.util.Date; @RestController
@RequestMapping("/user")
public class UserController { @Value("${server.port}")
private String port; @Value("${eureka.client.service-url.defaultZone}")
private String eureka; @GetMapping("/get")
public String get(){
return "server port is \t"+port+".\t\t\t\t time:"+new Date();
} @GetMapping("/get2")
public String get2(){
return "eureka server is \t"+eureka+".\t\t\t\t time:"+new Date();
} }

9)创建服务提供者子模块cloud-provider8002,方式同8001,只是端口号不同。创建完成后先启动eureka,然后启动8001和8002,在浏览器测试接口。

2.3.2创建路由子模块cloud-gateway9527

1)导入依赖

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

需要注意的是,这里不需要导入web。

2)yml配置

server:
port: 9527 spring:
application:
name: cloud-gateway
cloud:
gateway:
#开启从注册中心动态创建路由的功能,利用微服务名进行路由
discovery:
locator:
enabled: true
routes:
- id: provider_routh #路由的ID,没有固定规则但要求唯一,简易配合服务名
uri: lb://cloud-provider #匹配后提供服务的路由地址,根据服务名访问
predicates:
- Path=/user/get/** #断言,路径相匹配的进行路由 - id: provider_routh #路由的ID,没有固定规则但要求唯一,简易配合服务名
uri: lb://cloud-provider #匹配后提供服务的路由地址
predicates:
- Path=/user/get2/** #断言,路径相匹配的进行路由 eureka:
instance:
hostname: cloud-gateway-service
instance-id: cloud-gateway
#访问路径显示ip
prefer-ip-address: true
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:7001/eureka/

3)创建启动类

package com.zys.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication
@EnableEurekaClient
public class GatewayMain9527 {
public static void main(String[] args) {
SpringApplication.run(GatewayMain9527.class,args);
}
}

4)启动测试

先启动eureka,然后启动8001和8002,最后启动9527。浏览器输入http://127.0.0.1:9527/user/get2就可以正常访问了。多刷新几次,可以看出是8001和8002轮询的。

2.3.3动态路由配置

除了2.3.2中使用yml的方式配置路由外,还可以通过编码方式配置。

新建配置类GateWayConfig

package com.zys.cloud.config;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; /**
* 编码方式配置路由
*/
@Configuration
public class GateWayConfig {
/**
* 配置一个id为route-name的路由规则,
* 当访问地址http://localhost:9527/guonei时会自动转发到地址:http://news.baidu.com/guonei
* @param routeLocatorBuilder
* @return
*/
@SuppressWarnings("JavaDoc")
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
routes.route("path_route1",
r -> r.path("/guonei")
.uri("http://news.baidu.com/guonei")).build();
return routes.build();
}
}

重启9527,访问地址http://localhost:9527/guonei时会自动转发到地址:http://news.baidu.com/guonei。

2.3.4断言配置

有时候为了进行配置,就可以配置断言。

例如:配置get2请求在某个时间后生效。只需要在yml的predicates设置After即可。

predicates:
- Path=/user/get2/** #断言,路径相匹配的进行路由
- After=2020-04-09T21:15:28.872+08:00[Asia/Shanghai]

后面的时间格式必须正确,获取格式时间的方法

public static void  getTime(){
ZonedDateTime zbj = ZonedDateTime.now();
System.out.println(zbj);
}

又如设置请求的方法必须为get

predicates:
- Path=/user/get2/** #断言,路径相匹配的进行路由
- After=2020-04-09T21:15:28.872+08:00[Asia/Shanghai]
- Method=GET

2.3.5过滤器配置

自定义一个过滤器,只有在请求中包含unmae且不为null时才能访问。创建过滤器类MyLogGateWayFilter

package com.zys.cloud.filter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono; /**
* 自定义过滤器
*/
@Component
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//每次进来后判断带不带uname这个key
String uname = exchange.getRequest().getQueryParams().getFirst("uname");
//uname为null非法用户
if(uname == null){
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}

重启9527,访问地址http://127.0.0.1:9527/user/get2时无法访问,而http://127.0.0.1:9527/user/get2?uname=1可以正常访问。

  

SpringCloud之服务网关的更多相关文章

  1. 八、springcloud之服务网关zuul(一)

    一.Zuul简介 zuul 是netflix开源的一个API Gateway 服务器, 本质上是一个web servlet应用. Zuul是Netflix出品的一个基于JVM路由和服务端的负载均衡器. ...

  2. 微服务SpringCloud之服务网关zuul二

    Zuul的核心 Filter是Zuul的核心,用来实现对外服务的控制.Filter的生命周期有4个,分别是“PRE”.“ROUTING”.“POST”.“ERROR”,整个生命周期可以用下图来表示. ...

  3. 微服务SpringCloud之服务网关zuul一

    前面学习了Eureka.Feign.Hystrix.Config,本篇来学习下API网关zuul.在微服务架构中,后端服务往往不直接开放给调用端,而是通过一个API网关根据请求的url,路由到相应的服 ...

  4. SpringCloud的服务网关zuul

    演示如何使用api网关屏蔽各服务来源 一.概念和定义 1.zuul最终还是使用Ribbon的,顺便测试一下Hystrix断路保护2.zuul也是一个EurekaClient,访问服务注册中心,获取元数 ...

  5. 二十一、springcloud(七)服务网关zuul

    1.简介 Eureka用于服务的注册于发现,Feign支持服务的调用以及均衡负载,Hystrix处理服务的熔断防止故障扩散,Spring Cloud Config服务集群配置中心,在微服务架构中,后端 ...

  6. 九、springcloud之服务网关zuul(二)

    一.路由熔断 当我们的后端服务出现异常的时候,我们不希望将异常抛出给最外层,期望服务可以自动进行一降级.Zuul给我们提供了这样的支持.当某个服务出现异常时,直接返回我们预设的信息. 我们通过自定义的 ...

  7. SpringCloud之服务网关Gateway,入门+实操

    SpringCloudAlibaba微服务实战教程系列 Spring Cloud 微服务架构学习记录与示例 一. GateWay简介 Spring Cloud GateWay是Spring Cloud ...

  8. 【微服务】之六:轻松搞定SpringCloud微服务-API网关zuul

    通过前面几篇文章的介绍,我们可以轻松搭建起来微服务体系中比较重要的几个基础构建服务.那么,在本篇博文中,我们重点讲解一下,如何将所有微服务的API同意对外暴露,这个就设计API网关的概念. 本系列教程 ...

  9. SpringCloud微服务负载均衡与网关

    1.使用ribbon实现负载均衡ribbon是一个负载均衡客户端 类似nginx反向代理,可以很好的控制htt和tcp的一些行为.Feign默认集成了ribbon. 启动两个会员服务工程,端口号分别为 ...

随机推荐

  1. 1.Centos7修改主机名

    1.在CentOS7中,有三种定义的主机名: 静态的(Static hostname):也称为内核主机名,是系统在启动时从/etc/hostname自动初始化的主机名. 瞬态的(Tansient ho ...

  2. GLIBC升级

    GLIBC升级 1.安装 1.1 说明 目前大部分架构都已经是GLIBC2.14了,难免会有一些老的机器会是GLIBC2.12,所以下面是我升级GLIBC的过程及步骤. GLIBC是系统核心服务,升级 ...

  3. php之PDOStatement::execute数组参数带有键值会出错

    当预处理的SQL语句是用问号占位符时,如果是用数组传参的,数组里不要带有键值,否则无法执行SQL. 出错的代码如下: $test = new PDODB(); $param=["d" ...

  4. C# 使用PictureBox实现图片按钮控件

    引言 我们有时候会在程序的文件夹里看见一些图标,而这些图标恰好是作为按钮的背景图片来使用的.鼠标指针在处于不同状态时,有"进入按钮"."按下左键"," ...

  5. 为何 JVM TLAB 在线程退还给堆的时候需要填充 dummy object

    TLAB 全网最硬核的解析,请参考:全网最硬核 JVM TLAB 分析 TLAB 在何时退还给堆? 有两种情况: 当前 TLAB 不足分配,并且剩余空间小于当前线程最大浪费空间限制时. 发生 GC 时 ...

  6. Educational Codeforces Round 83 D. Count the Arrays(组合,逆元,快速幂)

    题意: 从 m 个数中选 n - 1 个数组成先增后减的长为 n 的数组. 思路: 因为 n 个数中有两个数相同,所以每种情况实际上只有 n - 1 个不同的数--$c_m^{n - 1}$, 除去最 ...

  7. Luogu T16048 会议选址

    本题idea版权来自CSDN博客Steve_Junior的医院设置2. 并没有什么用的链接 题目背景 \(A\)国的国情十分独特.它总共有\(n\)个城市,由\(n-1\)条道路连接.国内的城市当然是 ...

  8. Codeforces Round #687 (Div. 2, based on Technocup 2021 Elimination Round 2) D. XOR-gun (二进制,异或,前缀和)

    题意:给你一组非递减的数,你可以对两个连续的数进行异或,使其合并为一个数,问最少操作多少次使得这组数不满足非递减. 题解:首先,给出的这组数是非递减的,我们考虑二进制,对于三个连续的非递减的最高位相同 ...

  9. SPOJ 227 Ordering the Soldiers

    As you are probably well aware, in Byteland it is always the military officer's main worry to order ...

  10. HDU 4272 LianLianKan(状压DP)题解

    题意:一个栈,每次可以选择和栈顶一样的数字,并且和栈顶距离小于6,然后同时消去他们,问能不能把所有的数消去 思路:一个数字最远能消去和他相距9的数,因为中间4个可以被他上面的消去.因为还要判断栈顶有没 ...