37、api网关-kong

一、API网关简介

  • 什么是api 网关
    • 我们知道在微服务架构中,大型服务都被拆分成了独立的微服务,每个微服务通常会以RESTFUL API的形式对外提供服务
    • 但是在UI方面,我们可能需要在一个页面上显示来自不同微服务的数据,此时就会需要一个统一的入口来进行API的调用
    • API Gateway就在此场景下充当了多个服务的大门,系统的统一入口
  • api 网关应该具备的功能
    • 服务路由
      • 动态路由:API Gateway可以与微服务注册中心连接,实现微服务无感知动态扩容
      • 负载均衡
    • 服务发现
    • 熔断降级:API Gateway对于无法访问的服务,可以做到自动熔断,无需人工参与
    • 黑白名单过滤
  • api网关技术选型
API网关 Kong APISIX Trk Apigee Aliyun
部署模式 单机和集群 单机和集群 单机和集群 不支持单机 RaaS
数据存储 Postgres或者Cassandra etcd Redis Postgres、Cassandra和Zookeeper RaaS
是否开源 Apache 2.0协议 Apache 2.0协议 MPL协议
核心技术 Nginx+Lua Nginx+Lua Golang 未知 未知
私有部署
自定义插件
社区活跃度
支持yaml

二、kong的安装和配置


三、动态路由

1 - kong的端口说明

  • 8001:kong的管理端口
  • 8000:用户访问的端口
  • 1337:konga地址

在这里插入图片描述

2 - 动态路由实现

  • SERVICES
    • Service顾名思义就是我们自己定义的上游服务,通过kong匹配到相应的请求要转发的地方
    • Service可以与下面的Router进行关联,一个Service可以有很多Router,匹配到的Router就会转发到Service中
    • 当然中间也会通过Plugin的处理,增加或者减少一些相应的Header或者其他信息
  • ROUTERS
    • Router路由相当于nginx配置中的location
    • Router实体定义匹配客户端请求的规则,每个路由都与一个服务相关联,而服务可能有多个与之相关联的路由
    • 每一个匹配给定路线的请求都将被提交给它的相关服务
    • 路由和服务的组合(以及它们之间的关注点分离)提供一种强大的理由基址,可以在kong中定义细粒度的入口点
    • 从而引导访问到不同的upstream服务
  • 添加Service

在这里插入图片描述
在这里插入图片描述

  • 为Service添加Router
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 测试kong的路由服务:开启goods_srv、goods_web,http://192.168.124.51:8000/g/v1/goods
    在这里插入图片描述
  • goods_web/initialize/init_router.go:修改下路由规则,去掉/g
package initialize

import (
	"github.com/gin-gonic/gin"

	"web_api/goods_web/middlewares"
	"web_api/goods_web/router"
)

func Routers() *gin.Engine {
    
    
	Router := gin.Default()

	//配置跨域
	Router.Use(middlewares.Cors())
	//ApiGroup := Router.Group("/g/v1")
	ApiGroup := Router.Group("/v1")

	router.InitGoodsRouter(ApiGroup)
	router.InitCategoryRouter(ApiGroup)
	router.InitBannerRouter(ApiGroup)
	router.InitBrandRouter(ApiGroup)

	return Router
}

  • konga的router中添加/g:记得回车并提交
    在这里插入图片描述
    在这里插入图片描述

3 - service、rouer、upstream请求过程

  • kong三种访问服务的方式
    • 硬编码方式:这个在之前的动态路由里面实现的
    • 通过upstream实现
    • 通过consul实现
  • 额外说明
    • routers路由匹配客户端的请求规则,匹配成功后分配到service层,一个路由指向一个service,一个service可以被多个不同规则的路由router指向
    • 访问地址:kong网关地址+代理端口(默认http=8000,https=8443)
    • service服务是一个抽象服务层,可以用于指向具体物理服务(target),也可以指向upstream用于实现物理服务的负载效果,一个service对于upstream、target都是一对一的关系

在这里插入图片描述

4 - kong集成consul服务发现与负载均衡

在这里插入图片描述
在这里插入图片描述

  • 浏览器访问:开启goods_srv、goods_web,[http://192.168.124.51:8000/g/v1/goods];我们可以看到依然可以访问
    在这里插入图片描述
  • 测试负载均衡
    • goods_web/main.go:修改为port随机,之前我们是写死的,flag = 5 // 这里为了测试kong的负载均衡
    • 开启2个goods_web服务,然后浏览器访问2次,我们可以看到每个服务各请求了一次
      在这里插入图片描述
      在这里插入图片描述

四、kong配置jwt实现登录校验

1 - 原理分析

  • 需求分析:之前我们已经做了jwt的验证,为什么还要在kong中使用jwt?
    • 很简单,因为api网关是统一的入口,我们只需要在网关中实现jwt验证,那么在业务中我们就不需要在做jwt校验了
  • 通用认证:一般情况下,上游api服务器都需要客户端有身份认证,且不允许错误的认证或无法认证的请求通过;认证插件可以实现这一需求
  • 通用认证插件的方案/流程
    • ①.向一个api或全局添加AUTH插件(此插件不作用域consumers)
    • ②.创建一个consumers对象
    • ③.为consumer提供指定的验证插件方案的身份验证凭据
    • ④.现在,只要有请求进入kong,都将检查其提供的身份验证凭据(取决于auth类型),如果该请求无法被验证或者验证失败,则请求会被锁定,不执行向上游服务转发的操作
    • 但是,上述的一般流程并不是总是有效的;比如,当使用了外部验证方案(比如LDAP)时,kong就不会(不需要)对consumer进行身份验证
  • Counsumers
    • 最简单的理解和配置consumer的方式,将其与“用户”进行一一隐射,即一个consumer代表一个“用户”(这里指的是应用,不要理解成登录的用户)
    • 但是对于kong而言,这些都无所谓;
    • consumer的核心原则是你可以为其添加插件,从而自定义它的请求行为;
    • 所以,或许你会有一个手机APP应用,并为他的每个版本都定义个consumer,又或者你有一个应用或几个应用,并为这些应用定义同一个consumer,这些都无所谓
    • 注意:这是一个模糊的概念,它叫做consumer,而不是user,要区分清楚

2 - kong配置jwt

  • 添加1个consumer
    在这里插入图片描述

  • 为这个consumer添加JWT
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 配置全局的PLUGIN:设置header为x-token
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 生成tokenhttps://jwt.io/,添加key和secret

在这里插入图片描述

  • 没有配置x-tocken时:返回"message": “Unauthorized”
    在这里插入图片描述
  • 配置x-token:将刚才在https://jwt.io/中生成token复制进来,并且前面要加上Bearer(这个是kong的要求)
    • 此时提示未登陆

在这里插入图片描述

  • 未登陆的原因分析
    • jwt的nacos配置中我们设置过secret了
    • jwt的验证要确认key是不是“imooc”,也就是之前未consumer添加JWT验证时候key和secret要和gin对应
    • 之前在用户服务时user_web/api/api_user.go,生成token的时候我们Issuer设置为的是“imooc”

在这里插入图片描述

  • 这时候还有一个非常重要的修改:之前我们在token中因为kong的要求添加了前缀Bearer,所以在jwt中我们就需要分割去掉Bearer
  • goods_web/middlewares/jwt.go
func JWTAuth() gin.HandlerFunc {
    
    
	return func(c *gin.Context) {
    
    
		// 我们这里jwt鉴权取头部信息 x-token 登录时回返回token信息 这里前端需要把token存储到cookie或者本地localSstorage中 不过需要跟后端协商过期时间 可以约定刷新令牌或者重新登录
		token := c.Request.Header.Get("x-token")
		if token == "" {
    
    
			c.JSON(http.StatusUnauthorized, map[string]string{
    
    
				"msg": "请登录",
			})
			c.Abort()
			return
		}
		token = strings.Split(token, " ")[1]
		j := NewJWT()
		// parseToken 解析token包含的信息
		claims, err := j.ParseToken(token)
		//省略

在这里插入图片描述


五、kong实现反爬和ip黑名单

1 - 反爬

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2 - ip黑名单

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq23001186/article/details/126357834