go 集成nacos注册中心、配置中心
使用限制
Go>=v1.15
Nacos>2.x
安装
使用go get
安装SDK:
go get -u github.com/nacos-group/nacos-sdk-go/v2
快速使用
- 初始化客户端配置ClientConfig
constant.ClientConfig{TimeoutMs uint64 // 请求Nacos服务端的超时时间,默认是10000msNamespaceId string // Nacos的命名空间IdEndpoint string // 当使用地址服务器时,需要该配置. https://help.aliyun.com/document_detail/130146.htmlRegionId string // Nacos&KMS的regionId,用于配置中心的鉴权AccessKey string // Nacos&KMS的AccessKey,用于配置中心的鉴权SecretKey string // Nacos&KMS的SecretKey,用于配置中心的鉴权OpenKMS bool // 是否开启kms,默认不开启,kms可以参考文档 https://help.aliyun.com/product/28933.html// 同时DataId必须以"cipher-"作为前缀才会启动加解密逻辑CacheDir string // 缓存service信息的目录,默认是当前运行目录UpdateThreadNum int // 监听service变化的并发数,默认20NotLoadCacheAtStart bool // 在启动的时候不读取缓存在CacheDir的service信息UpdateCacheWhenEmpty bool // 当service返回的实例列表为空时,不更新缓存,用于推空保护Username string // Nacos服务端的API鉴权UsernamePassword string // Nacos服务端的API鉴权PasswordLogDir string // 日志存储路径RotateTime string // 日志轮转周期,比如:30m, 1h, 24h, 默认是24hMaxAge int64 // 日志最大文件数,默认3LogLevel string // 日志默认级别,值必须是:debug,info,warn,error,默认值是info
}
- ServerConfig
constant.ServerConfig{ContextPath string // Nacos的ContextPath,默认/nacos,在2.0中不需要设置IpAddr string // Nacos的服务地址Port uint64 // Nacos的服务端口Scheme string // Nacos的服务地址前缀,默认http,在2.0中不需要设置GrpcPort uint64 // Nacos的 grpc 服务端口, 默认为 服务端口+1000, 不是必填
}
Note:我们可以配置多个ServerConfig,客户端会对这些服务端做轮询请求
Create client
// 创建clientConfig
clientConfig := constant.ClientConfig{NamespaceId: "e525eafa-f7d7-4029-83d9-008937f9d468", // 如果需要支持多namespace,我们可以创建多个client,它们有不同的NamespaceId。当namespace是public时,此处填空字符串。TimeoutMs: 5000,NotLoadCacheAtStart: true,LogDir: "/tmp/nacos/log",CacheDir: "/tmp/nacos/cache",LogLevel: "debug",
}// 创建clientConfig的另一种方式
clientConfig := *constant.NewClientConfig(constant.WithNamespaceId("e525eafa-f7d7-4029-83d9-008937f9d468"), //当namespace是public时,此处填空字符串。constant.WithTimeoutMs(5000),constant.WithNotLoadCacheAtStart(true),constant.WithLogDir("/tmp/nacos/log"),constant.WithCacheDir("/tmp/nacos/cache"),constant.WithLogLevel("debug"),
)// 至少一个ServerConfig
serverConfigs := []constant.ServerConfig{{IpAddr: "console1.nacos.io",ContextPath: "/nacos",Port: 80,Scheme: "http",},{IpAddr: "console2.nacos.io",ContextPath: "/nacos",Port: 80,Scheme: "http",},
}// 创建serverConfig的另一种方式
serverConfigs := []constant.ServerConfig{*constant.NewServerConfig("console1.nacos.io",80,constant.WithScheme("http"),constant.WithContextPath("/nacos"),),*constant.NewServerConfig("console2.nacos.io",80,constant.WithScheme("http"),constant.WithContextPath("/nacos"),),
}// 创建服务发现客户端
_, _ := clients.CreateNamingClient(map[string]interface{}{"serverConfigs": serverConfigs,"clientConfig": clientConfig,
})// 创建动态配置客户端
_, _ := clients.CreateConfigClient(map[string]interface{}{"serverConfigs": serverConfigs,"clientConfig": clientConfig,
})// 创建服务发现客户端的另一种方式 (推荐)
namingClient, err := clients.NewNamingClient(vo.NacosClientParam{ClientConfig: &clientConfig,ServerConfigs: serverConfigs,},
)// 创建动态配置客户端的另一种方式 (推荐)
configClient, err := clients.NewConfigClient(vo.NacosClientParam{ClientConfig: &clientConfig,ServerConfigs: serverConfigs,},
)
服务发现
- 注册实例:RegisterInstance
success, err := namingClient.RegisterInstance(vo.RegisterInstanceParam{Ip: "10.0.0.11",Port: 8848,ServiceName: "demo.go",Weight: 10,Enable: true,Healthy: true,Ephemeral: true,Metadata: map[string]string{"idc":"shanghai"},ClusterName: "cluster-a", // 默认值DEFAULTGroupName: "group-a", // 默认值DEFAULT_GROUP
})
- 注销实例:DeregisterInstance
success, err := namingClient.DeregisterInstance(vo.DeregisterInstanceParam{Ip: "10.0.0.11",Port: 8848,ServiceName: "demo.go",Ephemeral: true,Cluster: "cluster-a", // 默认值DEFAULTGroupName: "group-a", // 默认值DEFAULT_GROUP
})
- 获取服务信息:GetService
services, err := namingClient.GetService(vo.GetServiceParam{ServiceName: "demo.go",Clusters: []string{"cluster-a"}, // 默认值DEFAULTGroupName: "group-a", // 默认值DEFAULT_GROUP
})
- 获取所有的实例列表:SelectAllInstances
// SelectAllInstance可以返回全部实例列表,包括healthy=false,enable=false,weight<=0
instances, err := namingClient.SelectAllInstances(vo.SelectAllInstancesParam{ServiceName: "demo.go",GroupName: "group-a", // 默认值DEFAULT_GROUPClusters: []string{"cluster-a"}, // 默认值DEFAULT
})
- 获取实例列表 :SelectInstances
// SelectInstances 只返回满足这些条件的实例列表:healthy=${HealthyOnly},enable=true 和weight>0
instances, err := namingClient.SelectInstances(vo.SelectInstancesParam{ServiceName: "demo.go",GroupName: "group-a", // 默认值DEFAULT_GROUPClusters: []string{"cluster-a"}, // 默认值DEFAULTHealthyOnly: true,
})
- 获取一个健康的实例(加权随机轮询):SelectOneHealthyInstance
// SelectOneHealthyInstance将会按加权随机轮询的负载均衡策略返回一个健康的实例
// 实例必须满足的条件:health=true,enable=true and weight>0
instance, err := namingClient.SelectOneHealthyInstance(vo.SelectOneHealthInstanceParam{ServiceName: "demo.go",GroupName: "group-a", // 默认值DEFAULT_GROUPClusters: []string{"cluster-a"}, // 默认值DEFAULT
})
- 监听服务变化:Subscribe
// Subscribe key=serviceName+groupName+cluster
// 注意:我们可以在相同的key添加多个SubscribeCallback.
err := namingClient.Subscribe(vo.SubscribeParam{ServiceName: "demo.go",GroupName: "group-a", // 默认值DEFAULT_GROUPClusters: []string{"cluster-a"}, // 默认值DEFAULTSubscribeCallback: func(services []model.Instance, err error) {log.Printf("\n\n callback return services:%s \n\n", utils.ToJsonString(services))},
})
- 取消服务监听:Unsubscribe
err := namingClient.Unsubscribe(vo.SubscribeParam{ServiceName: "demo.go",GroupName: "group-a", // 默认值DEFAULT_GROUPClusters: []string{"cluster-a"}, // 默认值DEFAULTSubscribeCallback: func(services []model.Instance, err error) {log.Printf("\n\n callback return services:%s \n\n", utils.ToJsonString(services))},
})
- 获取服务名列表
serviceInfos, err := namingClient.GetAllServicesInfo(vo.GetAllServiceInfoParam{NameSpace: "0e83cc81-9d8c-4bb8-a28a-ff703187543f",PageNo: 1,PageSize: 10,}),
动态配置
- 发布配置:PublishConfig
success, err := configClient.PublishConfig(vo.ConfigParam{DataId: "dataId",Group: "group",Content: "hello world!222222"})
- 删除配置:DeleteConfig
success, err = configClient.DeleteConfig(vo.ConfigParam{DataId: "dataId",Group: "group"})
- 获取配置:GetConfig
content, err := configClient.GetConfig(vo.ConfigParam{DataId: "dataId",Group: "group"})
- 监听配置变化:ListenConfig
err := configClient.ListenConfig(vo.ConfigParam{DataId: "dataId",Group: "group",OnChange: func(namespace, group, dataId, data string) {fmt.Println("group:" + group + ", dataId:" + dataId + ", data:" + data)},
})
- 取消配置监听:CancelListenConfig
err := configClient.CancelListenConfig(vo.ConfigParam{DataId: "dataId",Group: "group",
})
- 搜索配置: SearchConfig
configPage,err := configClient.SearchConfig(vo.SearchConfigParam{Search: "blur",DataId: "",Group: "",PageNo: 1,PageSize: 10,
})
工具
client
/** Copyright 1999-2020 Alibaba Group Holding Ltd.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package nacosimport ("fmt""github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client""github.com/nacos-group/nacos-sdk-go/v2/vo"
)func RegisterServiceInstance(client naming_client.INamingClient, param vo.RegisterInstanceParam) {success, err := client.RegisterInstance(param)if !success || err != nil {panic("RegisterServiceInstance failed!" + err.Error())}fmt.Printf("RegisterServiceInstance,param:%+v,result:%+v \n\n", param, success)
}func BatchRegisterServiceInstance(client naming_client.INamingClient, param vo.BatchRegisterInstanceParam) {success, err := client.BatchRegisterInstance(param)if !success || err != nil {panic("BatchRegisterServiceInstance failed!" + err.Error())}fmt.Printf("BatchRegisterServiceInstance,param:%+v,result:%+v \n\n", param, success)
}func DeRegisterServiceInstance(client naming_client.INamingClient, param vo.DeregisterInstanceParam) {success, err := client.DeregisterInstance(param)if !success || err != nil {panic("DeRegisterServiceInstance failed!" + err.Error())}fmt.Printf("DeRegisterServiceInstance,param:%+v,result:%+v \n\n", param, success)
}func UpdateServiceInstance(client naming_client.INamingClient, param vo.UpdateInstanceParam) {success, err := client.UpdateInstance(param)if !success || err != nil {panic("UpdateInstance failed!" + err.Error())}fmt.Printf("UpdateServiceInstance,param:%+v,result:%+v \n\n", param, success)
}func GetService(client naming_client.INamingClient, param vo.GetServiceParam) {service, err := client.GetService(param)if err != nil {panic("GetService failed!" + err.Error())}fmt.Printf("GetService,param:%+v, result:%+v \n\n", param, service)
}func SelectAllInstances(client naming_client.INamingClient, param vo.SelectAllInstancesParam) {instances, err := client.SelectAllInstances(param)if err != nil {panic("SelectAllInstances failed!" + err.Error())}fmt.Printf("SelectAllInstance,param:%+v, result:%+v \n\n", param, instances)
}func SelectInstances(client naming_client.INamingClient, param vo.SelectInstancesParam) {instances, err := client.SelectInstances(param)if err != nil {panic("SelectInstances failed!" + err.Error())}fmt.Printf("SelectInstances,param:%+v, result:%+v \n\n", param, instances)
}func SelectOneHealthyInstance(client naming_client.INamingClient, param vo.SelectOneHealthInstanceParam) {instances, err := client.SelectOneHealthyInstance(param)if err != nil {panic("SelectOneHealthyInstance failed!")}fmt.Printf("SelectOneHealthyInstance,param:%+v, result:%+v \n\n", param, instances)
}func Subscribe(client naming_client.INamingClient, param *vo.SubscribeParam) {_ = client.Subscribe(param)
}func UnSubscribe(client naming_client.INamingClient, param *vo.SubscribeParam) {_ = client.Unsubscribe(param)
}func GetAllService(client naming_client.INamingClient, param vo.GetAllServiceInfoParam) {service, err := client.GetAllServicesInfo(param)if err != nil {panic("GetAllService failed!")}fmt.Printf("GetAllService,param:%+v, result:%+v \n\n", param, service)
}
config
/** Copyright 1999-2020 Alibaba Group Holding Ltd.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package nacosimport ("fmt""github.com/nacos-group/nacos-sdk-go/v2/clients/config_client""github.com/nacos-group/nacos-sdk-go/v2/model""github.com/nacos-group/nacos-sdk-go/v2/vo"
)func PublishConfig(client config_client.IConfigClient, param vo.ConfigParam) {//publish config//config key=dataId+group+namespaceId_, err := client.PublishConfig(param)if err != nil {fmt.Printf("PublishConfig err:%+v \n", err)}
}func DeleteConfig(client config_client.IConfigClient, param vo.ConfigParam) {_, err := client.DeleteConfig(param)if err != nil {fmt.Printf("DeleteConfig err:%+v \n", err)}
}func GetConfig(client config_client.IConfigClient, param vo.ConfigParam) string {//get configcontent, err := client.GetConfig(param)if err != nil {fmt.Printf("GetConfig err:%+v \n", err)} else {fmt.Println("GetConfig,config :" + content)}return content
}func ListenConfig(client config_client.IConfigClient, param vo.ConfigParam) {//Listen config change,key=dataId+group+namespaceId.err := client.ListenConfig(vo.ConfigParam{DataId: "test-data",Group: "test-group",OnChange: func(namespace, group, dataId, data string) {fmt.Println("config changed group:" + group + ", dataId:" + dataId + ", content:" + data)},})if err != nil {fmt.Printf("PublishConfig err:%+v \n", err)}
}func CancelListenConfig(client config_client.IConfigClient, param vo.ConfigParam) {//cancel config changeerr := client.CancelListenConfig(param)if err != nil {fmt.Printf("CancelListenConfig err:%+v \n", err)}
}func SearchConfig(client config_client.IConfigClient, param vo.SearchConfigParam) *model.ConfigPage {searchPage, err := client.SearchConfig(param)if err != nil {fmt.Printf("SearchConfig err:%+v \n", err)} else {fmt.Printf("SearchConfig:%+v \n", searchPage)}return searchPage
}
相关文章:
go 集成nacos注册中心、配置中心
使用限制 Go>v1.15 Nacos>2.x 安装 使用go get安装SDK: go get -u github.com/nacos-group/nacos-sdk-go/v2 快速使用 初始化客户端配置ClientConfig constant.ClientConfig{TimeoutMs uint64 // 请求Nacos服务端的超时时间,默…...

ssd202d-badblock-坏块检测
这边文章讲述的是坏快检测功能 思路: 1.第一次烧录固件会实现跳坏块,但是后续使用会导致坏块的产生; 于是我在uboot环境变量添加了两个变量来控制坏快 lb_badnum //坏块个数 lb_badoff //坏块所在位置 2.第一次开机会根据lb_badnum是否…...

MySQL-练习-数据介绍
文章目录 一. 数据介绍1. 数据结构2. 创建数据库,数据表3. 员工表(employees)练习1 4. 顾客表(customers)练习2 5. 商品(products)和商品类别(categories)表练习3 6. 供应商表(suppliers)练习4 7. 订单和订单明细表练习5 二. 数据汇总三. 使用CASE WHEN …...
React框架:解锁现代化Web开发的新维度
在当今前端开发领域,React 无疑是一颗璀璨的明星。React 是由 Facebook 开发的用于构建用户界面的 JavaScript 库,它在前端开发中占据着重要的地位,为开发者提供了一种高效、灵活且可维护的方式来构建复杂的用户界面。 一、React 的背景与开…...

电阻功率,限流,等效电阻
1 电阻额定功率 2 电阻限流作用 3 电阻并联等效电阻...

Qt | 开发工具(top1)
Qt Creator 跨平台、完整的集成开发环境(IDE),供应用程序开发者创建用于多个桌面、嵌入式和移动设备平台的应用程序。 Qt Linguist 一套将Qt C和Qt Quick应用程序翻译成本地语言的工具。 qmake Qt自动化构建工具,简化了不同平台的构建过程。…...

Node.js express
1. express 介绍 express 是一个基于 Node.js 平台的极简、灵活的 WEB 应用开发框架,官方网址:https://www.expressjs.com.cn/简单来说,express 是一个封装好的工具包,封装了很多功能,便于我们开发 WEB 应用ÿ…...
ios h5中在fixed元素中的input被focus时,键盘遮挡input (van-popup、van-feild)
问题描述: 前提:我使用的是vant组件库,其中一个页面中有一个van-popup组件,van-popup组件中又嵌套了一个van-field组件预期结果:当点击van-feild输入框时,键盘弹起,输入框显示在键盘上方实际结…...

springboot整合lua脚本在Redis实现商品库存扣减
1、目的 使用lua脚本,可以保证多条命令的操作原子性;同时可以减少操作IO(比如说判断redis对应数据是否小于0,小于0就重置为100,这个场景一般是取出来再判断,再存放进行,就至少存在2次IO,用lua脚…...

MySQL ON DUPLICATE KEY UPDATE影响行数
目录 分析为什么Updates返回7 总结 数据库更新日志如下 insertOrUpdateList|> Preparing: INSERT INTO clue_user_tag (vuid, tag_id, tag_type, content) VALUES (?, ?, ?, ?) , (?, ?, ?, ?) , (?, ?, ?, ?) , (?, ?, ?, ?) ON DUPLICATE KEY UPDATE …...
uniapp小程序 slot中无法传递外部参数的解决方案
最近在封装一个List组件,外部传给我数据,我循环后将每个Item部分slot到外部,由调用者自己去写item布局,类似ElementUI、iView的Tabe列表。 List: <view v-if"list.length > 0" class"list-scroll__item&quo…...

umi实现动态获取菜单权限
文章目录 前景登录组件编写登录逻辑菜单的时机动态路由页面刷新手动修改地址 前景 不同用户拥有不同的菜单权限,现在我们实现登录动态获取权限菜单。 登录组件编写 //当我们需要使用dva的dispatch函数时,除了通过connect函数包裹组件还可以使用这种方…...

Pytest-Bdd-Playwright 系列教程(14):Docstring 参数
Pytest-Bdd-Playwright 系列教程(14):Docstring 参数 前言一、什么是docstring?二、基本语法三、主要特点四、实际例子五、注意事项六、使用建议总结 前言 在自动化测试的过程中,我们经常需要处理复杂的测试数据或需要输入多行文…...

交互开发---测量工具(适用VTK或OpenGL开发的应用程序)
简介: 经常使用RadiAnt DICOM Viewer来查看DICOM数据,该软件中的测量工具比较好用,就想着仿照其交互方式自己实现下。后采用VTK开发应用程序时,经常需要开发各种各样的测量工具,如果沿用VTK的widgets的思路,…...

Qt 一个简单的QChart 绘图
Qt 一个简单的QChart 绘图 先上程序运行结果图: “sample9_1QChart.h” 文件代码如下: #pragma once#include <QtWidgets/QMainWindow> #include "ui_sample9_1QChart.h"#include <QtCharts> //必须这么设置 QT_CHARTS_USE_NAME…...

【Java笔记】LinkedList 底层结构
一、LinkedList 的全面说明 LinkedList底层实现了双向链表和双端队列特点可以添加任意元素(元素可以重复),包括null线程不安全,没有实现同步 二、LinkedList 的底层操作机制 三、LinkedList的增删改查案例 public class LinkedListCRUD { public stati…...

el-table组件树形数据修改展开箭头
<style lang"scss" scoped> ::v-deep .el-table__expand-icon .el-icon-arrow-right:before {content: ">"; // 箭头样式font-size: 16px; }::v-deep .el-table__expand-icon{ // 没有展开的状态background-color: rgba(241, 242, 245, 1);color:…...

太速科技-FMC154-基于FMC 八路SFP+万兆光纤子卡
FMC154-基于FMC 八路SFP万兆光纤子卡 一、板卡概述 本卡是一个FPGA夹层卡(FMC)模块,可提供高达8个SFP / SFP 模块接口,直接插入千兆位级收发器(MGT)的赛灵思FPGA。支持业界标准的小型可插拔࿰…...

记:排查设备web时慢时快问题,速度提升100%
问题描述 问题1: 发现web登录界面刷新和登录功能都比较卡,开浏览器控制台看了下,让我很惊讶,居然能这么慢: 公司2个局域网内的表现不同,局域网A中的都比较卡,局域网B中的又不存在该现象。 问…...
音视频入门基础:MPEG2-TS专题(13)——FFmpeg源码中,解析Section Header的实现
一、引言 在《音视频入门基础:MPEG2-TS专题(11)—— TS中的Section》中讲述了Section Header的基本概念,本文讲述FFmpeg源码中是怎样解析Section Header的。 二、parse_section_header函数的定义 FFmpeg源码中通过parse_section…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...

2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...