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. OSPF特殊区域和LSA

    OSPF路由计算优选次序: (1) 直连路由:本路由器发起的LSA 1.2: (2) 区域内路由:O: LSA 1.2: (3) 区域间路由:O IA: LSA 3: (4) 1类外部路由:O E1: ...

  2. Codeforces Round #635 (Div. 2)

    Contest Info Practice Link Solved A B C D E F 4/6 O O Ø  Ø     O 在比赛中通过 Ø 赛后通过 ! 尝试了但是失败了 - 没有尝试 Sol ...

  3. 2019ICPC南昌站

    ICPC比CCPC场面要更大的感觉,这是我的第一印象. 这场比赛教练和我们一起去的,有教练陪着也挺好的,一起吃了吃饭.后来我们吃饭就发现江西这边辣就只是辣,没啥味道,不过拌粉还是可以的.还有江西师范大 ...

  4. Educational Codeforces Round 67 E.Tree Painting (树形dp)

    题目链接 题意:给你一棵无根树,每次你可以选择一个点从白点变成黑点(除第一个点外别的点都要和黑点相邻),变成黑点后可以获得一个权值(白点组成连通块的大小) 问怎么使权值最大 思路:首先,一但根确定了, ...

  5. Codeforces Round #655 (Div. 2) B. Omkar and Last Class of Math

    题目链接:https://codeforces.com/contest/1372/problem/B 题意 给出一个正整数 $n$,找到两个正整数 $a,b$ 满足 $a+b = n$ 且 $LCM( ...

  6. 洛谷P5496 回文自动机【PAM】模板

    回文自动机模板 1.一个串的本质不同的回文串数量是\(O(n)\)级别的 2.回文自动机的状态数不超过串长,且状态数等于本质不同的回文串数量,除了奇偶两个根节点 3.如何统计所有回文串的数量,类似后缀 ...

  7. 【uva 1617】Laptop(算法效率--贪心,2种理解)

    题意:有N条长度为1的线段,要求使每条线段分别在相应区间,且"空隙"数目最小.输出"空隙"数.(1≤N≤100000) 解法:(P.S.我这题竟做了2个多小时, ...

  8. CodeForces - 220B 离散化+莫队算法

    莫队算法链接:传送门 题意: 有n个数,m个区间.问区间内有多少个x,x满足x的个数等于x的值的个数(如果x是3,区间内要存在3个3). 题解: 因为a[i]太大,所以要离散化一下,但是不能用map容 ...

  9. Codeforces Round #481 (Div. 3) F. Mentors (模拟,排序)

    题意:有一个长度为\(n\)的序列\(a\),求这个序列中有多少比\(a_{i}\)小的数,如果某两个位置上的数有矛盾,则不能算小. 题解:用\(pair\)来记录序列中元素的位置和大小,将他们升序排 ...

  10. Codeforces Round #521 (Div. 3) E. Thematic Contests (离散化,二分)

    题意:有\(n\)个话题,每次都必须选取不同的话题,且话题数必须是上次的两倍,第一次的话题数可以任意,问最多能选取多少话题数. 题解:我们首先用桶来记录不同话题的数量,因为只要求话题的数量,与话题是多 ...