文章目录

  • 1. 简介
  • 2. 环境搭建
    • 2.1 前置条件
    • 2.2 开始
      • 2.2.1 获取Kong源码
      • 2.2.2 准备IDE(VSCODE)
    • 2.3 Kong环境配置
      • 2.3.1 获取相关依赖
      • 2.3.2 配置
  • 3自定义插件开发
    • 3.1 插件目录结构
    • 3.2 自定义逻辑编写
      • 3.2.1 handler.lua 生命周期
      • 3.2.2 handler.lua 文件规范
      • 3.2.3 schema.lua规范
  • 4 举个栗子
    • 4.1 插件代码部分
      • 4.1.1 hello-world.handler.lua
      • 4.1.2 hello-world.schema.lua
      • 4.1.3 安装并启动kong
    • 4.2 konga安装与使用(非必需)
      • 4.2.1 konga源码安装
      • 4.2.2 mysql安装与配置
      • 4.2.3 konga配置
      • 4.2.4 konga运行
    • 4.3 测试验证
      • 4.3.1 配置 `SERVICES (服务)`/`ROUTES(路由)`/ `PLUGINS(插件)`
      • 4.3.2 通过浏览器或 curl请求进行功能验证
  • 5 参考资料
    • 说明

1. 简介

  • Kong是一个api网关,在客户端和服务间转发API进行通信,支持自定义插件来扩展功能。
  • Kong 是在Nginx基础上构建的,更确切地说,kong是在Nginx中运行的Lua应用程序,由 lua-nginx-module实现。
  • Kong和OpenResty一起发行的,其中已经包含了lua-nginx-module。其中OpenResty不是Nginx的分支,而是一堆扩展其功能的模块。
  • Kong是可拔插架构,在该架构中,可以在运行时启用和执行Lua脚本(可称为“插件”),其核心是实现数据抽象、路由和插件管理。
  • 插件可以独立存在于单独的代码库中,并可通过几行代码注入到请求生命周期的任何位置,类似于java的AOP切面。
  • 插件开发套件(或“ PDK”)与请求/响应对象或流进行交互,以实现任意逻辑。PDK是一组Lua函数,插件可以使用它们来促进插件与Kong的核心(或其他组件)之间的交互。

2. 环境搭建

Kong 的安装(部署)方式较为多样,支持多种操作环境,如Docker,Ubuntu,CentOS,MacOS系统等等,详情可见Kong安装 ,但其开发环境却是有些受限,在windows系统中表现尤为明显。 在Windos系统中,本人做了如下尝试:

  • 通过Docker搭建开发环境,由于电脑环境限制,未取得良好效果;
  • 通过运行Linux虚拟机搭建开发环境,可行但Linux虚拟机不是很稳定;
  • 直接安装Linux[Ubuntu]系统,进行开发。

关于Kong插件开发,实际上也可以理解为Lua程序的编写,本文采用的是vscode+lua扩展(如EmmyLua)作为IDE进行开发的,其中值得注意的是Lua的编译器采用的是LuaJIT,详情可参考OpenResty最佳实践一书(开源书籍,包括了Lua & Nginx& Lua Module & OpenResty开发测试等内容)

2.1 前置条件

  • 系统准备

    • Linux系统(如Ubuntu),可通过visualbox搭建虚拟机环境或者安装Linux双系统;
  • 软件准备
    • git 源码管理
    • konga,用于kong admin api管理的GUI WEB界面,可在测试插件功能时候使用
    • node & npm,安装konga所需的必要的工具
    • mysql,使用konga 需要使用的数据库
    • postgress,必须,运行Kong需要使用的数据库
    • pgAdmin4,postgres的GUI管理工具
    • vscode,Lua插件开发选用的IDE
    • ……
  • 知识准备
    • Kong、OpenResty & Nginx 等相关知识
    • Lua 语言基础

2.2 开始

2.2.1 获取Kong源码

从github上获取最新源码

smj@smj-ubuntu:~$  mkdir workspace
smj@smj-ubuntu:~$  cd workspace/
smj@smj-ubuntu:~/workspace$ git clone https://github.com/Kong/kong.git
正克隆到 'kong'...

Kong 源码文件包含内容如下:

2.2.2 准备IDE(VSCODE)

1 在vscode extends 搜索emmyLua插件直接安装,或者通过离线安装方式加载

2 配置EmmyLua插件,文件>>首选项>>设置,搜索emmylua设置JAVA_HOME选项,(settings.json)设置如下:

{"terminal.integrated.shell.linux": "/bin/bash","editor.mouseWheelZoom": true,"[lua]": {"editor.defaultFormatter": "trixnz.vscode-lua"},"terminal.explorerKind": "external","terminal.integrated.fontFamily": "monospace","emmylua.java.home":  "/opt/java/jdk1.8.0_181",
}

如果Linux系统无java环境,请先安装java环境,可参考Ubuntu安装java8

3 加载Kong源码文件,即可看到Lua文件的高亮的显示(编写Lua也会有相应的代码提示)

上述前置环境准备就绪,接下来就就正式进入我们的Lua插件开发啦~

2.3 Kong环境配置

If you are planning on developing on Kong, you’ll need a development installation. The next branch holds the latest unreleased source code. --from github-kong

本文主要以源码编译方式进行插件开发及验证,可参考官方文档源码编译指南的文档

拥有Linux开发环境(虚拟或裸机)后,还需要一些初始化工作,包括有(1)必要的软件包,包括编译器,工具和编译其他内容所需的库等:(2) OpenResty系统,包括Nginx,LuaJIT,PCRE等;(3)数据库,Kong使用Posgres,Cassandra和Redis。

2.3.1 获取相关依赖

以Ubuntu系统为例,使用root 或者sudo角色安装下列依赖(基本涵盖了所需的软件包):

$: apt-get update
$: apt-get install \automake \build-essential \curl \docker \docker-compose \git \libpcre3 \libyaml-dev \m4 \openssl \perl \procps \unzip \zlib1g-dev

获取OpenResty(暂时可忽略该步骤,本文不涉及)

 $:  git clone https://github.com/kong/openresty-build-tools$:  cd openresty-build-tools$: ./kong-ngx-build -p build \--openresty 1.15.8.2 \--openssl 1.1.1d \--luarocks 3.2.1 \--pcre 8.43

2.3.2 配置

注意:此处配置并非唯一确定的

根据不同的开发方式进行不同设置,本文是在源码基础上进行插件扩展开发,需要进行如下设置:
打开源码目录,需要修改2个文件:

  1. bin/kong
    修改首行 #!/usr/bin/env resty => #!/usr/local/openresty/bin/resty
    其中"/usr/local/openresty"为本机openresty实际安装路径 ,根据实际情况而定
  2. kong/templates/kong_defaults.lua
    第2行,prefix = /usr/local/kong/,表示kong安装目录,可选默认或自定义修改
    第10行,plugins后面添加自己即将定义的plugin名称
    如定义了hello-world插件,修改为plugins = bundled,hello-world,其中bundled 表示kong自带的开源插件

上述配置完成即可写自己的插件了,在 kong/plugins/目录下新建自定义插件,如hello-world

3自定义插件开发

开发自定义插件之前,需要了解下kong插件开发指南,详情点击官方指导文档

3.1 插件目录结构

所有的Kong插件都位于kong/plugins目录下, 如在plugins目录我们创建一个名为hello-world插件, 至少需要包含2个文件,如下所示:

plugins
├── hello-world
│   ├── handler.lua
│   └── schema.lua   # (必需)插件配置参数定义, 可加入自定义校验函数
└── other-plugin
  • handler.lua:插件的核心,包括请求/连接生命周期,提供接口来实现插件的运行逻辑;
  • schema.lua:配置参数定义,定义校验规则以便用户只能输入有效的配置值

完全版目录结构

hello-world
├── api.lua  #
├── daos.lua
├── handler.lua
├── migrations
│   ├── init.lua
│   └── 000_base_complete_plugin.lua
└── schema.lua
模块名称 必需 描述
api.lua 扩展Admin API,在需要对外暴露接口时候
daos.lua 数据访问层,对插件自定义实体的抽象,并存储在数据存储区中
handler.lua 对外暴露出在请求/连接生命周期的接口,由Kong实现逻辑并运行
migrations/*.lua 数据库迁移(例如,创建表),仅当插件应用daos.lua进行存储时才需要进行迁移
schema.lua 保留插件配置结构,以便用户只能输入有效的配置值

3.2 自定义逻辑编写

3.2.1 handler.lua 生命周期

Kong插件允许您在Kong代理的 request/response 或tcp stream 连接的生命周期中的几个入口点注入自定义逻辑(通过 Lua)。为此必须实现一个或多个base_plugin.lua 的方法接口,在kong.plugins.<plugin_name> .handler中实现。 Kong执行生命周期的各个入口点:

  • HTTP模块 用于为HTTP / HTTPS请求编写的插件
函数名 阶段 描述
:init_worker() init_worker 在每个 Nginx 工作进程启动时执行
:certificate() ssl_certificate 在SSL握手阶段的SSL证书服务阶段执行
:rewrite() rewrite 从客户端收到的每个请求作为重写阶段处理程序执行。在这个阶段,无论是Service 还是Customer都没有被识别,因此这个处理器只在插件被配置为全局插件时执行
:access() access 针对客户端的每个请求并在将其代理到上游服务之前执行
:header_filter() header_filter 当已从上游服务接收到所有响应头字节时执行
:body_filter() body_filter 对从上游服务接收到的响应主体的每个块执行。由于响应流回客户端,因此它可能超出缓冲区大小,并且逐块流式传输。因此,如果响应较大,则可以多次调用此方法
:log() log 当最后一个响应字节已经发送到客户端时执行
  • 流模块 用于为TCP流连接编写的插件
函数名 阶段 描述
:init_worker() init_worker 在每个 Nginx 工作进程启动时执行
:preread() preread 每个连接执行一次
:log() log 关闭每个连接后,对每个连接执行一次

3.2.2 handler.lua 文件规范

该handler.lua文件必须返回一个实现您希望执行的功能的表。为了简洁起见,这是一个注释示例模块,实现了两个模块的所有可用方法(请注意,其中一些在模块之间共享,例如log):

-- 扩展Base Plugin handler是可选的,因为Lua中没有真正的接口概念,
-- 但是Base Plugin handler的方法可以从子实现中调用,
-- 并将在“error.log”中打印日志(其中打印所有日志)。
local BasePlugin = require "kong.plugins.base_plugin"local CustomHandler = BasePlugin:extend()CustomHandler.VERSION  = "1.0.0"
--设置执行的优先级,Kong 将按照插件的优先级来确定其执行顺序(越大越优先)
CustomHandler.PRIORITY = 10-- 你插件handler的构造函数。
-- 如果要扩展Base Plugin handler,它的唯一作用就是用名称实例化自己。
-- 该名称是您的插件名称,同时它将打印在日志中function CustomHandler:new()CustomHandler.super.new(self, "my-custom-plugin")
endfunction CustomHandler:init_worker() -- 最终执行父实现 (并将记录您的插件正在进入此上下文)CustomHandler.super.init_worker(self)-- 实现任何自定义逻辑
endfunction CustomHandler:preread(config) CustomHandler.super.preread(self) -- Implement any custom logic here
endfunction CustomHandler:certificate(config) CustomHandler.super.certificate(self)   -- Implement any custom logic here
endfunction CustomHandler:rewrite(config) CustomHandler.super.rewrite(self)-- Implement any custom logic here
endfunction CustomHandler:access(config) CustomHandler.super.access(self) -- Implement any custom logic here
endfunction CustomHandler:header_filter(config) CustomHandler.super.header_filter(self) -- Implement any custom logic here
endfunction CustomHandler:body_filter(config) CustomHandler.super.body_filter(self) -- Implement any custom logic here
endfunction CustomHandler:log(config) CustomHandler.super.log(self) -- Implement any custom logic here
end-- 该模块需要返回创建的表以便让Kong 可以执行这些功能。
return CustomHandler

当然,插件本身的逻辑可以抽象到另一个模块中,并从处理程序模块调用。许多现有的插件在逻辑冗长时已经选择了这种模式。

3.2.3 schema.lua规范

Kong为您提供了一种验证用户插件配置的方法,它包含用户通过Admin API启用插件时将设置的键/值属性。该模块将返回具有属性的Lua表,该属性将定义用户以后如何配置插件。
此处不做过多说明,详情请参考schema.lua规范

4 举个栗子

为了了解kong插件开发,我们也需要了解kong的开发套件pdk,基于此我们实现一个函数,用来打印pdk中部分函数的输出,通过运行kong的插件拦截我们web http请求,打印文本内容输出到web浏览器,即:

  • 插件名:helloworld
  • 功能:打印pdk的部分函数输出
  • 选取执行阶段:access

4.1 插件代码部分

4.1.1 hello-world.handler.lua

-- hello-world.handlar.lua
local BasePlugin = require "kong.plugins.base_plugin"local CustomHandler = BasePlugin:extend()local resultAns = ">>插件开始运行了\n"CustomHandler.VERSION = "1.0.0"
CustomHandler.PRIORITY = 10function CustomHandler:new()CustomHandler.super.new(self, "hello-world")
end
function CustomHandler:access(config)CustomHandler.super.access(self)  resultAns = resultAns .. ">>>>>>>执行:access阶段开始\n输出嵌入的内容(请求在还未到达上游服务器):\n"resultAns = resultAns .. "kong.version:\t" .. kong.version .. "\n"resultAns = resultAns .. "kong.client.get_ip():\t" .. kong.client.get_ip() .. "\n" resultAns = resultAns .. "kong.request.get_scheme():\t" .. kong.request.get_scheme() .. "\n"resultAns = resultAns .. "kong.request.get_host():\t" .. kong.request.get_host() .. "\n"resultAns = resultAns .. "kong.request.get_port()\t:" .. kong.request.get_port() .. "\n"resultAns = resultAns .. "kong.request.get_http_version():\t" .. kong.request.get_http_version() .. "\n"resultAns = resultAns .. "kong.request.get_method():\t" .. kong.request.get_method() .. "\n"resultAns = resultAns .. "kong.request.get_path():\t" .. kong.request.get_path() .. "\n"resultAns = resultAns .. "<<<<<<<执行access阶段结束 \n" return kong.response.exit(200,resultAns,{["Content-Type"] = "application/json",["WWW-Authenticate"] = "Basic"})
end return CustomHandler

4.1.2 hello-world.schema.lua

--  hello-world.schema.lua
local typedefs = require "kong.db.schema.typedefs"
return {name = "hello-world",fields = {{consumer = typedefs.no_consumer},{config = {type = "record",fields = {-- 这里的username, 会显示在插件配置页{username = {type = "array",elements = {type = "string"},default = {}                            }}}}}}
}

4.1.3 安装并启动kong

上述插件编写完成后,需要安装并启动Kong软件,此处目前笔者已知有2种方式:

  1. 通过bin\kong start命令安装并启动Kong
    在kong源码目录运行终端:

    root@smj-ubuntu:/home/smj/workspace/kong# bin/kong start
    2019/11/12 18:51:01 [warn] ulimit is currently set to "1024". For better performance set it to at least "4096" using "ulimit -n"
    Kong started
    
  2. 通过luarocks make命令安装Kong
    root@smj-ubuntu:/home/smj/workspace/kong# luarocks make
    kong 1.4.0-0 is now installed in /usr/local (license: Apache 2.0)root@smj-ubuntu:/home/smj/workspace/kong# kong start
    2019/11/12 17:54:39 [warn] ulimit is currently set to "1024". For better performance set it to at least "4096" using "ulimit -n"
    Kong startedroot@smj-ubuntu:/home/smj/workspace/kong# kong stop
    Kong stopped
    
  3. 运行命令sudo netstat -tunlp | grep nginx 查看下kong的端口信息
    smj@smj-ubuntu:~$ sudo netstat -tunlp | grep nginx
    tcp        0      0 0.0.0.0:8443            0.0.0.0:*               LISTEN      6289/nginx: master
    tcp        0      0 127.0.0.1:8444          0.0.0.0:*               LISTEN      6289/nginx: master
    tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN      6289/nginx: master
    tcp        0      0 127.0.0.1:8001          0.0.0.0:*               LISTEN      6289/nginx: master
    

4.2 konga安装与使用(非必需)

kong admin api 对外暴露的端口为8001,可通过curl命令进行设置,
除此之外,还有可选择的管理界面konga,通过该工程可对kong进行可视化配置管理。
konga的安装较为简单,使用前需要具备一些条件:

  • nodejs >=8 ,推荐8.11.3 LTS(版本12在安装依赖时候可能会出现一些问题)
  • 推荐使用mysql数据库(还支持 postgresSQL, MongoDB)
  • 运行的kong版本>=1.0.0

4.2.1 konga源码安装

此处使用源码进行安装,在准备的工作目录执行:

$ git clone https://github.com/pantsel/konga.git
$ cd konga
$ npm i

4.2.2 mysql安装与配置

  1. mysql安装
    过程(略)……

  2. 检验是否安装:

    smj@smj-ubuntu:~$ mysqladmin --version
    mysqladmin  Ver 8.42 Distrib 5.7.27, for Linux on x86_64
    
  3. 登录并创建konga数据库:
    假设您已经设置了mysql的用户名(root)和密码 (123456)

    # 1 登录mysql
    smj@smj-ubuntu:~$ mysql -uroot -p
    Enter password:
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    (省略)……
    # 2 创建konga
    mysql> create database if  not exist konga charset utf8 column utf8_general_ci ;
    #  3 检查是否创建成功,若有konga ,表示创建成功
    mysql> show databases;
    

4.2.3 konga配置

完成依赖包和数据库的安装后, 需要配置一下.env 中关于数据库连接的配置
在源码目录执行如下命令:

## 进入源码目录
cd ~/workspace/konga
cp .env_example .envvim .env
## 修改为如下设置
PORT=1337
NODE_ENV=production
KONGA_HOOK_TIMEOUT=120000
DB_ADAPTER=mysql
DB_URI=mysql://localhost:3306/konga
DB_USER=root
DB_PASSWORD=123456
KONGA_LOG_LEVEL=warn
TOKEN_SECRET=some_secret_token## 执行下面的语句 创建数据库的表
node ./bin/konga.js  prepare --adapter mysql --uri mysql://localhost:3306/konga## 启动服务
npm start

4.2.4 konga运行

  1. 在浏览器键入地址:http://localhost:1337
    注册登录用户,显示如下:

  2. 设置kong admin api监控路径:
    选择 connections进行添加

  3. 展示连接的kong配置项:
    其中自定义插件hello-world已经显示在上面

接下来我们就可以通过konga进行kong的配置咧,并且可以据此验证我们自定义插件的效果~

4.3 测试验证

4.3.1 配置 SERVICES (服务)/ROUTES(路由)/ PLUGINS(插件)

  1. 设置service选项,其余可选默认配置:
    http://localhost:8000/
  2. 在创建的service选项,添加route配置选项:
    路径:"/index"
  3. 在创建的service选项或route选项页面,添加plugin设置:

    按照上述配置完毕后,即可进行功能的测试验证了

4.3.2 通过浏览器或 curl请求进行功能验证

  • 在浏览器键入路径: http://localhost:8000/index ,返回body内容如下:

    >>插件开始运行了
    >>>>>>>执行:access阶段开始
    输出嵌入的内容(请求在还未到达上游服务器):
    kong.version:    1.4.0
    kong.client.get_ip():    127.0.0.1
    kong.request.get_scheme():   http
    kong.request.get_host(): localhost
    kong.request.get_port() :8000
    kong.request.get_http_version(): 1.1
    kong.request.get_method():   GET
    kong.request.get_path(): /index
    <<<<<<<执行access阶段结束
    
  • 通过curl命令:curl -i http://localhost:8000/index

  • 如此可见,kong插件成功拦截到了我们配置的url请求,能够正常拦截切输出我们预期的结果,则可说明嵌入的lua脚本(插件)生效。

可通过该流程进行插件的开发测试

5 参考资料

  1. Kong开发工具: https://github.com/Kong/kong-build-tools#developing-kong
  2. kong源码文档:https://github.com/Kong/kong#development
  3. 官方插件开发指南: https://docs.konghq.com/1.4.x/plugin-development/
  4. 官方源码编译指南:https://docs.konghq.com/install/source/
  5. Kong源码导读:https://blog.csdn.net/aa1215018028/article/details/81297724
  6. kong专题目录:https://www.jianshu.com/p/fe6b99756669
  7. kong 网关教程入门:https://blog.csdn.net/luanpeng825485697/article/details/85287291
  8. Kong初探 (插件开发以及使用):http://www.102no.com/archives/1338
  9. API网关Kong-Docker &安装:https://www.ucloud.cn/yun/40529.html

说明

kong开发环境搭建方式多种,文中只介绍了自己使用的方式。
如有疏漏,烦请指正~

kong插件开发-完全版相关推荐

  1. Kong插件开发向导

    转载 李亚飞 大佬的文章:https://www.lyafei.com/ 简介 前面洋洋洒洒写了那么多文章,Kong搭建.Konga搭建.Kong插件开发工具包.Lua算法实现等等,就为了这篇Kong ...

  2. kong组件_Kong插件开发工具包

    Kong插件开发工具包 插件开发工具包(或称 PDK),是一组 Lua 方法和变量,插件可以使用这些方法和变量实现自己的逻辑,PDK 最初在 Kong 0.14.0 中发布,PDK 保证从1.0.0版 ...

  3. [云框架]KONG API Gateway v1.5 -框架说明、快速部署、插件开发

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 当前版本采用KONGv0.12.3 当我们决定对应用进行微服务改造时,应用客户端如何与微服务交互的问 ...

  4. 一次kong概念验证之旅

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 0. 本地k8s 环境搭建(minikube) 1. kong及 kong ingress controller 配置 ...

  5. Kong(三)Konga UI安装和使用

    一   konga 的github地址 konga安装参考 ①  Kong 可视化UI 选择 +++++++++++++++ '官方kong-dashboard' +++++++++++++++1)收 ...

  6. 使用Kong和Konga管理微服务和API

    Kong是Mashape开源的高性能高可用API网关和API服务管理层.自2015年在github开源后,广泛受到关注.它基于OpenResty,进行API管理,并提供了插件实现API的AOP.Kon ...

  7. 高性能API网关Kong介绍

    本文关键词:高性能.API网关.Kong.微服务​​​​​​​ 1.Introduction API网关是随着微服务(Microservice)概念兴起的一种架构模式.原本一个庞大的单体应用(All ...

  8. Kong实现禁止国外IP访问

    一.需求背景 最近公司观察到某些国外IP或者非中国大陆IP有扫描访问记录,出于业务安全考虑,公司的业务只对中国大陆进行开展,所以需要禁止国外IP访问,增加系统安全性.同时也避免某些黑产通过国外代理IP ...

  9. 【书籍】C++经典教程

    [书籍]C++经典教程     要下载请登录通了电123课件站(http://www.told123.cn)计科里面进行下载或者直接在通了电进行搜索[推荐]. [书籍]C++经典教程 [书籍]C++编 ...

最新文章

  1. Ubuntu 16.04设置Redis为开机自动启动服务
  2. java web shiro_javase和javaweb环境下shiro的搭建
  3. hadoop学习-mahout-Bayes分类算法示例程序
  4. icem密度盒怎么设置_seo中关键词密度的问题
  5. VTK:PolyData之GreedyTerrainDecimation
  6. 电影推荐_亲和性分析_规则提取(数据挖掘入门与实践-实验6)
  7. 本周的比特币现金市场和商家支持
  8. ORACLE 多表关联 UPDATE 语句
  9. linux下安装mysql5.5_Linux下安装mysql-5.5
  10. Python Tricks(三)—— 计算误分率
  11. 五种常用源代码开源协议
  12. 矩阵标准型的系数是特征值吗_21、二次型、合同关系、惯性指数、标准型、规范型,XTAX...
  13. excel之天数转年月日
  14. html显示doc内容,doc文件怎么打开?doc是什么文件?
  15. BJDCTF_2nd PWN复盘
  16. 敏捷软件开发scrum介绍
  17. 微信小程序中如何将数据保存到内存中并且读取的同步写法
  18. 罐子与硬币--【英雄会】
  19. php 删除特殊符号,利用PHP删除特殊符号
  20. primocache学生党常用场景设置

热门文章

  1. RStudio安装xlsx包
  2. android胎心监测设计,胎心监测
  3. 我 stormzhang 来报道了!
  4. 在Idea解决找不到sun.misc.BASE64Encoder及sun.misc.BASE64Decoder找不到包
  5. Vue笔记随笔---kalrry
  6. 阿里云服务器远程连接和v2ray
  7. 时间分割算法,Java将一段时间按星期来分割
  8. mysql5_7winx64,MySQL 5.7.30 Winx64 安装
  9. 微信小程序picket绑定数组对象
  10. 中层管理者如何做好员工管理