1.什么是微服务网关
微服务网关是整个微服务API接口的入口。
可以实现:
API接口过滤
验证登录
解决跨域
日志拦截
权限控制
限流熔断
负载均衡
黑白名单机制
2.过滤器和网关的区别
过滤器局部拦截
网关全局拦截
3.zuul网关和gateway网关区别
gateway比zuul的性能要好很多。
zuul底层基于servlet实现,阻塞式api,不支持长连接
gateway基于spring5构建,响应式非阻塞api,支持长连接
4.网关与nginx区别
相同点:都可以实现api拦截,负载均衡,反向代理,请求过滤
不同点: gateway采用java语言编写 nginx采用c语言编写
5.搭建网关
1)pom依赖
<properties>
<boot-version>2.1.11.RELEASE</boot-version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.11.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<!--nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<!--openfegin-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${boot-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2)yml配置
server:
port: 80
####服务网关名称
spring:
application:
name: demo-gateway
cloud:
gateway:
###路由策略
routes:
###根据我们的服务名称查找地址实现调用
- id: member
####转发 https://www.baidu.com/ http://127.0.0.1:8080/ lb://nacos-member/
uri: lb://nacos-member/
filters:
- StripPrefix=1
###匹配规则
predicates:
- Path=/member/**
discovery:
locator:
###允许通过注册中心获取地址调用
enabled: true
nacos:
discovery:
server-addr: 127.0.0.1:8848
3)全局过滤
package com.demo.filter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* 全局过滤-验证token
*/
@Component
public class TokenGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// //获取参数
// String token = exchange.getRequest().getQueryParams().getFirst("token");
// if (StringUtils.isEmpty(token)) {
// ServerHttpResponse response = exchange.getResponse();
// response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
// String msg = "token not is null ";
// DataBuffer buffer = response.bufferFactory().wrap(msg.getBytes());
// return response.writeWith(Mono.just(buffer));
// }
// 直接转发到真实服务
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
package com.demo.filter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* 全局过滤-跨域设置
*/
@Component
public class CrossOriginFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
HttpHeaders headers = response.getHeaders();
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "POST, GET, PUT, OPTIONS, DELETE, PATCH");
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "*");
headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*");
return chain.filter(exchange);
}
}
4)启动
package com.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AppGateWay {
public static void main(String[] args) {
SpringApplication.run(AppGateWay.class);
}
}
5)测试
http://localhost/member/getUser?userId=1
6.动态网关实现
链接:https://pan.baidu.com/s/1Yzcs7sbHH1oxaogl3q_XUg? 提取码:51ja
1)数据库
/*
Navicat Premium Data Transfer
Source Server : localhost
Source Server Type : MySQL
Source Server Version : 50727
Source Host : localhost:3306
Source Schema : nacos_gateway
Target Server Type : MySQL
Target Server Version : 50727
File Encoding : 65001
Date: 10/03/2022 17:52:15
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for sys_gateway
-- ----------------------------
DROP TABLE IF EXISTS `sys_gateway`;
CREATE TABLE `sys_gateway` (
`id` bigint(20) NOT NULL,
`route_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`route_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`route_pattern` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`route_type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`route_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of sys_gateway
-- ----------------------------
INSERT INTO `sys_gateway` VALUES (1, 'member', 'member', '/member/*', '0', 'http://127.0.0.1:8081/');
SET FOREIGN_KEY_CHECKS = 1;
2)pom依赖
<properties>
<boot-version>2.1.11.RELEASE</boot-version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.11.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<!--nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<!--openfegin-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!-- mysql 依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 阿里巴巴数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.14</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${boot-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
3)yml配置
server:
port: 80
####服务网关名称
spring:
application:
name: nacos-gateway
cloud:
gateway:
# ###路由策略
# routes:
# ###根据我们的服务名称查找地址实现调用
# - id: member
# uri: lb://nacos-member/
# filters:
# - StripPrefix=1
# ###匹配规则
# predicates:
# - Path=/member/**
discovery:
locator:
###允许通过注册中心获取地址调用
enabled: true
nacos:
discovery:
server-addr: 127.0.0.1:8848
datasource:
url: jdbc:mysql://localhost:3306/nacos_gateway?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
4)实体类
package com.demo.entity;
import lombok.Data;
@Data
public class GateWayEntity {
private Long id;
private String routeId;
private String routeName;
private String routePattern;
private String routeType;
private String routeUrl;
}
4)mapper
package com.demo.mapper;
import com.demo.entity.GateWayEntity;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
public interface GatewayMapper {
@Select("SELECT ID AS ID, route_id as routeid, route_name as routeName,route_pattern as routePattern,route_type as routeType,route_url as routeUrl FROM sys_gateway")
List<GateWayEntity> gateWayAll();
}
5)动态路由业务实现
package com.demo.service;
import com.demo.entity.GateWayEntity;
import com.demo.mapper.GatewayMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;
import javax.annotation.Resource;
import java.net.URI;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class GatewayService implements ApplicationEventPublisherAware {
private ApplicationEventPublisher publisher;
@Resource
private RouteDefinitionWriter routeDefinitionWriter;
@Resource
private GatewayMapper gatewayMapper;
private static final Logger logger = (Logger)LoggerFactory.getLogger(GatewayService.class);
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
public String loadAllLoadRoute() {
List<GateWayEntity> gateWayEntities = gatewayMapper.gateWayAll();
for (GateWayEntity gb : gateWayEntities) {
loadRoute(gb);
}
return "success";
}
public String loadRoute(GateWayEntity gateWayEntity) {
RouteDefinition definition = new RouteDefinition();
Map<String, String> predicateParams = new HashMap<>(8);
PredicateDefinition predicate = new PredicateDefinition();
FilterDefinition filterDefinition = new FilterDefinition();
Map<String, String> filterParams = new HashMap<>(8);
URI uri = null;
if ("0".equals(gateWayEntity.getRouteType())) {
// 如果配置路由type为0的话 则从注册中心获取服务地址
uri = UriComponentsBuilder.fromUriString("lb://" + gateWayEntity.getRouteUrl() + "/").build().toUri();
} else {
uri = UriComponentsBuilder.fromHttpUrl(gateWayEntity.getRouteUrl()).build().toUri();
}
// 定义的路由唯一的id
definition.setId(gateWayEntity.getRouteId());
predicate.setName("Path");
//路由转发地址
predicateParams.put("pattern", gateWayEntity.getRoutePattern());
predicate.setArgs(predicateParams);
// 名称是固定的, 路径去前缀
filterDefinition.setName("StripPrefix");
filterParams.put("_genkey_0", "1");
filterDefinition.setArgs(filterParams);
definition.setPredicates(Arrays.asList(predicate));
definition.setFilters(Arrays.asList(filterDefinition));
definition.setUri(uri);
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
this.publisher.publishEvent(new RefreshRoutesEvent(this));
return "success";
}
}
6)控制层
package com.demo.controller;
import com.demo.service.GatewayService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class GatewayController {
@Resource
private GatewayService gatewayService;
/**
* 同步网关配置
* @return
*/
@RequestMapping("/synGatewayConfig")
public String synGatewayConfig() {
return gatewayService.loadAllLoadRoute();
}
}
7)启动类
package com.demo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.demo.mapper")
public class AppGateWay {
public static void main(String[] args) {
SpringApplication.run(AppGateWay.class);
}
}
8)测试
http://localhost/synGatewayConfig? 同步网关配置
http://localhost/member/getUser?userId=1
|