详讲api网关之kong的基本概念及安装和使用(二)

news2024/11/15 4:49:22

consul的服务注册与发现
如果不知道consul的使用,可以点击上方链接,这是我写的关于consul的一篇文档。

upstream+consul实现负载均衡

我们知道,配置upstream可以实现负载均衡,而consul实现了服务注册与发现,那么接下来我们就来看看利用这两个组件怎么实现负载均衡吧。

安装consul

  • docker安装consul,注意端口,注意将consul的网络加入到kong的网络中,即--network=kong-ee-net
docker run -d --name consul \
  --network=kong-ee-net \
  -p 8500:8500 \
  -p 8300:8309 \
  -p 8301:8301 \
  -p8302:8302 \
  -p 8600:8600/udp \
  hashicorp/consul consul agent -dev -client=0.0.0.0

gin服务注册到consul

  • 我们启动3个gin服务,并注册到consul中,相关代码如下,注意,服务端口是随机获取的,并注册到consul中,我们几乎不需要关心端口是多少
package main
import (
	"fmt"
	"gin-demo/config"
	"gin-demo/db"
	"gin-demo/route"
	"gin-demo/utils"
	"github.com/fvbock/endless"
	consulapi "github.com/hashicorp/consul/api"
)
// 定义服务注册的信息
type ServiceConfig struct {
	ID      string
	Name    string
	Tags    []string
	Port    int
	Address string
}

// consul的服务地址
var consulIp = "127.0.0.1:8500"

// 注册
func RegisterSevice(s ServiceConfig) error {
	consulConfig := consulapi.DefaultConfig()
	consulConfig.Address = consulIp

	//获取到客户端
	client, err := consulapi.NewClient(consulConfig)
	if err != nil {
		fmt.Printf("create consul client : %v\n", err.Error())
		return err
	}
	registration := &consulapi.AgentServiceRegistration{
		ID:      s.ID,
		Name:    s.Name,
		Port:    s.Port,
		Tags:    s.Tags,
		Address: s.Address,
	}

	if err := client.Agent().ServiceRegister(registration); err != nil {
		fmt.Printf("register to consul error: %v\n", err.Error())
		return err
	}
	return nil
}

func main() {
	//配置文件
	config.InitConfig()
	//sql初始化
	db.NewDb().InitAllSql()
	//启动
	r := route.InitRoute()
	//随机获取一个可用端口
	_, port := utils.RandomPort()

	//注册到consul
	consulPort := fmt.Sprintf("%d", port)
	service := ServiceConfig{
		ID:      consulPort,
		Name:    "blog_service",
		Tags:    []string{"blog"},
		Port:    port,
		Address: "192.168.11.20",
	}
	err := RegisterSevice(service)
	if err != nil {
		fmt.Printf("register to consul error: %v\n", err.Error())
	}

	//启动gin服务
	addr := fmt.Sprintf(":%d", port)
	err = endless.ListenAndServe(addr, r)
	if err != nil {
		return
	}
}

  • 启动完毕之后,我们访问consul的web页面已注册成功http://127.0.0.1:8500/ui/dc1/services/blog_service/instances
    在这里插入图片描述

  • 我们使用dns的方式访问一下

dig @127.0.0.1 -p 8600 blog_service.service.consul

在这里插入图片描述

kong里面配置consul

  • 通过docker network inspect kong-ee-net 查看consul的ip为172.23.0.4
  • 这里我们需要删除原来的kong容器,并使用以下命令创建一个新看kong,需要注意的是,由于你指定了KONG_DNS_RESOLVER,那么原来指定的KONG_PG_HOST就不可以再用dns的方式,因为consul里面并没有这个域名,会导致服务启动报错。所以要直接指定ip。
docker run -d --name kong \
  --network=kong-ee-net \
  -e "KONG_DATABASE=postgres" \
  -e "KONG_DNS_RESOLVER=192.168.11.20:8600" \
  -e "KONG_PG_HOST=172.23.0.2" \
  -e "KONG_PG_USER=kong" \
  -e "KONG_PG_PASSWORD=kong" \
  -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
  -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \
  -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \
  -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \
  -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \
  -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \
  -p 8000:8000 \
  -p 8443:8443 \
  -p 8001:8001 \
  -p 8444:8444 \
  kong-oss:latest
  • 启动之后,我们会再konga里面看到下面这行,这个时候,我们在kong里面配置的域名都会被 consul解析
    在这里插入图片描述

  • 我们配置blog_service.service.consul给service,就是咱们原来创建的blog的service
    在这里插入图片描述

  • 我们现在多访问几次接口 http://127.0.0.1:8000/v1/blog/detail?id=12,返回数据正常,我们多访问几次,查看三台服务的日志,均收到了请求
    在这里插入图片描述

在这里插入图片描述

jwt实现权限校验

一般情况下,上游api服务都需要客户端有身份验证,并且不影响错误的请求或者无认证的请求通过,那么此时,我们可以利用kong的jwt插件来实现,直接在网关这一层过滤掉请求

consumers

一个consumer可以代表一个微服务或者一个应用。为什么?因为你想给一个应用配置插件服务的话,比如说jwt认证,这个插件怎么样才能作用到这个应用上面呢?就是需要创建一个consumer,插件作用于consumer,consumer绑定应用。

  • 接下来我们创建一个consumer
    在这里插入图片描述
  • 添加jwt认证
    在这里插入图片描述
  • 全局配置jwt,配置header头的token名
    在这里插入图片描述
  • 此时我们再来访问http://127.0.0.1:8000/v1/blog/detail?id=12,已经不通过了
    在这里插入图片描述
  • 那么我们先手动构造一个token来验证一下,有两点需要注意,一个是jwt,是我们配置的验证名称,一个是iss
    在这里插入图片描述
  • 我们通过https://jwt.io/生成token,payload如下,注意secret去consumer中获取
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022,
  "iss":"jwt"
}

项目中引入jwt

  • 关于怎么使用jwt,我在jwt讲解这篇文章中说过。
  • 注意两个地方,一个是jwt的秘钥kong和gin必须保持一致
  • 一个是issuer必须保持一致,相关代码如下
package middleware

import (
	"gin-demo/service"
	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v5"
	"log"
	"strings"
	"time"
)

// 定义自己的秘钥 所有的服务必须用一个秘钥才能正确解析token
// 注意注意:这个秘钥必须和kong保持一致
var privateKey = []byte("FLHzZzGqZPlSzKgNyq4wXg4bKUhFRsH1")

// UserClaims 我们声明一个结构体,里面包含我们想要保存的信息
type UserClaims struct {
	Uid                  int64
	jwt.RegisteredClaims // 内嵌标准的声明
}

// GenToken 生成token
func GenToken(uid int64) (string, error) {
	//初始化结构体
	claims := UserClaims{
		Uid: uid,
		RegisteredClaims: jwt.RegisteredClaims{
			//设置过期时间
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Second * 3600)),
			//颁发时间
			IssuedAt: jwt.NewNumericDate(time.Now()),
			//主题
			Subject: "Token",
			//注意这里 发行人要和kong保持一致
			Issuer: "jwt",
		},
	}
	//生成token  使用hs256 加密 结构体,然后再用秘钥对其做数字签名
	return jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString(privateKey)
}

// 解析token
func ParseToken(c *gin.Context) {
	claims := new(UserClaims)
	xtoken := c.GetHeader("x-token")
	tokenString := strings.Split(xtoken, " ")
	if len(xtoken) == 0 || len(tokenString) < 2 {
		service.ErrorResponse(c, 9999, "请先登录!")
		return
	}
	log.Printf("解析到的token是:%v", tokenString)
	token, err := jwt.ParseWithClaims(tokenString[1], claims, keyFunc)
	log.Printf("解析到的token是:%v", err)
	if err != nil {
		c.Abort()
		service.ErrorResponse(c, 9999, "用户名密码错误!")
		return
	}
	//建议token是否有效
	if token.Valid {
		log.Printf("解析到的uid是:%d", claims.Uid)
		c.Set("uid", claims.Uid)
		c.Next()
	} else {
		c.Abort()
		service.ErrorResponse(c, 9999, "用户名密码错误!")
		return
	}
}

func keyFunc(token *jwt.Token) (interface{}, error) {
	return privateKey, nil
}

在这里插入图片描述

  • 结果
    在这里插入图片描述

  • 失败结果,kong直接拦截,并未到达服务层实例在这里插入图片描述

流量控制

  • 我们现在来配置一个每秒接收5个请求的限制
    在这里插入图片描述
  • 然后我们用jmeter测试一下,一秒内模拟10个用户发送10个请求
    在这里插入图片描述
  • 查看结果
    在这里插入图片描述

黑白名单

  • 我们可以选择指定给service或者route添加插件,下图我给route添加了插件
    在这里插入图片描述
  • 再次访问接口
    在这里插入图片描述

总结

kong的相关功能就演示完毕了,其他功能比如反爬策略,协议转换感兴趣的小伙伴们可以自己探索一下。

相关参考

相关参考
相关参考
官方文档
中文文档
相关文档
相关文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1420512.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

短视频与小程序:如何实现完美结合?

在短视频日益成为人们娱乐、社交和信息获取的重要渠道的今天&#xff0c;如何在短视频平台进行小程序推广成为了许多企业和品牌关注的焦点。本文将介绍如何利用短视频平台进行小程序推广&#xff0c;提升品牌曝光和用户互动。 首先&#xff0c;打开乔拓云-门店系统的后台&#…

让AI帮你说话--GPT-SoVITS教程

有时候我们在录制视频的时候&#xff0c;由于周边环境嘈杂或者录音设备问题需要后期配音&#xff0c;这样就比较麻烦。一个比较直观的想法就是能不能将写好的视频脚本直接转换成我们的声音&#xff0c;让AI帮我们完成配音呢&#xff1f;在语音合成领域已经有很多这类工作了&…

Linux操作系统权限相关问题(一站式速通权限)

一、sudo命令 sudo yum install -y sl sudo命令的作用 不切换用户&#xff0c;就想让普通用户以root的身份&#xff0c;执行对应的指令 输入密码时&#xff0c;输入的是自己普通用户的密码&#xff0c;而不是root的密码&#xff01;&#xff01;&#xff01; sudo可以进行…

500道微信小程序毕业设计题目,小程序新颖毕业选题推荐,建议收藏

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

通过Demo学WPF—数据绑定(一)✨

前言✨ 想学习WPF&#xff0c;但是看视频教程觉得太耗时间&#xff0c;直接看文档又觉得似懂非懂&#xff0c;因此想通过看Demo代码文档的方式进行学习。 准备✨ 微软官方其实提供了WPF的一些Demo&#xff0c;地址为&#xff1a;microsoft/WPF-Samples: Repository for WPF …

仿真APP在金属波纹管液压胀形工艺设计中的应用

一、背景介绍 金属波纹管是带有波纹状截面的金属管状零件&#xff0c;在工业中应用广泛。金属波纹管特殊的截面形状使其具备较好的柔韧性&#xff0c;能够在一定范围内伸缩弯曲。这一特性赋予波纹管两大用途&#xff1a;一是作为变形补偿器&#xff0c;可用于补偿管道设备由于…

MySQL原理(三)锁定机制

一、介绍&#xff1a; 1、锁的本质 业务场景中存在共享资源&#xff0c;多个进程或线程需要竞争获取并处理共享资源&#xff0c;为了保证公平、可靠、结果正确等业务逻辑&#xff0c;要把并发执行的问题变为串行&#xff0c;串行时引入第三方锁当成谁有权限来操作共享资源的判…

Windows Server 2025 LTSC 预览版来了

Windows Server 2025 LTSC 预览版来了 1. 安装 Windows Server 2025 LTSC 预览版2. 安装 VMware Tools3. Windows Server 2025 LTSC 预览版4. Windows Server 2025 LTSC 预览版下载地址 1. 安装 Windows Server 2025 LTSC 预览版 使用 VMware Workstation 安装&#xff0c; 安…

Mysql-事务(隔离级别,事务底层原理,MVCC)

什么是事务&#xff1f;有哪些特性&#xff1f; 事务&#xff1a;事务指的是逻辑上的一组操作&#xff0c;组成这组操作的各个单元要么全都成功&#xff0c;要么全都失败。 事务特性&#xff1a; 原子性&#xff08;Atomicity&#xff09;&#xff1a; 原子性是指事务是一个不…

如何在 Ubuntu 中安装 Microsoft Edge 浏览器

微软终于聪明了一回&#xff0c;也学会了「打不过就加入」。Microsoft Edge 浏览器的 Linux 稳定版已经于 2020 年 10 月 23 日发布&#xff0c;并提供给 Linux 发行版使用。除了官方 Edge APT 源以外&#xff0c;还提供了.deb和.rpm格式的安装包。 Microsoft Edge 基于 Chrom…

###C语言程序设计-----C语言学习(7)#(调试篇)

前言&#xff1a;感谢您的关注哦&#xff0c;我会持续更新编程相关知识&#xff0c;愿您在这里有所收获。如果有任何问题&#xff0c;欢迎沟通交流&#xff01;期待与您在学习编程的道路上共同进步。 一. 程序调试 1.程序调试介绍&#xff1a; 程序调试是软件开发过程中非常重…

大坑!react+thress.js

2. UI交互界面与Canvas画布叠加 | Three.js中文网 (webgl3d.cn) // canvas画布绝对定位 renderer.domElement.style.position absolute; renderer.domElement.style.top 0px; renderer.domElement.style.left 0px; renderer.domElement.style.zIndex -1; 我按照教程设置了…

C#小结:以Winform为例,总结一些C#在桌面开发中一些技巧

目录 一、给列表增加按钮&#xff0c;打印实体信息 二、嵌套子窗体 一、给列表增加按钮&#xff0c;打印实体信息 private void button1_Click(object sender, EventArgs e) {List<Student> studentList new List<Student>(){new Student() { Id 1, Name &quo…

Hadoop-MapReduce-源码跟读-MapTask阶段篇

一、源码下载 下面是hadoop官方源码下载地址&#xff0c;我下载的是hadoop-3.2.4&#xff0c;那就一起来看下吧 Index of /dist/hadoop/core 二、Mapper类 我们先看下我们写的map所继承的Mapper类 public class Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT> {/*** 传递…

python二维高斯热力图绘制简单的思路代码

import numpy as np import matplotlib.pyplot as plt from scipy.ndimage import gaussian_filter import cv2# 生成一个示例图像 image_size 100 image np.zeros((image_size, image_size))# 在图像中心创建一个高亮区域 center_x, center_y image_size // 2, image_size …

爱可声助听器参与南湖区价值百万公益助残捐赠活动成功举行

“声音大小合适吗&#xff1f;能听清楚吗&#xff1f;”今天下午&#xff0c;一场助残捐赠活动在南湖区凤桥镇悄然举行&#xff0c;杭州爱听科技有限公司带着验配团队和听力检测设备来到活动现场&#xff0c;为南湖区听障残疾人和老人适配助听器。 家住余新镇的75岁的周奶奶身体…

mac截图翻译软件有哪些?五大超实用翻译软件

mac截图翻译软件有哪些&#xff1f;随着全球化的发展&#xff0c;跨语言沟通已成为日常生活和工作中不可或缺的一部分。然而&#xff0c;语言障碍常常让我们在阅读外文资料时感到困惑。为了解决这一问题&#xff0c;Mac用户需要一款强大的截图翻译软件来帮助他们快速理解外文内…

Docker 搭建MySQL主从复制-读写分离

一. 介绍 MySQL主从复制是一种常用的数据库高可用性解决方案&#xff0c;通过在主数据库上记录的数据变更&#xff0c;同步到一个或多个从数据库&#xff0c;实现数据的冗余备份和读写分离。在Docker环境下搭建MySQL主从复制和读写分离&#xff0c;不仅方便管理&#xff0c;还…

MES和QMS怎么选?

MES&#xff0c;即制造执行系统&#xff0c;主要用于监控和控制生产过程&#xff0c;提升生产效率、减少生产成本。万界星空科技MES可以提供实时的生产数据&#xff0c;帮助企业做出更准确的决策&#xff0c;并且能够自动化地执行生产任务&#xff0c;提高生产线的效率和灵活性…

视频转GIF动图实践, 支持长视频转GIF

背景 找了很多GIF动图制作的工具&#xff0c;比如将视频转成GIF, 或者将一系列图片转成GIF, 增加背景文案等等功能。很多收费或者用的一些三方库有点点卡顿&#xff0c;或者需要安装一个软件&#xff0c;所以就自己做一款纯前端页面级别的 视频转 GIF 动图工具。 最开始找到一…