对接华泰极速行情丨DolphinDB INSIGHT 插件使用教程

INSIGHT 是华泰证券依托大数据存储、实时分析等领域的技术积累,整合接入国内多家交易所高频行情数据,为投资者提供集行情接入、推送、回测、计算及分析等功能于一体的行情数据服务解决方案。基于 INSIGHT 官方提供的行情数据服务 C++ SDK(TCP 版本),DolphinDB 开发了能够获取市场行情数据的 INSIGHT 插件,帮助用户方便地通过 DolphinDB 脚本语言将实时行情数据接入 DolphinDB 进程中以便进行后续的计算或存储

本文主要介绍如何通过 INSIGHT 插件将实时行情数据写入分布式数据库,以及如何实现节点启动时自动订阅 INSIGHT 实时行情。本文全部代码需要运行在 2.00.11 或者更高版本的 DolphinDB server 以及插件上,目前仅支持 Linux 系统。

1. DolphinDB INSIGHT 行情插件介绍

INSIGHT 插件的接口介绍见 DolphinDB INSIGHT Plugin 使用说明,注意, INSIGHT 插件基于 INSIGHT 官方提供的行情数据服务 C++ SDK(即 TCP 版本 INSIGHT)实现。若您的 INSIGHT 订阅账号对应 C++ UDP SDK,本文提到的 2.00.11 版本插件将无法支持,可以联系 DolphinDB 技术支持以进一步了解。

INSIGHT 插件最核心的功能是实现了INSIGHT C++ SDK 中的行情回调函数,每次接收到行情时会写入对应的 DolphinDB 内存表,DolphinDB INSIGHT 插件目前已经支持的数据源包括:

Level-2 快照逐笔成交逐笔委托逐笔成交和委托
股票
指数
期货
基金

注:逐笔成交和委托类型是为了对接 DolphinDB 快照合成流计算引擎的特殊处理,指将逐笔成交和逐笔委托处理为同构数据写入一张 DolphinDB 表中。(可联系 DolphinDB 技术支持以进一步了解)

2. 基本使用介绍

2.1 安装插件

节点启动后,连接节点并在 GUI(或 VS Code、Web UI)等DolphinDB客户端中执行 installPlugin 函数,则可以下载到与当前 server 版本适配的 INSIGHT 插件文件,插件文件包括插件描述文件及插件的二进制文件。

login("admin", "123456")
installPlugin("insight")

installPlugin 函数若正常返回,则代表下载成功,其返回值为插件描述文件(PluginInsight.txt)的安装路径,如:

/path_to_dolphindb_server/server/plugins/insight/PluginInsight.txt

installPlugin 函数实际上是完成从远程文件服务器拉取插件文件到 DolphinDB server 所在的服务器,因此需要一定的耗时,请耐心等待大约一分钟。

2.2 加载插件

在脚本中调用插件相关的接口前,需要先加载插件。在 GUI(或 VS Code、Web UI)等客户端中执行 loadPlugin 函数加载插件。以下示例中使用了相对路径,也可以试用 2.1 中返回的绝对路径 /path_to_dolphindb_server/server/plugins/insight/PluginInsight.txt

loadPlugin("./plugins/insight/PluginInsight.txt")

loadPlugin 函数正常返回则插件加载成功,以 VS Code 为例,首次加载成功后返回的部分信息如下,返回值是 INSIGHT 插件提供的所有函数,至此插件安装与加载已全部完成:

此外,需要注意,如果重复执行 loadPlugin 加载插件,会抛出模块已经被使用的错误提示,因为节点启动后,只允许加载一次 INSIGHT 插件,即可在任意会话中调用该插件提供的函数。错误提示如下:

The module [insight] is already in use.

可以通过 try-cach 语句捕获这个错误,避免因为插件已加载而中断后续脚本代码的执行:

try{ loadPlugin("./plugins/insight/PluginInsight.txt") }catch(ex){print ex}

此外,若节点重启则需要重新加载插件。

3. 通过 INSIGHT 行情插件将实时行情数据写入分布式数据库

本章以订阅沪深两市的全市场股票的逐笔数据、实时写入 DolphinDB 分布式数据库为例,对 INSIGHT 插件的使用进行说明,大致的流程如下:

  • 通过 INSIGHT 插件订阅逐笔数据写入 DolphinDB transactionTable 和 orderTable 两个持久化流数据表。持久化流数据表是具备发布订阅功能的内存表。
  • 订阅持久化流数据表写入 DolphinDB 分布式数据库。分布式数据库是将数据存储到磁盘上。

注意:请勿使用 INSIGHT 插件将行情数据直接写入分布式数据库。因为分布式数据库并不适用于此类高频的流式写入。建议在使用时,借助流数据表及其发布订阅功能以实现微批处理。这样既可以提高写入的吞吐,也有助于降低时延。

下面分步骤介绍关键的 DolphinDB 代码实现,完整脚本见附录。

3.1 清理环境(可选)

为保证本文的示例脚本能够反复执行,特提供了以下流环境清理脚本。

由于相同的流数据表名和订阅无法进行重复定义,因此先取消相关订阅并清除需要用到的流数据表。

try {
	tcpClient  = insight::getHandle()
	insight::unsubscribe(tcpClient) 
	insight::close(tcpClient) 
} catch(ex) { print(ex) }
try { unsubscribeTable(tableName="transactionTable", actionName="transactionTableInsert") } catch(ex) { print(ex) }
try { unsubscribeTable(tableName="orderTable", actionName="orderTableInsert") } catch(ex) { print(ex) }
try { dropStreamTable(tableName="transactionTable") } catch(ex) { print(ex) }
try { dropStreamTable(tableName="orderTable") } catch(ex) { print(ex) }
undef all

3.2 创建库表

执行创建分布式库表的语句前,需要登陆有创建权限的账号。执行如下代码登录默认的管理员账号:

login("admin", "123456")

获取表结构

调用 insight::getSchema 方法可以获取行情数据各个表的表结构。以下代码获取股票逐笔成交和逐笔委托两张表的表结构:

// 股票逐笔成交
transactionSchema = insight::getSchema(`StockTransaction); 
//股票逐笔委托
orderSchema = insight::getSchema(`StockOrder); 

创建持久化流数据表

得到行情数据的表结构后,使用该表结构创建持久化流数据表。

// 建立用于insight行情接入的持久化流表
cacheSize = 1000000
transactionColName = transactionSchema[`name]
transactionColType = transactionSchema[`type]
orderColName = orderSchema[`name]
orderColType = orderSchema[`type]

enableTableShareAndPersistence(table=streamTable(cacheSize:0, transactionColName, transactionColType), tableName=`transactionTable, cacheSize=cacheSize)
enableTableShareAndPersistence(table=streamTable(cacheSize:0, orderColName, orderColType), tableName=`orderTable, cacheSize=cacheSize)
  • 为保证 enableTableShareAndPersistence 函数能够正常执行,需要节点启动之前在配置文件中(单节点:dolohindb.cfg,集群:cluster.cfg)指定配置参数 persistenceDir ,配置参考功能配置。
  • 代码第二行的 cacheSize 变量控制了在建表时预分配内存的大小、以及流数据表可占用的最大内存,其单位是行,设置较大的 cacheSize 可以降低出现峰值时延的频率。具体大小可以根据实际的可使用的内存大小决定。具体优化原理可参考 流计算时延统计与性能优化

创建分布式数据库

为将行情数据存入分布式数据库,需要根据之前得到的行情数据表结构来创建分布式库表,分区规则参考自《基于 DolphinDB 存储金融数据的分区方案最佳实践》。

dbName = "dfs://Stock_TB"
transactionTbName = "transactionTable"
orderTbName = "orderTable"
dbDate = database(, partitionType=VALUE, partitionScheme=2023.01.01..2024.01.01)
dbID = database(, partitionType=HASH, partitionScheme=[SYMBOL, 25])
db = database(directory=dbName, partitionType=COMPO, partitionScheme=[dbDate, dbID],engine='TSDB',atomic='CHUNK')

tbSchema = table(1:0, transactionColName, transactionColType)
db.createPartitionedTable(table=tbSchema,tableName=transactionTbName,partitionColumns=`MDDate`HTSCSecurityID,sortColumns=`HTSCSecurityID`MDTime)	

tbSchema = table(1:0, orderColName, orderColType)
db.createPartitionedTable(table=tbSchema,tableName=orderTbName,partitionColumns=`MDDate`HTSCSecurityID,sortColumns=`HTSCSecurityID`MDTime)	

3.3 订阅流数据表把增量数据实时写入分布式数据库

订阅 3.2 节中的两个持久化流数据表,将增量数据实时写入分布式数据库。

Transaction = loadTable(database=dbName, tableName=transactionTbName)
Order = loadTable(database=dbName, tableName=orderTbName)

subscribeTable(tableName="transactionTable", actionName="transactionTableInsert", offset=-1, handler=tableInsert{Transaction}, msgAsTable=true, batchSize=20000, throttle=1, reconnect=true)
subscribeTable(tableName="orderTable", actionName="orderTableInsert", offset=-1, handler=tableInsert{Order}, msgAsTable=true, batchSize=20000, throttle=1, reconnect=true)
  • 通过调整 subscribeTable 函数中的 batchSize 和 throttle 参数可以控制写入分布式数据库的频率。
    • batchSize=20000 表示当未处理消息的数量达到 20000 时,handler 才会处理消息。
    • throttle=1 表示继上次 handler 处理消息之后,若未处理消息的数量还没有达到 20000 ,但是时间间隔 1s 后也会处理消息。
    • 因此,达到 batchSize 设置的条件或者达到 throttle 设置的条件,才会向分布式数据库写入一次。

3.4 订阅 INSIGHT 行情将增量数据实时写入流数据表

建立 INSIGHT 连接

用户配置 INSIGHT 账户信息,使用 insight::connect 函数进行连接,handles 用于设置接收行情数据的流数据表,下例用流数据表 transactionTable 接收逐笔成交(字典的 key 为 Transaction 表示了逐笔成交)。

// 配置账户信息
HOST = "111.111.111.111";
PORT = 111;
USER = "111";
PASSWORD = "111";

handles = dict(['Transaction', 'Order'], [transactionTable, orderTable]);
tcpClient= insight::connect(handles,HOST, PORT, USER, PASSWORD,,,true);

订阅行情数据

使用 insight::subscribe 函数进行 INSIGHT 行情订阅,行情数据将进入流数据表。

// 深交所股票数据
insight::subscribe(tcpClient, `MD_TRANSACTION`MD_ORDER, `XSHE, `StockType)  
// 上交所股票数据
insight::subscribe(tcpClient, `MD_TRANSACTION`MD_ORDER, `XSHG, `StockType)  

3.5 查询 INSIGHT 行情接收情况

运行过程中,可以查看 INSIGHT 行情的接收情况。首先调用 insight::getHandle 函数获取连接句柄,再使用 insight::getStatus 查询 INSIGHT 行情的接收情况。

tcpClient = insight::getHandle()
insight::getStatus(tcpClient)

返回结果如下,本例在 16:26 (见 startTime 字段) 提交了 INSIGHT 订阅,订阅了逐笔成交和逐笔委托(见 startTime 不为空的 topicType 字段),订阅的是沪深两市的股票数据(见 market 字段)。但是由于已经是盘后了,所以实际上并没有逐笔数据发送过来,因此 firstMsgTime 为空,firstMsgTime 表示收到第一条数据的系统时刻。

当在盘中启动时,可以看到 firstMsgTime 与 lastMsgTime 均不为空,lastMsgTime 表示收到最后一条数据的系统时刻。

4. 节点启动时自动订阅 INSIGHT 实时行情数据入库

DolphinDB 系统的启动流程如下图所示:

  • 系统初始化脚本(dolphindb.dos


系统初始化脚本是必需的,默认加载版本发布目录中的 dolphindb.dos。不建议做修改,因为版本升级的时候需要用新版本发布包中的系统初始化脚本覆盖。

  • 用户启动脚本(startup.dos


用户启动脚本是通过配置参数 startup 后才会执行,单节点模式在 dolphindb.cfg 中配置,集群模式在 cluster.cfg 中配置,可配置绝对路径或相对路径。若配置了相对路径或者没有指定目录,系统会依次搜索本地节点的 home 目录、工作目录和可执行文件所在目录。


配置举例如下:

startup=/DolphinDB/server/startup.dos

将上述业务代码添加到 /DolphinDB/server 目录的 startup.dos 文件中,并在对应的配置文件中配置参数 startup,即可完成节点启动时的自动订阅部署。

  • 定时任务脚本(postStart.dos


DolphinDB 中通过 scheduleJob 函数定义的定时任务会进行持久化。所以在重新启动节点时,系统先执行用户启动脚本,然后在初始化定时任务模块时完成持久化定时任务的加载。在完成上述步骤后,系统会执行定时任务脚本,此时用户可以在定时任务脚本中调用 scheduleJob 函数定义新的定时任务。


本教程中未使用该功能,所以不需要开启该配置项。1.30.15 和 2.00.3 版本开始支持配置 postStart.dos 实现节点启动自动执行定时任务脚本。

注意

  • INSIGHT 的账户信息需要根据实际环境进行修改。

附录

  • 详细启动脚本配置可以参考官网文档教程:启动脚本教程。
  • 关于节点启动时自动订阅处理业务的部署可以参考官网文档教程:节点启动时的流计算自动订阅教程。
  • startup.dos 启动脚本(账户信息需要根据用户实际情况进行修改)。
// 加载插件
login("admin", "123456")
try{ loadPlugin("./plugins/insight/PluginInsight.txt") }catch(ex){print ex}

// 清理环境
def cleanEnvironment(){
	try {
		tcpClient  = insight::getHandle()
		insight::unsubscribe(tcpClient) 
		insight::close(tcpClient) 
	} catch(ex) { print(ex) }
	try { unsubscribeTable(tableName="transactionTable", actionName="transactionTableInsert") } catch(ex) { print(ex) }
	try { unsubscribeTable(tableName="orderTable", actionName="orderTableInsert") } catch(ex) { print(ex) }
	try { dropStreamTable(tableName="transactionTable") } catch(ex) { print(ex) }
	try { dropStreamTable(tableName="orderTable") } catch(ex) { print(ex) }
	undef all
}

// 创建用于 INSIGHT 行情接入的持久化流数据表
def createStreamTable() {
	cacheSize = 1000000
	transactionSchema = insight::getSchema(`StockTransaction);
	orderSchema = insight::getSchema(`StockOrder);
	transactionColName = transactionSchema[`name]
	transactionColType = transactionSchema[`type]
	orderColName = orderSchema[`name]
	orderColType = orderSchema[`type]
	enableTableShareAndPersistence(table=streamTable(cacheSize:0, transactionColName, transactionColType), tableName=`transactionTable, cacheSize=cacheSize)
	enableTableShareAndPersistence(table=streamTable(cacheSize:0, orderColName, orderColType), tableName=`orderTable, cacheSize=cacheSize)
}

// 创建存储行情数据的分布式数据库表
def createDFSTable(dbName, transactionTbName, orderTbName) {
	transactionSchema = insight::getSchema(`StockTransaction);
	orderSchema = insight::getSchema(`StockOrder);
	transactionColName = transactionSchema[`name]
	transactionColType = transactionSchema[`type]
	orderColName = orderSchema[`name]
	orderColType = orderSchema[`type]
	if(!existsDatabase(dbName)) {
		dbDate = database(, partitionType=VALUE, partitionScheme=2023.01.01..2024.01.01)
		dbID = database(, partitionType=HASH, partitionScheme=[SYMBOL, 25])
		db = database(directory=dbName, partitionType=COMPO, partitionScheme=[dbDate, dbID],engine='TSDB',atomic='CHUNK')
	}
	if(!existsTable(dbName, transactionTbName)) {
		db = database(dbName)
		tbSchema = table(1:0, transactionColName, transactionColType)
		db.createPartitionedTable(table=tbSchema,tableName=transactionTbName,partitionColumns=`MDDate`HTSCSecurityID,sortColumns=`HTSCSecurityID`MDTime)	
	}
	if(!existsTable(dbName, orderTbName)) {
		db = database(dbName)
		tbSchema = table(1:0, orderColName, orderColType)
		db.createPartitionedTable(table=tbSchema,tableName=orderTbName,partitionColumns=`MDDate`HTSCSecurityID,sortColumns=`HTSCSecurityID`MDTime)	
	}
}

// 订阅流数据表把增量数据实时写入分布式数据库
def saveToDFSTable(dbName, transactionTbName, orderTbName) {
	Transaction = loadTable(database=dbName, tableName=transactionTbName)
	Order = loadTable(database=dbName, tableName=orderTbName)
	subscribeTable(tableName="transactionTable", actionName="transactionTableInsert", offset=-1, handler=tableInsert{Transaction}, msgAsTable=true, batchSize=20000, throttle=1, reconnect=true)
	subscribeTable(tableName="orderTable", actionName="orderTableInsert", offset=-1, handler=tableInsert{Transaction}, msgAsTable=true, batchSize=20000, throttle=1, reconnect=true)
}

// 订阅 INSIGHT 行情将增量数据实时写入流数据表
def connectToInsight(ip, port, user, password){
	// 建立 INSIGHT 连接
	handles = dict(['Transaction', 'Order'], [objByName(`transactionTable), objByName(`orderTable)])
	tcpClient= insight::connect(handles, ip, port, user, password,,,true)
	// 订阅深交所股票逐笔成交、逐笔委托
	insight::subscribe(tcpClient, `MD_TRANSACTION`MD_ORDER, `XSHE, `StockType)  
	// 订阅上交所股票逐笔成交、逐笔委托
	insight::subscribe(tcpClient, `MD_TRANSACTION`MD_ORDER, `XSHG, `StockType)  
}

// 配置账户信息。注意!账户信息必须根据用户实际情况进行修改
host = "111.111.111.111"
port = 111
user = "111"
password = "111"

// 配置数据库表名
dbName = "dfs://Stock_TB"
transactionTbName = "transactionTable"
orderTbName = "orderTable"

cleanEnvironment()
createStreamTable()
createDFSTable(dbName, transactionTbName, orderTbName) 
saveToDFSTable(dbName, transactionTbName, orderTbName)
connectToInsight(ip, port, user, password)
writeLog("Subsribe to insight market data successfully!")

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【对比】Gemini:听说GPT-4你小子挺厉害

前言 🍊缘由 谷歌连放大招:Gemini Pro支持中文,Bard学会画画 🏀事情起因: 一心只读圣贤书的狗哥,不经意间被新闻吸引。【谷歌最新人工智能模型Gemini Pro已在欧洲上市 将与ChatGPT竞争】, 平时玩弄ChatGPT-4很熟练了…

[c/c++] 结构体对齐

在 c 语言中,结构体的大小并不是结构体每个成员的大小之和,结构体的大小往往比结构体的成员大小之和要大。如下结构体,每个成员的大小分别是 1、4、1,但是结构体的大小却不是 6,而是 8。 struct Test { char a; int b;…

怎么将pom在文件放到src下方

今天在IDEA从git拉取项目的时候,发现pom.xml文件在文件夹src的上方,平时看惯了项目的pom.xml文件在文件夹src的下方,应该怎么去设置呢? 点击设置——>点击Folder Always on Top 即可 参考:http://t.csdnimg.cn/s34…

淘宝买家卖家ERP API(添加购物车、上下架商品、订单)

custom-自定义API操作 taobao.custom 调用地址 公共参数 名称类型必须描述keyString是调用key(必须以GET方式拼接在URL中)secretString是调用密钥api_nameString是API接口名称(包括在请求地址中)[item_search,item_get,item_se…

【JavaEE进阶】部署Web项目到Linux服务器

文章目录 🍃前言🍀什么是部署🌲环境配置🚩数据准备🚩程序配置⽂件修改 🎄构建项目并打包🎋上传Jar包到服务器,并运行🚩上传Jar包🚩运行程序🚩开放端口号 &…

HotFix原理学习 IL2CPP 学习

原文链接:Unity 游戏用XLua的HotFix实现热更原理揭秘-CSDN博客 本文通过对XLua的HoxFix使用原理的研究揭示出来这样的一套方法。这个方法的 第一步:通过对C#的类与函数设置Hotfix标签。来标识需要支持热更的类和函数。第二步:生成函数连接器…

2024年【焊工(初级)】考试题及焊工(初级)考试资料

题库来源:安全生产模拟考试一点通公众号小程序 焊工(初级)考试题是安全生产模拟考试一点通生成的,焊工(初级)证模拟考试题库是根据焊工(初级)最新版教材汇编出焊工(初级…

XM外汇平台自行扣除客户账户资金,理由荒谬且无据!

小编在FX110网多年,也算是“见多识广”了,可虽说是见惯了平台的“骚操作”,但对于XM平台这一次的行径,还是挺震惊的,只能说平台方多少有点无赖了! 事故源于一位XM用户的一次出金,发现莫名其妙被…

LeetCode每日一题之 复写0

目录 题目介绍: 算法原理: 特殊位置处理: 代码实现: 题目介绍: 题目链接:. - 力扣(LeetCode) 算法原理: 这种对数组元素进行修改,移动的题目我们仍然可以…

LeetCode-02

225. 用队列实现栈 用两个队列实现栈的功能,思路如下: 往空队列中放新元素把非空队列中的元素依次放入刚才添加了新元素的队列,直到非空队列变为空队列 class MyStack(object):def __init__(self):self.queue1 []self.queue2 []def push(…

台式电脑电源各线的电压和电流输出和输出电流

台式电脑电源是电脑硬件的重要组成部分。 它为计算机的各个部件提供所需的电压和电流。 不同的硬件设备和组件有不同的电压和电流输出。 下面详细介绍台式电脑电源各线的电压,包括3.3V、5V、12V、-12V、-5V和5VSB,以及它们的输出电流和用途。 3.3V&#…

命名实体识别NER(综合代码示例)

一、命名实体识别发展方向 二、中文数据集 CCKS2017开放的中文的电子病例测评相关的数据。 评测任务一:https://biendata.com/competition/CCKS2017_1/ 评测任务二:https://biendata.com/competition/CCKS2017_2/ CCKS2018开放的音乐领域的实体识别任务…

大唐杯学习笔记:Day4

1.1NR帧结构 5G NR中,依然采用一帧10ms,并将一帧分为10子帧,每个子帧为1ms。每个子帧包含几个时隙(slot),每个时隙由14个OFDM符号构成(在常规CP下)。 μ \mu μ Δ f 2 μ ∗ 15 [ K H Z ] \Delta f2^{\mu}*15[KHZ] Δf2μ∗15[KHZ]Cyclic prefix015Normal130Normal260Normal…

【鸿蒙 HarmonyOS 4.0】应用状态:LocalStorage/AppStorage/PersistentStorage

一、介绍 如果要实现应用级的,或者多个页面的状态数据共享,就需要用到应用级别的状态管理的概念。 LocalStorage:页面级UI状态存储,通常用于UIAbility内、页面间的状态共享。AppStorage:特殊的单例LocalStorage对象&…

jxls——自定义命令设置动态行高

文章目录 前言依赖引入绘制 jxls 批注的 excel 模板测试类编写自定义命令关于自动换行 前言 之前的博客中都简单说了数据的渲染和导出excel文件。包括固定的 表头结构,以及动态 表头和表数据等方式。 本篇博客主要说明自定义命令的方式,控制输出excel文…

bert 相似度任务训练简单版本,faiss 寻找相似 topk

目录 任务 代码 train.py predit.py faiss 最相似的 topk 数 任务 使用 bert-base-chinese 训练相似度任务,参考:微调BERT模型实现相似性判断 - 知乎 参考他上面代码,他使用的是 BertForNextSentencePrediction 模型,Bert…

固定资产管理系统包括哪些

固定资产管理是企业经营过程中一项非常重要的任务。它涉及到公司的核心资产,包括土地、建筑物、设备、车辆等。为了有效地管理这些资产,许多企业选择使用固定资产管理系统。那么,固定资产管理系统的内容是什么呢?本文将为您进行全…

O2OA(翱途)通过服务来调用接口实现单点登录案例

本文介绍O2OA服务管理中,接口的权限设定和调用方式。 创建接口 具有服务管理设计权限的用户(具有ServiceManager角色或Manager角色)打开“服务管理平台”,进入接口配置视图,点击左上角的新建按钮,可创建一…

webpack基础配置及使用

webpack是什么 是一个现代 JavaScript 应用程序的静态模块打包器。当webpack 处理应用程序时,它会递归地构建一个依赖关系图 ,其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle 。主要有 五个核心概念&#xff1a…

11. Nginx进阶-HTTPS

简介 基本概述 SSL SSL是安全套接层。 主要用于认证用户和服务器,确保数据发送到正确的客户机和服务器上。 SSL可以加密数据,防止数据中途被窃取。 SSL也可以维护数据的完整性,确保数据在传输过程中不被改变。 HTTPS HTTPS就是基于SSL来…