v-rep--websocket接口

websocket是什么

V-REP 中的 Web Socket 是一种用于在 V-REP 和外部应用程序之间进行通信的协议和技术。Web Socket 基于 TCP 连接,可以提供双向、实时的数据传输,适用于互动性或实时交互性应用。

(比如v-rep在云服务器上运行,通过websocket和用户所使用的web前端通信)


什么是云仿真

就是将v-rep的仿真程序发送到云服务器上,借助云服务器更好的硬件设备更高效地运行v-rep程序,用户可以从云服务器上获取需要的v-rep数据。

使用云仿真是将 V-REP 的仿真环境迁移到云端,让 V-REP 在云服务器上进行运行,用户通过互联网,通过浏览器等远程接入云端的 V-REP环境来完成仿真操作。因此,使用云仿真不需要将 V-REP 的程序发送到云服务器上运行,而是将 V-REP 的仿真环境放到云端进行运行,用户可以通过互联网访问云端的 V-REP 环境,进行仿真任务,而不需要在本地计算机上安装和配置 V-REP 软件。
 

什么是云端

云端(Cloud)指的是互联网上的远程服务器,也被成为“云服务器”,是封装计算资源的虚拟化环境。云端提供了一个集中式的存储、管理和运行数据和应用程序的平台,用户可以通过互联网访问这些数据和应用程序。

《互联网上用于管理,存储,运行数据的服务器》

websocket在v-rep中的作用

完成云服务器上v-rep仿真和web浏览器之间的通信。

websocket的实现

v-rep内部websocket实现(服务端)

wsRemoteAPI

源码链接

sim = require 'sim'
removeLazyLoaders()wsRemoteApi = {}
//获取wsRemoteApi.verbose这个v-rep全局参数的值,无值返回0
function wsRemoteApi.verbose()return sim.getNamedInt32Param('wsRemoteApi.verbose') or 0
endfunction wsRemoteApi.require(name)_G[name] = require(name)
endfunction wsRemoteApi.info(obj)if type(obj) == 'string' then obj = wsRemoteApi.getField(obj) endif type(obj) ~= 'table' then return obj end
//~=  :表示不等于local ret = {}for k, v in pairs(obj) doif type(v) == 'table' thenret[k] = wsRemoteApi.info(v)elseif type(v) == 'function' thenret[k] = {func = {}}elseif type(v) ~= 'function' thenret[k] = {const = v}endendreturn ret
end
/*
该函数接受一个字符串类型的参数 `f`,表示要获取的值的键。在 Lua 语言中,字符串类似于表中的字段名,可以作为表索引来访问对应的值。例如,`_G['print']` 可以获取 Lua 语言中的 `print` 函数。在函数体内部,首先将 `_G` 赋值给变量 `v`,表示从全局变量表开始查找。然后通过 `string.gmatch` 函数循环遍历字符串类型的键 `f` 中所有的单词和下划线,以及它们出现的顺序。在每次循环中,根据单词获取表 `v` 中对应的值,并将其赋值给变量 `v`。如果在遍历的过程中遇到了 `v` 为空(`nil`)的情况,则说明字符串类型的键在 `_G` 全局变量表中不存在,于是返回 `nil`。最后返回变量 `v`,表示找到了对应的值,并将其返回。
*/
//获取key(f)对应的value
function wsRemoteApi.getField(f)local v = _Gfor w in string.gmatch(f, '[%w_]+') dov = v[w]if not v then return nil endendreturn v
endfunction wsRemoteApi.handleRequest(req)if wsRemoteApi.verbose() > 1 then print('request received:', req) endlocal resp = {}resp['id'] = req['id']if req['func'] ~= nil and req['func'] ~= '' thenlocal func = wsRemoteApi.getField(req['func'])local args = req['args'] or {}if not func thenresp['error'] = 'No such function: ' .. req['func']elselocal status, retvals = pcall(function()local ret = {func(unpack(args))}return retend)resp[status and 'ret' or 'error'] = retvalsendelseif req['eval'] ~= nil and req['eval'] ~= '' thenlocal status, retvals = pcall(function()local ret = {loadstring('return ' .. req['eval'])()}return retend)resp[status and 'ret' or 'error'] = retvalsendresp['success'] = resp['error'] == nilif wsRemoteApi.verbose() > 1 then print('returning response:', resp) endreturn resp
endfunction onWSMessage(server, connection, message)local rawReq = message-- if first byte is '{', it *might* be a JSON payloadif rawReq:byte(1) == 123 thenlocal req, ln, err = json.decode(rawReq)if req ~= nil thenlocal resp = wsRemoteApi.handleRequest(req)resp = json.encode(resp)simWS.send(server, connection, resp, simWS.opcode.text)returnendend-- if we are here, it should be a CBOR payloadlocal status, req = pcall(cbor.decode, rawReq)if status thenlocal resp = wsRemoteApi.handleRequest(req)resp = cbor.encode(resp)-- resp=sim.packTable(resp,1)simWS.send(server, connection, resp, simWS.opcode.binary)returnendsim.addLog(sim.verbosity_errors, 'cannot decode message: no suitable decoder')return ''
endfunction wsRemoteApi.publishStepCount()-- if wsRemoteApi.verbose()>1 then--    print('publishing simulationTimeStepCount='..simulationTimeStepCount)-- end
endfunction sysCall_info()return {autoStart = sim.getNamedBoolParam('wsRemoteApi.autoStart') ~= false,menu = 'Connectivity\nWebSocket remote API server',}
endfunction sysCall_init()simWS = require 'simWS'port = sim.getNamedInt32Param('wsRemoteApi.port') or 23050if wsRemoteApi.verbose() > 0 thensim.addLog(sim.verbosity_scriptinfos,string.format('WebSocket Remote API server starting (port=%d)...', port))endjson = require 'dkjson'-- cbor=require 'cbor' -- encodes strings as buffers, always. DO NOT USE!!cbor = require 'org.conman.cbor'wsServer = simWS.start(port)simWS.setMessageHandler(wsServer, 'onWSMessage')if wsRemoteApi.verbose() > 0 thensim.addLog(sim.verbosity_scriptinfos, 'WebSocket Remote API server started')endstepping = false
endfunction sysCall_cleanup()if not simWS then return endif wsServer then simWS.stop(wsServer) endif wsRemoteApi.verbose() > 0 thensim.addLog(sim.verbosity_scriptinfos, 'WebSocket Remote API server stopped')end
endfunction sysCall_addOnScriptSuspend()return {cmd = 'cleanup'}
endfunction sysCall_addOnScriptSuspended()return {cmd = 'cleanup'}
endfunction sysCall_nonSimulation()
endfunction sysCall_beforeMainScript()local outDataif stepping thenoutData = {doNotRunMainScript = not go}go = nilendreturn outData
endfunction sysCall_beforeSimulation()simulationTimeStepCount = 0wsRemoteApi.publishStepCount()
endfunction sysCall_actuation()simulationTimeStepCount = simulationTimeStepCount + 1wsRemoteApi.publishStepCount()
endfunction sysCall_afterSimulation()stepping = false -- auto disable sync. mode
endfunction setStepping(enable)stepping = enablego = nil
endfunction step()go = true
end

wsRemoteAPI中的接口sysCall_init()调用simWS的start接口建立连接。

那么sysCall_init什么时候被执行呢?

v-rep启动的时候就会自动启动连接的监听。

simWS

源码链接

从这个插件的start函数中可以看出,调用start,server端就会listen,然后accept,建立连接。

服务端代码启动流程

1,监听启动

1-1,v-rep启动----调用wsRemoteAPI中的接口sysCall_init(),其中调用simWS的start接口监听,建立连接。

2,事件监听启动

onInstancePass中调用webSocket::server对象的poll接口进行事件监听。

onInstance由v-rep自动调用。

verbose

在 V-REP 中,`wsRemoteApi.verbose()` 函数用于设置或获取远程 API 调用时的日志输出级别。日志输出级别是一个整数值,决定了在进行远程 API 调用时打印哪些日志信息,以便于调试和问题定位。

常见的远程 API 日志输出级别如下:

- 0:不输出任何信息;
- 1:输出仅关键信息,如连接建立和断开等;
- 2:输出详细调用信息,如函数名、参数等;
- 3:输出所有信息,包括调试和错误信息。

浏览器前端websocket实现和接口调用(客户端)

前端怎么打开网页

html双击就会自动使用浏览器打开,浏览器打开就会自动执行html。

(选择Edge浏览器快一些)

客户端代码启动流程

前端页面显示肯定是通过加载html文件,通过解析html文件显示页面的。

前端通过在html中切入js语言,浏览器自动解析并执行。

client端(前端)建立连接只需要两步

1,建立RemoteAPIClient对象;

2,调用RemoteAPIClient中的WebSocketAsPromised对象的open接口发起连接。

前端html中的js建立RemoteAPIClient对象,调用对象open()发起和server的连接,利用这个对象---和服务端建立连接和通信。

        <script>const log = (what) => $('#log').append(`${what}\n`);(async () => {var client = new RemoteAPIClient('localhost', 23050, 'json');log('Connecting...');await client.websocket.open();log('Getting proxy object "sim"...');var sim = await client.require('sim');log('Calling sim.getObject("/Floor")...');var [h] = await sim.getObject('/Floor');log(`Result: ${h}`);})();</script>

client端事件发送

RemoteAPIClient对象中的call接口调用WebScoketAsPromised对象的sendRequest接口发送数据,并等待server端执行返回执行结果数据。

 RemoteAPIClient
"use strict";const WebSocketAsPromised = require('websocket-as-promised');class RemoteAPIClient {//编解码方式(默认为 'cbor')constructor(host = 'localhost', port = 23050, codec = "cbor", opts = {}) {this.host = host;this.port = port;this.codec = codec;var packMessage;var unpackMessage;/*则使用 CBOR 序列化和反序列化库 `CBOR.encode` 和 `CBOR.decode`进行编解码。`packMessage` 为一个函数,将传入的数据进行 CBOR 编码,并返回编码后的结果。`unpackMessage` 为一个异步函数,将传入的数据进行 CBOR 解码,并返回解码后的结果。如果编解码方式为 `'json'`,则使用 JavaScript 原生的 JSON 序列化和反序列化函数 `JSON.stringify` 和 `JSON.parse` 进行编解码。*/if(this.codec == 'cbor') {//this.websocket.binaryType = "arraybuffer";packMessage = data => CBOR.encode(data);unpackMessage = async data => CBOR.decode(await data.arrayBuffer());} else if(this.codec == "json") {packMessage = data => JSON.stringify(data);unpackMessage = data => JSON.parse(data);}var wsOpts = {packMessage,unpackMessage,// attach requestId to message as `id` fieldattachRequestId: (data, requestId) => Object.assign({id: requestId}, data),// read requestId from message `id` fieldextractRequestId: data => data && data.id,};for(var k in opts)wsOpts[k] = opts[k];this.websocket = new WebSocketAsPromised(`ws://${this.host}:${this.port}`, wsOpts);}
/*
使用 `await` 关键字等待该 Promise 对象执行完成并获取响应结果,保存在变量`reply` 中。在该方法中,使用了 `async` 关键字将 `call` 方法标记为异步函数,使其返回一个 Promise 对象。在调用 `await` 时,控制权会交给引擎,等待 WebSocket 通信的异步操作完成,并返回一个响应结果
*/
//函数调用,传递函数名和参数async call(func, args) {var reply = await this.websocket.sendRequest({func, args});if(reply.success) {return reply.ret;} else {throw reply.error;}}
/*
返回name所对应的值,name可能是一个普通变量,也可能是一个建值对的key,或者其他
js对象
*/async getObject(name) {var r = await this.call('wsRemoteApi.info', [name]);return this.getObject_(name, r[0]);}async require(name) {await this.call('wsRemoteApi.require', [name]);return await this.getObject(name);}getObject_(name, _info) {const client = this;var ret = {}for(let k in _info) {var v = _info[k];if(Object.keys(v).length == 1 && v['func'] !== undefined)ret[k] = async function(...args) {return await client.call(name + "." + k, args);};else if(Object.keys(v).length == 1 && v['const'] !== undefined)ret[k] = v['const'];elseret[k] = this.getObject(name + "." + k, null, null, v);}return ret}
}
WebSocketAsPromised


`WebSocketAsPromised` 是一个第三方 JavaScript 库,用于实现基于 Promise 的 WebSocket 连接。
标准的 WebSocket API 使用回调函数来处理事件,例如在连接建立时调用 `onopen` 回调函数,在收到消息时调用 `onmessage` 回调函数等。而使用 `WebSocketAsPromised` 库可以直接返回 Promise 对象来处理 WebSocket 相关的操作,这种写法更符合现代 JavaScript 中基于 Promise 或 async/await 的编程风格,更易于编写和维护。
在这段代码中,`this.websocket` 保存了一个 `WebSocketAsPromised` 类型的对象,表示当前客户端的 WebSocket 连接。`WebSocketAsPromised` 的构造函数需要传递两个参数:WebSocket 的 URL 和 WebSocket 配置对象。其中,URL 参数表示要连接的 WebSocket 服务器的地址和端口号,`wsOpts` 参数为可选参数对象,用于配置 WebSocket 的一些选项,如超时时间、心跳间隔等。
通过创建基于 Promise 的 `WebSocketAsPromised` 类型的对象,可以使用 `async/await` 等方式来处理 WebSocket 连接的事件处理和错误处理,让代码更加简洁、易读和可维护。

open()函数的作用

用于client对端发起连接,和远程server建立连接。

        <script>const log = (what) => $('#log').append(`${what}\n`);(async () => {var client = new RemoteAPIClient('localhost', 23050, 'json');log('Connecting...');await client.websocket.open();log('Getting proxy object "sim"...');var sim = await client.require('sim');log('Calling sim.getObject("/Floor")...');var [h] = await sim.getObject('/Floor');log(`Result: ${h}`);})();</script>
如果open连接失败

如果`open()`连接失败,`open()` 后面的代码不会执行,而是会抛出异常。在这个案例中,如果`await client.websocket.open()`连接失败,控制台会输出一个错误或异常信息,即不会输出"Getting proxy object "sim"..."或"Result: ${h}"。

这是因为`await`关键字会等待异步方法的执行结果,如果异步方法出现错误或异常,则会阻塞当前线程并将错误或异常抛出,因此,如果`open()`连接失败,则异步 `async () => {...}` 函数的执行会被中止,后续的代码也不会执行。

对于上面的代码,如果server端没打开,client端一直处于Connecting
 

websocketpp

pp---cpp

websocket提供了封装好了client和server从链接建立,数据监听,通信到结束通信的对象和接口。

资料链接

讲解

用户手册

html和js

一般情况下,前端加载 HTML 文件时,其中的 JavaScript 代码就会被自动执行。这是因为 HTML 中的 `<script>` 标签会被浏览器自动解析并执行其中的 JavaScript 代码

当浏览器解析 HTML 文件时,碰到 `<script>` 标签时会自动执行其中的脚本。如果 `<script>` 标签中带有 `src` 属性,则浏览器会根据该属性的值加载外部 JavaScript 文件,并自动执行其中的代码。如果 `<script>` 标签内部有 JavaScript 代码,则直接执行其中的代码。

需要注意的是,当浏览器加载 JS 文件时,会阻塞 HTML 页面的渲染。如果 JavaScript 代码很长或运行时间很长,可能会导致页面出现卡顿的现象。为了避免这种情况,可以将 JavaScript 代码放到页面底部,在 HTML 元素加载完毕后再执行。另外,也可以使用异步加载技术,如 `<script async src="xxx.js"></script>` 让 JS 文件在后台异步加载,避免阻塞页面渲染。
 

eg:

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>CoppeliaSim remote API client</title></head><body><div id="log" style="white-space: pre"></div><script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script><script src="https://cdn.jsdelivr.net/gh/spaceify/cbor-js@master/cbor.js" integrity="sha512-0ABB8mRQj73e8+aaUzonPYnP34/YsUCf6SGUJp/pj5BUXttDonDIvCI7XuC7C27Qem6yRpzIzTlq8kJSlUNjoQ==" crossorigin="anonymous"></script><script src="WebSocketAsPromised.bundle.js"></script><script src="RemoteAPIClient.js"></script><script>const log = (what) => $('#log').append(`${what}\n`);(async () => {var client = new RemoteAPIClient('localhost', 23050, 'json');log('Connecting...');await client.websocket.open();log('Getting proxy object "sim"...');var sim = await client.require('sim');log('Calling sim.getObject("/Floor")...');var [h] = await sim.getObject('/Floor');log(`Result: ${h}`);})();</script></body>
</html>

这是一个基于 JavaScript 的 V-REP 远程 API 客户端示例,用于在网页中通过 JavaScript 调用 V-REP 中的场景对象和函数。

在代码中,首先定义了一个 `log` 函数,用于在页面上输出调试信息。然后使用 `async` 函数和箭头函数等语法定义了一个立即执行的异步函数,其中包含了调用 V-REP 远程 API 的过程。

在异步函数中,首先创建了一个名为 `client` 的 `RemoteAPIClient` 对象,用于与 V-REP 中的远程 API 服务建立连接。其中 `localhost` 表示连接本地计算机,`23050` 表示连接的端口号,`json` 表示使用 JSON-RPC 协议进行通信。

然后使用 `client.require('sim')` 函数获取到远程 API 的命名空间 `sim`,该命名空间包含了 V-REP 中预定义的各种对象和函数。最后使用 `sim.getObject('/Floor')` 函数获取到名为 `/Floor` 的场景对象,将结果保存到变量 `h` 中。

在获取到结果后,调用 `log` 函数将结果输出到页面上。

js调用加载lua模块,调用lua接口实现及原理

最终的实现是通过三方库定义的WebSocketAsPromised接口sendRequest()向服务端发送需要调用的接口和参数,服务端接收到请求之后,会执行需要调用的接口,并返回执行接口返回的内容。

因为我们v-rep中的RemoteAPIClient指定了序列化和反序列化,所以即使调用Lua或者c++接口,反序列化之后就可以变为js所对应的数据。

class RemoteAPIClient {//编解码方式(默认为 'cbor')constructor(host = 'localhost', port = 23050, codec = "cbor", opts = {}) {this.host = host;this.port = port;this.codec = codec;var packMessage;var unpackMessage;/*则使用 CBOR 序列化和反序列化库 `CBOR.encode` 和 `CBOR.decode`进行编解码。`packMessage` 为一个函数,将传入的数据进行 CBOR 编码,并返回编码后的结果。`unpackMessage` 为一个异步函数,将传入的数据进行 CBOR 解码,并返回解码后的结果。如果编解码方式为 `'json'`,则使用 JavaScript 原生的 JSON 序列化和反序列化函数 `JSON.stringify` 和 `JSON.parse` 进行编解码。数据传输格式使用json,无论数据来自lua函数返回还是c++函数返回,JSON.parse都解析为js数据。*/if(this.codec == 'cbor') {//this.websocket.binaryType = "arraybuffer";packMessage = data => CBOR.encode(data);unpackMessage = async data => CBOR.decode(await data.arrayBuffer());} else if(this.codec == "json") {packMessage = data => JSON.stringify(data);unpackMessage = data => JSON.parse(data);}var wsOpts = {packMessage,unpackMessage,// attach requestId to message as `id` fieldattachRequestId: (data, requestId) => Object.assign({id: requestId}, data),// read requestId from message `id` fieldextractRequestId: data => data && data.id,};for(var k in opts)wsOpts[k] = opts[k];this.websocket = new WebSocketAsPromised(`ws://${this.host}:${this.port}`, wsOpts);}


 

客户端怎么调用接口的

通过html中执行js代码。

方式1:先加载模块,再通过模块加载模块中定义的接口。

插件中的返回值通过js获取

直接在js中定义与调用的函数返回的类型对应的js变量接收返回值即可。

                //getInfo返回数组var [info]=await simTest.getInfo();log(`info length: ${info.length}`);for(var i=0;i<info.length;++i){log(`getInfo: ${info[i]}`);}

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

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

相关文章

【国产MCU】-CH32V307-定时器同步模式

定时器同步模式 文章目录 定时器同步模式1、定时器同步模式介绍2、驱动API介绍3、定时器同步模式实例1、定时器同步模式介绍 CH32V307的定时器能够输出时钟脉冲(TRGO),也能接收其他定时器的输入(ITRx)。不同的定时器的ITRx的来源(别的定时器的TRGO)是不一样的。 通用定…

Covalent Network的长期数据可用性 获得了众多加密 KOL的肯定及支持

随着 Web3 生态系统的动态发展&#xff0c;Covalent Network&#xff08;CQT&#xff09;的关键性正在显现&#xff0c;通过提供分布式、加密安全的数据层&#xff0c;以解决长期数据可用性的问题。Covalent Network&#xff08;CQT&#xff09;不仅仅是一个工具&#xff0c;更…

企业内部文件资料如何进行加密 ——防止泄露?

企业内部文件资料的加密是防止数据泄露的关键措施之一。 www.weaem.com 以下是一些建议&#xff0c;用于在企业内部进行文件资料的加密&#xff0c;以防止数据泄露&#xff1a; 选择适合的加密技术&#xff1a; 透明加密&#xff1a;这种加密方式允许用户在不改变原有操作习惯的…

简单网站模板1(HTML)

想要拥有自己的网站&#xff0c;却不知该如何才能简约好看&#xff0c;接下来分享一种自己搭建的网站模板&#xff0c;希望大家喜欢。 展示图&#xff1a; CODE: <!DOCTYPE html> <html> <head><title>我的网站</title><style>body {fo…

eltable 合计行添加tooltip

eltable 合计行添加tooltip 问题描述&#xff1a; eltable 合计行单元格内容过长会换行&#xff0c;需求要求合计行数据超长显示 … &#xff0c;鼠标 hover 时显示提示信息。 解决方案&#xff1a;eltable合计行没有对外的修改接口&#xff0c;想法是 自己实现一个tooltip&a…

JVM对象创建与内存分配机制

JVM对象创建与内存分配机制 JVM对象创建与内存分配机制 JVM对象创建与内存分配机制对象的创建过程内存分配对象栈上分配对象逃逸分析标量替换 对象在Eden区分配大对象直接进入老年代长期存活的对象将进入老年代对象年龄动态判断老年代空间分配担保机制 对象头与指针压缩对象头利…

课时49:表达式_表达式进阶_集合基础

3.3.2 集合基础 学习目标 这一节&#xff0c;我们从 基础知识、简单实践、小结 三个方面来学习。 基础知识 简介 所谓的集合&#xff0c;主要是针对多个条件表达式组合后的结果&#xff0c;尤其是针对于逻辑场景的组合。初中数学的相关逻辑示意图&#xff1a;表现样式 两个…

将四个主页面配置为 tab-bar 的子路由

使用vant组件库 路由 {path: /, name: layout,component: () > import(/views/layout),children: [{path: , // 默认子路由name: home,component: () > import(/views/home)},{path: qa,name: qa,component: () > import(/views/qa)},{path: video,name: video,compo…

阿里云2核4G服务器租用价格85元一年,30元3个月

阿里云2核4G服务器多少钱一年&#xff1f;2核4G服务器1个月费用多少&#xff1f;2核4G服务器30元3个月、85元一年&#xff0c;轻量应用服务器2核4G4M带宽165元一年&#xff0c;本文阿里云服务器网整理的2核4G参加活动的主机是ECS经济型e实例和u1云服务器&#xff0c;阿里云服务…

图搜索基础-深度优先搜索

图搜索基础-深度优先搜索 参考原理引入流程解析手推例子 代码实现运行结果结果分析 参考 理论参考&#xff1a;深蓝学院 实现参考&#xff1a;github项目 原理 引入 对于这样一个图&#xff0c;我们试图找到S到G的通路&#xff1a; 计算机程序不会像人眼一样&#xff0c;一…

如何做代币分析:以 USDT 币为例

作者&#xff1a;lesleyfootprint.network 编译&#xff1a;cicifootprint.network 数据源&#xff1a;USDT Token Dashboard &#xff08;仅包括以太坊数据&#xff09; 在加密货币和数字资产领域&#xff0c;代币分析起着至关重要的作用。代币分析指的是深入研究与代币相关…

DolphinScheduler——工作流实例的生命周期

目录 一、DolphinScheduler架构原理 1.1 系统架构图 1.2 DolphinScheduler核心概念 1.2 创建工作流 1.2.1 如何触发一个工作流实例 1.2.2 任务调度链路监控 1.2.3 Workflow-DAG解析 DAG解析 Dispatch分发流程 Master和Worker的交互过程 1.3 任务运行状态 该篇文章主…

Leetcode : 215. 数组中的第 K 个最大元素

给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 k 个最大的元素。 请注意&#xff0c;你需要找的是数组排序后的第 k 个最大的元素&#xff0c;而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 思路&#xff1a;最开始排序算法&…

MySQL 存储过程批量插入总结

功能需求背景&#xff1a;今天接到产品经理核心业务表的数据压测功能&#xff0c;让我向核心业务表插入百万级的业务量数据&#xff0c;我首先想到的办法就是存储过程实现数据的批量 。 由于无法提供核心业务表&#xff0c;本文仅仅提供我刚刚自己创建的表bds_base_user 表做相…

nginx 反向代理 与缓存功能

一 理论说明 &#xff08;一&#xff09;反向代理简介 反向代理&#xff1a;reverse proxy&#xff0c;指的是代理外网用户的请求到内部的指定的服务器&#xff0c;并将数据返回给用户的一种方式&#xff0c;这是用的比较多的一种方式。 即 代理服务机 Nginx 除了可以在企…

算法——滑动窗口之最大连续1的个数、将x减到0的最小操作数、水果成篮

3.最大连续1的个数 题目:. - 力扣&#xff08;LeetCode&#xff09; 题目要求的是给定一个二进制数组 nums 和一个整数 k&#xff0c;如果可以翻转最多 k 个 0 &#xff0c;则返回 数组中连续 1 的最大个数 。 按照题目正面去做,还要替换0,很麻烦 反正我们最后要求的是最长…

YOLOv8改进 | 独家创新篇 | 结合SOTA思想利用双主干网络改进YOLOv8(全网独家创新,最重磅的更新)

一、本文介绍 本文给大家带来的改进机制是结合目前SOTAYOLOv9的思想利用双主干网络来改进YOLOv8(本专栏目前发布以来改进最大的内容,同时本文内容为我个人一手整理全网独家首发 | 就连V9官方不支持的模型宽度和深度修改我都均已提供,本文内容支持YOLOv8全系列模型从n到x均可…

刷题笔记 洛谷 P1162 填涂颜色

思路来自 大佬 hat.openai.com/c/9c30032e-5fb9-4677-8c15-9ea6530dc6db 题目链接 P1162 填涂颜色 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路 搜索 首先 在外面围上一圈0开始搜素 因为题目说将封闭区域内的0变成2 我们可以在外面进行搜索 把外面所有可以搜索…

Nginx----高性能的WEB服务端(四)

一、http 协议反向代理 1、反向代理&#xff1a;缓存功能 ​ proxy_cache zone_name | off; 默认off #指明调用的缓存&#xff0c;或关闭缓存机制;Context:http, server, location #zone_name 表示缓存的名称.需要由proxy_cache_path事先定义proxy_cache_key string; #缓存中…

【Redis】深入理解 Redis 常用数据类型源码及底层实现(5.详解List数据结构)

本文是深入理解 Redis 常用数据类型源码及底层实现系列的第5篇&#xff5e;前4篇可移步(&#xffe3;∇&#xffe3;)/ 【Redis】深入理解 Redis 常用数据类型源码及底层实现&#xff08;1.结构与源码概述&#xff09;-CSDN博客 【Redis】深入理解 Redis 常用数据类型源码及底…