Pengc - cc
type: channel
link: https://pcc.pub/author/1
description: cc
items: Mongo错误修复 - WiredTiger metadata corruption detected
items: Mongo 关联表查询
items: MQTT - LWT(遗愿消息) + Retain 实现设备状态监测
items: 摘自— 《纳瓦尔宝典》
items: PromptAI - 开启交互式AI仅一步之遥！
items: 联想510s mini 安装 Ventura
items: Server Send Events With Spring Boot
items: 摘自-《幸福之路》
items: 我是怎么样优化API的？
items: Frp 内网穿透

Mongo错误修复 - WiredTiger metadata corruption detected
type: item
date: 2024-08-01T15:38:00+08:00
description: 免责声明本文提供的所有信息仅供参考，作者不对使用本文所含信息而导致的任何直接或间接损失负责。在进行MongoDB数据恢复操作之前，请务必备份您的数据并仔细阅读MongoDB官方文档。数据恢复操作具有风险，可能导致数据的永久丢失或损坏。作者建议在执行任何数据恢复步骤之前，先在测试环境中进行尝试，并咨询有经验的数据库管理员或技术专家。背景系统: macOS 13.6Mongo: 5.0.3 (Docker 容器部署)原因: 由于Docker Desktop在Mac上运行消耗资源非常高，所以又安装了OrbStack进行docker管理。 在OrbStack运行时，意外的打开了Docker Desktop（噩耗的开始）。 刚开始没在意，中午吃饭发现系统刷新失败了！？ 果然还是出问题了。782c0bd0dfb4 mongo:5.0.3 "docker-entrypoint.s…" 6 weeks ago Restarting (14) 46 seconds ago mongodbmongodb的容器一直在重启，于是看看log:{"t":{"$date":"2024-08-01T06:15:22.352+00:00"},"s":"I", "c":"NETWORK", "id":4915701, "ctx":"-","msg":"Initialized wire specification","attr":{"spec":{"incomingExternalClient":{"minWireVersion":0,"maxWireVersion":13},"incomingInternalClient":{"minWireVersion":0,"maxWireVersion":13},"outgoing":{"minWireVersion":0,"maxWireVersion":13},"isInternalClient":true}}} {"t":{"$date":"2024-08-01T06:15:22.352+00:00"},"s":"I", "c":"CONTROL", "id":23285, "ctx":"-","msg":"Automatically disabling TLS 1.0, to force-enable TLS 1.0 specify --sslDisabledProtocols 'none'"} {"t":{"$date":"2024-08-01T06:15:22.354+00:00"},"s":"W", "c":"ASIO", "id":22601, "ctx":"main","msg":"No TransportLayer configured during NetworkInterface startup"} {"t":{"$date":"2024-08-01T06:15:22.355+00:00"},"s":"I", "c":"NETWORK", "id":4648601, "ctx":"main","msg":"Implicit TCP FastOpen unavailable. If TCP FastOpen is required, set tcpFastOpenServer, tcpFastOpenClient, and tcpFastOpenQueueSize."} {"t":{"$date":"2024-08-01T06:15:22.355+00:00"},"s":"W", "c":"ASIO", "id":22601, "ctx":"main","msg":"No TransportLayer configured during NetworkInterface startup"} {"t":{"$date":"2024-08-01T06:15:22.355+00:00"},"s":"I", "c":"REPL", "id":5123008, "ctx":"main","msg":"Successfully registered PrimaryOnlyService","attr":{"service":"TenantMigrationDonorService","ns":"config.tenantMigrationDonors"}} {"t":{"$date":"2024-08-01T06:15:22.355+00:00"},"s":"I", "c":"REPL", "id":5123008, "ctx":"main","msg":"Successfully registered PrimaryOnlyService","attr":{"service":"TenantMigration…

Mongo 关联表查询
type: item
date: 2024-06-27T22:54:00+08:00
description: 摘要Mongo支持与Mysql类似的关联表查询，但比较麻烦。通过与Mysql实现进行对比，便于理解Mongo如何实现。MysqlOrder表关联Product表的id, 实现查询订单支持搜索产品名称。# Order CREATE TABLE `order` ( `id` bigint(20) DEFAULT NULL, `no` varchar(255) DEFAULT NULL, `amount` int(11) DEFAULT NULL COMMENT '单位- 分\n', `productId` bigint(20) DEFAULT NULL, `count` int(11) DEFAULT NULL, `userId` bigint(20) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Records of product -- ---------------------------- INSERT INTO `order` (`id`, `no`, `amount`, `productId`, `count`, `userId`) VALUES (1, '2024062701', 10000, 1, 1, 1); INSERT INTO `order` (`id`, `no`, `amount`, `productId`, `count`, `userId`) VALUES (1, '2024062702', 20000, 1, 2, 1); # Product CREATE TABLE `product` ( `id` bigint(20) DEFAULT NULL, `name` varchar(255) DEFAULT NULL, `price` int(11) DEFAULT NULL COMMENT '单位-分' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Records of product -- ---------------------------- INSERT INTO `product` (`id`, `name`, `price`) VALUES (1, '测试产品', 10000); 关联查询查询订单、产品名称，通过left join搜索产品名称SELECT o,p.name from `order` as o left JOIN `product` as p on o.productId = p.id where p.name like '%测试%'; ## 结果 #id no amount productId count userId name 1 2024062701 10000 1 1 1 测试产品 1 2024062702 20000 1 2 1 测试产品Mongo同样在mongo中准备Order和Product的集合## insert to product db.product.insertOne({ name: '测试产品', price: 10000 }); ## result { "_id" : ObjectId("667d7fbe04cfea555206351f"), "name" : "测试产品", "price" : 10000 } ## insert to orders db.order.insertMany([ { no: '2024062701', amount: 10000, productId: "667d7fbe04cfea555206351f", count: 1, userId: 1 }, { no: '2024062702', amount: 20000, productId: "667d7fbe04cfea555206351f", count: 2, userId: 1 } ]); # result { "_id" : ObjectId("667d80b804cfea5552063520"), "no" : "2024062701", "amount" : 10000, "productId" : "667d7fbe04cfea555206351f", "count" : 1, "userId" : 1 } { "_id" : ObjectId("667d80b804cfea5552063521"), "no" : "2024062702", "amount" : 20000, "productId" : "66…

MQTT - LWT(遗愿消息) + Retain 实现设备状态监测
type: item
date: 2023-11-17T23:30:00+08:00
description: 遗愿消息 - LWT（Last Will and Testament）根据MQTT协议，在创建链接时可设置遗愿消息（Will Message）。 它属于链接的一个配置信息，当链接意外断开时将发送该消息。包含但不限于以下情况将发送该信息：服务端发现I/O或网络错误；Client未在Keep Alive time规定时间内进行通信；Client关闭网络链接时未发送0x00代码的“DISCONNECT”包 （非正常关闭）；Server 关闭网络链接时未收到0x00代码的“DISCONNECT”包（非正常关闭）；遗愿被储存在服务端并与Session进行关联。遗愿消息存储在CONNECT的payload中，由三部分组成：Will Properties : 遗愿属性，一个自定义map。Will Topic : 遗愿主题。Will Payload fields: 遗愿payload，与普通message的payload一样，可自定义。保留消息 -Retain Message保留消息是指发布Message的retain标识为1，当服务端收到一条保留消息：服务端替换该Topic已有的保留消息；订阅者会立即收到消息；未来的订阅者订阅后会立即收到该消息。即Topic只会保存最新的一条保留信息，已订阅的会立即收到，未来订阅的会在订阅时收到该保留消息。清除Topic中的保留消息:如果保留消息的Payload为空(0字节)，服务端会该Topic中的保留消息进行移除，并且Topic将不会存储该保留消息。遗愿消息+保留消息实现设备状态监测1、订阅者首先启动，订阅device/status2、设备创建连接时设置保留遗愿消息：{"status":"offline"}3、设备链接成功后，立即发送保留消息：{"status":"online"}此时，订阅者会立即收到消息：{"status":"online"} 设备上线场景1: 订阅者重启1、订阅者会立即收到保留消息：{"status":"online"} 此时设备时在线的。场景2: 设备重启1、设备断开，触发遗愿消息：{"status":"offline"} 设备离线2、设备连接，收到上线的保留消息：{"status":"online"}至此，完成设备状态监测。源码 - JavaDevice:import com.alibaba.fastjson2.JSONObject; import com.hivemq.client.mqtt.MqttClient; import com.hivemq.client.mqtt.MqttClientBuilder; import com.hivemq.client.mqtt.MqttClientState; import com.hivemq.client.mqtt.datatypes.MqttQos; import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient; import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5WillPublish; import java.nio.charset.StandardCharsets; import java.util.Map; /** * publish message * * @author chenchen * @Date 2023/11/17 */ public class Publisher { public static void main(String[] args) { MqttClientBuilder clientBuilder = MqttClient.builder() .identifier("cc-status-monitor") .addConnectedListener((context) -> { MqttClientState clientState = context.getClientConfig().getState(); System.out.println(clientState.isConnected()); }) .addDisconnectedListener(context -> System.out.println(context.getCause().getMessage())) .serverHost("broker.hivemq.com") .serverPort(1883); // will message with retain Mqtt5WillPublish offline = Mqtt5WillPublish.builder() .topic("device/…

摘自— 《纳瓦尔宝典》
type: item
date: 2023-09-24T21:16:00+08:00
description: “我认为，过去就是过去了，没有回忆，没有遗憾，没有放不下的人，没有忘不掉的旅行。既往不恋。人之所以感到痛苦，很多时候是因为拿以往和现在做比较。”

PromptAI - 开启交互式AI仅一步之遥！
type: item
date: 2023-06-21T17:24:00+08:00
description: 背景我们一直从事企业服务，早在2020年通过服务国内的客户，我们就敏感的发现交互技术的变革即将发生，新的交互时代即将来临。我们把自身的专业知识、经验和能力集成到了我们的产品中，希望能帮助客户获得相应的能力，能更好的面对这个伟大的时代！PromptAI为快速对话设计和部署⽽构建的⽆代码开发环境。它基于RASA，但⼜不需要特定的RASA 知识来设计和部署聊天机器⼈。使⽤⾃然语⾔来设计⾃然语⾔对话，它最⼤限度地减少了标注和编码⼯作，旨在⼏分钟内发布企业级聊天机器⼈。有哪些特点？使用友好无需编程, 近似自然语言的方式编辑对话，能写word就能上手免费且拥有所有功能，可上线两个独立的chatbot [真-无任何费用]解决80%以上的对话需求，24小时在线服务开发友好：Web无侵入式部署，移动端完美适配FAQ、多轮、变量提取、Form、Webhook、Goto...免费下载⽣成的RASA源码ChatGPT支持私有部署 [免费版已推出，欢迎联系]适合那些用户？个人: 对chatbot/Rasa感兴趣个人开发者: 提供免费机器人服务，无任何运行及运维成本，一行代码无侵入式集成到您的应用中/小企业用户: 无需专门组建客服团队，已有客户团队的情况下极大降低客服团队工作量。其他: 欢迎联系我们获取专属解决方案.预览近似自然语言的方式编辑对话一键发布，无侵入式部署完美兼容移动端如何注册?https://www.promptai.cn联系我们:email: info@promptai.cnWechat: 官网左下角微信扫码加入群聊我们把我们产品最基本的部分贡献出来，方便企业用户开发、设计交互式对话系统，并在这个基础之上，我们提供了许多针对企业的咨询服务和解决方案。如果想更多的了解我们的产品和服务，请访问我们的网站，期待你的光临！

联想510s mini 安装 Ventura
type: item
date: 2023-05-03T17:19:00+08:00
description: 背景使用联想天逸510S mini(十代 10400)安装黑苹果作为日常生产力工具。 本文参考的天逸510s Mini兼macOS BigSur安装教程，然后记录一些细节问题。配置：(仅贴出与官方配置有差异的地方)类型具体型号内存玖合(JUHOR) 48GB DDR4 3200 笔记本内存条PCIe梵想（FANXIANG）1TB SSD固态硬盘 M.2接口PCIe 4.0 x4SATA移速 金钱豹系列-256GB网卡博通BCM94360Z4准备// U盘 推荐 32 GB // Ventura 镜像 微信公众号 黑果小兵的部落阁 // Ventura 镜像刻录工具 balenaetcher https://www.balena.io/etcher // 小兵开源的EFI https://github.com/daliansky/Lenovo-TianYi-510S-Mini-Hackintosh安装修改Bios配置参考github中的信息.注：如果要关闭CPU的“CFG Lock”，需要先安装仓库中提供的BIOS版本，先进入Windows运行该程序完成BIOS版本替换（我先安装了Windows，然后进行替换，未在PE系统中测试。）制作启动U盘使用balenaetcher将下载的Ventura安装镜像刻录到U盘。 安装过程略。替换U盘中的EFI从小兵开源的EFI仓库Release页面下载最新EFI。 下载完成后，解压替换启动盘中的EFI目录。这一步必须操作，否则无法进入安装界面。注意：目前release中的版本是v2.3.0，从日志看不支持Ventura。 可以直接clone项目，然后手动拷贝EFI目录。[2023/5/3]分区将硬盘格式化为GUID分区，将在ESP分区中创建EFI文件夹，将U盘替换后的EFI拷贝进去，否则无法脱离U盘使用。 -- 这一步一定要在安装前做，实际测试安装后替换无效。安装插入U盘启动进入安装界面，选择“Install macOS Ventura”进行安装：等待一会，顺利的话会进入安装界面：首先选择“磁盘工具-Disk Utility”格式化硬盘格式为“APFS”，如果格式化失败，先格式化为“Mac OS Extended (Hournaled)”，再格式化为“APFS”.接下来退出Disk Utility，选择“Install macOs Ventura”进行安装,选中格式化好的磁盘,进行安装。安装过程会几次重启,等待即可。完成顺利的话会进入配置界面，创建用户等操作，后续即可拔掉U盘使用。总结安装过程折腾了好几天，不过好在有小兵这样的大神提供完整的EFI，减少了很多折腾的时间。非常感谢！这个机器是20年发布的到现在已三年左右，CPU已是前三代的产品。不过作为日常写写代码已满足使用，比起二手的Mac迷你仍有不小的性价比。再加上目前内存、硬盘价格非常划算，300块可买32GB内存条。 比起苹果升级太香了！这个机器购买起来比较折腾，先在淘宝买的“准系统”，然后自购CPU、内存、硬盘及网卡，整个过程还是比较有意思。目前使用下来还体验还不错，Wi-Fi、蓝牙、接力等等都可正常使用，比目前使用的15款的Macbook Pro体验好得多。说一说问题：1、使用Ipad Pro当扩展屏，拖动的时候界面不会刷新，当操作完成后才用响应。2、在SATA固态上安装的Win11，目前开机后Core0会占用100%，解决方案是拔掉所有USB，等待一会再插上去即可恢复。3、网卡天线的安装对网速、蓝牙影响，如果自购准系统，建议让卖家帮忙安装天线。其他如果你折腾这个设备遇到了问题，可以联系我提供一些帮助（如果你啥经验都没有，建议直接买成品吧）。联系我：Email: idkpengc@gmail.com文章底部留言。引用https://blog.daliansky.net/Lenovo-Tianyi-510s-Mini-and-macOS-BigSur-Installation-Tutorial.html https://github.com/daliansky/Lenovo-TianYi-510S-Mini-Hackintosh

Server Send Events With Spring Boot
type: item
date: 2023-04-02T13:29:00+08:00
description: 背景在使用ChatGPT时，通过http.Post进行调用耗时非常高，体验较差。 OpenAI提供了Stream(即SSE)的返回模式,不用等到响应生成完后才给到客户端响应。使用Stream API方式时，那么后端与前端也需要使用SSE的方式进行API交互。源代码在文末。Server-Sent Events（SSE）是一种在Web浏览器和服务器之间实现服务器推送事件的技术。它允许服务器向客户端推送事件流，这些事件可以是简单的文本消息或具有自定义格式的复杂数据。SSE 是一种基于 HTTP 的协议，使用长轮询或 HTTP 流来实现服务器推送。 SSE 可以用于各种用例，例如实时更新股票报价、即时聊天应用程序、新闻或社交媒体网站上的实时更新等等。与传统的轮询或 WebSocket 不同，SSE 不需要客户端发起请求，而是服务器始终保持连接打开并推送数据，因此 SSE 可以更高效地使用网络带宽和服务器资源。 在前端，可以使用 JavaScript API 来监听服务器发送的事件，以及处理和显示这些事件的数据。 引用：## open ai chat api https://platform.openai.com/docs/api-reference/chat/create ## Request ChatGPT API Using Spring boot https://www.taogenjia.com/2023/03/16/The-Guide-to-Call-ChatGPT-3-5-Event-Stream-API-in-Spring-Boot/ ## Doc https://developer.mozilla.org/en-US/docs/web/api/server-sent_events/using_server-sent_events https://developer.mozilla.org/zh-CN/docs/Web/API/EventSource ## nginx https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering理解常见的HTTP请求是服务端把命令执行完成过后给到一个结果，那么客户端必须等待，大部分场景下这是没问题的。 那么在处理时间比较高的场景下，客户端可以实时接收部分处理结果，增加用户体验。我们从另一个角度看Http,HttpServerRequest: 有输入流，包含请求的数据HttpServletResponse:有输出流，可以写响应数据。那么我们处理Http请求时，不断的向Response的 outputStream写入数据，那么在没有处理完成响应的情况下也可以收到一部分数据。 @GetMapping("test") public void test(HttpServletRequest request, HttpServletResponse response) throws Exception { // 设置响应的Content-Type为text/event-stream response.setContentType("text/event-stream"); response.setStatus(200); OutputStream outputStream = response.getOutputStream(); int i = 10; while (i >= 0) { String message = "i : " + i + "\n"; outputStream.write(message.getBytes(StandardCharsets.UTF_8)); outputStream.flush(); try { Thread.sleep(1000); } catch (Exception ignored) {} i--; } }我们打开浏览器访问这个api时，界面会间隔一秒输出一行：i : 10 i : 9 i : 8 i : 7 i : 6 i : 5 i : 4 i : 3 i : 2 i : 1 i : 0点击查看效果有了以上理解，我们只需要按着SSE要求的格式不停的向写入数据即可。SSE 格式1、id event dataid: xxx \n event: message \n data: hello from cc\n\n2、event dataevent: message \n data: hello from cc\n\n3、data onlydata: hello from cc\n\n其中： event: 事件名称，可以自己定义，默认是message id、event: 可…

摘自-《幸福之路》
type: item
date: 2023-03-27T12:41:00+08:00
description: “我想我能变成动物，和它们为伴，它们是那么恬静那么矜持，我站着，久久的望着它们。它们不为儿女作牛马，也不为几女哀号，它们不在黑暗里睁眼失眠，为了它们的罪过啼泣，它们不喋喋讨论对上帝的责任，使我头晕脑胀，没有一个不满，没有一个为了占有欲而癲狂，没有一个向另一个屈膝，也不对几千年前的袓先跪拜，在整个的地球上没有一个有什么身份，也没有一个忧郁哀伤。——惠特曼Walt Whitman”摘录来自幸福之路罗素此材料可能受版权保护。“而过事诛求的结果，一定使你连应得的一份都落空。一个人能凭藉一些真正的兴趣，例如德朗会议或星辰史等，而忘记他的烦虑的话，当他从无人格的世界上旅行回来时，定将发觉自己觅得了均衡与宁静，使他能用最高明的手段去对付他的烦虑，而同时也尝到了真正的、即使是暂时的幸福。 幸福底秘诀是：让你的兴趣尽量的扩大，让你对人对物的反应，尽量的倾向于友善。”摘录来自: 罗素. “幸福之路 (傅雷经典译文全集).” Apple Books. 此材料受版权保护。

我是怎么样优化API的？
type: item
date: 2023-03-04T12:41:00+08:00
description: 背景在系统开发过程中，以迭代功能为主，在使用过程中遇到性能瓶颈再进行针对性优化。本次遇到的问题是在导入3000+FAQ时导入时间大概500S左右，用户端提示导入失败，结果数据在导入中。文章出现的代码经过处理，不包含任何具体隐私信息，仅还原场景概念：FAQ：一般指常见问题解答。常见问题解答（frequently-asked questions，简称FAQ）即：一个问题对应一个答案。他的结构大概是一组相关的问题和一个答案。比如“你是谁？”这个问题，他会有不同的问法：“你叫什么？你叫啥？”，然后对应一个答案："我是xxx"意图/Intent：即FAQ中的“你是谁”目标1、在3000条数据时，导入在时间优到5秒内（而用户能够忍受的最长等待时间在6～8秒之间）；2、优化查询，返回时间在1S内；步骤1、找出瓶颈点；2、确定优化措施；3、实施；这三个步骤看似简单，其实需要在开发过程中逐步积累出自己的套路及经验。FAQ批量导入这里从系统csv文件中读取出意图和答案，再将数据保存到数据库，然后做一些检查，把错误的信息打上标签。解析数据保存校验、更新找出瓶颈点首先，我们发现API慢时，我们要知道哪些步骤慢。 这里我们用到google的Stopwatch进行“打桩”，给个操作计时。如 public static void main(String[] args) { // 创建后可多次输出耗时 Stopwatch stopwatch = Stopwatch.createStarted(); ThreadUtil.sleep(1000); System.out.println("消耗时间：" + stopwatch.elapsed(TimeUnit.MILLISECONDS)); ThreadUtil.sleep(2000); System.out.println("消耗时间：" + stopwatch.elapsed(TimeUnit.MILLISECONDS)); } 消耗时间：1001 消耗时间：3009回到我们的导入FAQ代码 public void save(String faqId, MultipartFile file) throws Exception { Stopwatch stopwatch = Stopwatch.createStarted(); // 1、从faq文件解析出数据 List<List<String>> rows = _readRows(file); LOG.info("[import faq - finish check used:]", stopwatch.elapsed(TimeUnit.MILLISECONDS)); // 获取一个链接 Connection conn = getConn(); // 一个FAQ由一个User、一个Bot组成 // 转换成faq pair 对 List<Pair<User, Bot>> details = _convertRows(rows, faqId); LOG.info("[import faq - convert: ]", stopwatch.elapsed(TimeUnit.MILLISECONDS)); // 保存到数据库 for (Pair<User, Bot> p : details) { ComponentDao.add(conn, p.getKey().toComponent()); ComponentDao.add(conn, p.getRight().toComponent()); } LOG.info("[import faq - save 2 db: ]", stopwatch.elapsed(TimeUnit.MILLISECONDS)); conn.commit(); LOG.info("[import faq - finish commit 2: ]", stopwatch.elapsed(TimeUnit.MILLISECONDS)); _validate(faqId, conn); conn.commit(); } private void _validate(String faqId, Connection conn, String dbName) throws Exception { Stopwatch stopwatch = Stopwatch.createStarted(); // 1、创建一个上下文，携带一些信息 ComponentValidatorContext context = _buildContext(componentId, conn); LOG.debug("[validate faq - build context…

Frp 内网穿透
type: item
date: 2022-12-10T13:28:00+08:00
description: 背景由于Ngrok开源版本已停止维护，经过调研后Frp比较合适:服务端/客户端无需编译支持多种客户端...引用：// github https://github.com/fatedier/frp // doc https://gofrp.org/docs/环境服务端：Centos 7客户端：Linux、Mac...Frp: 0.45其他：supervisord要求：服务器有公网ip+自有域名域名解析可以使用子域名，如: frp.xx.com; 可工作的地址: xx.frp.xx.com这里需要配置两个域名解析frp.xx.com ip *.frp.xx.com ip （泛域名解析）安装 - 服务端下载目前在最新版本为0.45，下载对应的Linux版本frp_0.45.0_linux_amd64.tar.gzzip包解压后有对应的服务端、客户端及对应的配置. ├── LICENSE ├── frpc # 客户端 ├── frpc.ini # 客户端简化配置 ├── frpc_full.ini # 客户端完整配置 ├── frps # 服务端 ├── frps.ini # 服务端简化配置 └── frps_full.ini # 服务完整化配置 0 directories, 7 files准备这里我使用的目录：/usr/local/frp将frpc、frpc.ini拷贝到此目录中配置文件frps.inibind_port = 9443 # 客户端链接的端口 # if you want to support virtual host, you must set the http port for listening (optional) # Note: http port and https port can be same with bind_port # vhost_https_port = 443 vhost_http_port = 9443 subdomain_host = frp.xx.com # 配置子域名 # authentication_method specifies what authentication method to use authenticate frpc with frps. # If "token" is specified - token will be read into login message. # If "oidc" is specified - OIDC (Open ID Connect) token will be issued using OIDC settings. By default, this value is "token". authentication_method = token # 这里选择token进行验证，可参考文档进行调整 # auth token token = changeit # 这里是配置的token，客户端需要保持一致 # enable_prometheus will export prometheus metrics on {dashboard_addr}:{dashboard_port} in /metrics api. enable_prometheus = true 启动防止经进程挂掉，这里使用supervisor对frps进行管理supervisor 配置 [program:frserver] directory=/usr/local/frp command=/usr/local/frp/frps -c /usr/local/frp/frps.ini autostart=true autorestart=true startsecs=10 user=root stderr_logfile=/usr/local/frp/log/frp_stderr.log stdout_logfile=/usr/local/frp/log/frp_stdout.log redirect_stderr=true 注意，supervisor使用的目录要预先创建好，比如这里的log目录配置好后，执行supervisord reload supervisord status # 结果 [root@cc etc]# supervisorctl status frserver RUNNING pid 12464, uptime 1 days, 22:47:02 安装 - 客户端以Mac环境进行演示下载与服务端版本一致，下载对应的Mac版本frp_0.45.0_darwin_amd64.tar.gzzip包解压后有对应的服务端、客户端及对应的配置. ├── LICENS…