JAVA接入OPC DA2.0引发的问题
创始人
2024-02-07 12:31:54

背景:

JAVA接入OPC DA后,在生产环境跑了一段时间后就会出现异常,给折腾的够呛,起初的报错还能通过重启OPC连接解决,后来强制重新连接也不行,最终一套测试下来,除非重启OPC服务器,别无他法!简单说下几个错误及导致的原因,以及给出解决方案!

错误一:An internal error occurred. [0x8001FFFF]

查询了很多资料无果,只有一些有年代的提问:An internal error occurred. [0x8001FFFF]
后来发现可以通过重启解决,于是有了直接判断异常,相同则重启OPC,解决燃眉之急。

        if ("An internal error occurred. [0x8001FFFF]".equals(e.getMessage())) {OpcUtils.forceReconnect();}

但目前并未查到原因!

错误二:org.jinterop.dcom.common.JIException: Message not found for errorCode: 0x800700A4

后来跑了一段时间后发现一直报异常0x800700A4,而且重连再也无法建立链接,但是可以打印OPC服务器的服务,只是无法建立连接!此时的我已经要炸了!由于测试环境无法达成与生产环境完全一致,无法进行测试,只能搜索问题,更头大的是使用OPC客户端软件也无法建立连接,此刻已经无解了。

查了很多,有的说是COM无法创建更多线程,也有说是windows系统bug,内存泄露需要更新补丁!但是依旧无有效解决方案。由于客户端也连接不上只能认为是OPC服务软件的问题了,每次重启都会恢复,运行一段时间就不行,但是OPC服务本身无任何问题。于是猜想DCOM有问题,我又写了一个基于COM的中转程序,想着本地连接肯定没问题了吧,很自信!

结果开心的时刻来了,跑去生产环境去部署发现COM方式也连接不上,脸打的生疼!最终还是完整部署了一份和生产环境一致的测试环境,经过我不懈的压测,最终OPC服务软件报了个错!(擦 生产环境为何没有),就因为这个错误提示,才引起我对一段代码的怀疑,之前觉得有疑惑但是没管它。

JAVA通过COM方式(jeasyopc)接入OPC DA

定位到问题

仅仅一个服务端OPC软件的异常 “AddGroup”,让我想起一段代码:

        //TODO 同步读取数据try {Group group = server.addGroup();Map itemMap = group.addItems(itemIds.toArray(new String[0]));List result = new ArrayList<>();for (Map.Entry entry : itemMap.entrySet()) {Item item = entry.getValue();ItemState itemState = item.read(true);DataItem dataItem = JiVariantUtil.parseValue(item.getId(), itemState);result.add(dataItem);}
//            group.clear();
//            server.removeGroup(group,false);return result;} catch (Exception e) {log.error("同步读取失败!", e);return null;}

这段查询代码来源于网络,当时很纳闷为何注释了两行,因为也浅显的了解了下OPC知识,知道关于group分组是在客户端定义,当时脑里的思路还在想正常定义分组应该初始化定义好同步给OPC服务器,后面直接拿分组名称用就是了,这里等于每次都会新增分组,注释的是清除,现在想想也真是大意了,狠狠的吃了把偷懒的亏!

结论显而易见,由于不断的addGroup,导致OPC服务器崩溃了。

优化代码

方法一

最简单的优化方式,每次新增,并且每次移除,只需要把注释的代码修改为:

server.removeGroup(group,true);

本人已压测过千万次查询写入,没有问题,效率会低点。

方法二

当前最优解应该是项目启动的时候初始化分组,addGroup后记录分组的名称,并在后续的交互中使用Group名称进行交互!写的过程中才发现,原来自带了很多方法就是为了这么用的,没文档,只能看代码了。大致列下实现:

   public static List getOrCreateOpcItem(Collection itemIds) {Server server = getServer();if (Objects.isNull(server)) {log.error("OPC 获取OPC item时,服务为空!获取ItemIds:{}", itemIds);return null;}String key = String.join(",", itemIds);List result = new ArrayList<>();try {try {Group group = server.findGroup(key);List integers = OpcUtils.itemClientHandleMap.get(key);for (Integer integer : integers) {result.add(group.findItemByClientHandle(integer));}} catch (UnknownGroupException e) {Group group = server.addGroup(key);Map itemMap = group.addItems(itemIds.toArray(new String[0]));result = new ArrayList<>(itemMap.values());OpcUtils.itemClientHandleMap.put(key, result.stream().map(Item::getClientHandle).collect(Collectors.toList()));}} catch (Exception e) {log.error("OPC 查询/创建OPC Group及Item异常,ItemIds:{}", itemIds, e);return null;}return result;}public static void writeSync(String itemId, Boolean value) {try {List orCreateOpcItems = getOrCreateOpcItem(List.of(itemId));if (Objects.isNull(orCreateOpcItems)) {log.error("OPC-Sync write failed! 获取item失败,ItemId: {}, Value: {}", itemId, value);return;}Item item = orCreateOpcItems.get(0);JIVariant jiVariant = new JIVariant(value);item.write(jiVariant);} catch (Exception e) {log.error("OPC-Sync write failed! ItemId: {}, Value: {}", itemId, value, e);}}public static List readSync(Collection itemIds) {try {List orCreateOpcItems = getOrCreateOpcItem(itemIds);if (Objects.isNull(orCreateOpcItems)) {log.error("OPC-Sync read failed! 获取item失败,ItemId: {}", itemIds);return null;}List result = new ArrayList<>();for (Item item : orCreateOpcItems) {ItemState itemState = item.read(true);DataItem dataItem = JiVariantUtil.parseValue(item.getId(), itemState);result.add(dataItem);}return result;} catch (Exception e) {log.error("同步读取失败!itemIds:[{}]", itemIds, e);return null;}}

OPC DA客户端工具(从KEPServerEX 6精简):

链接: https://pan.baidu.com/s/1kAZJHdIDxOxjIXhdfnLJ_Q?pwd=his3

提取码: his3

总结

  1. 测试环境一定要与生产环境完全一致!
  2. 一定测试!长时间压测!
  3. 补足基础知识,查看源码,正确使用方式其义自见

参考:

microsoft security essentials errorcode 0x800700a4
.Net: I got the following exception InteropServices.COMException: "No more threads can be created in the system.

相关内容

热门资讯

苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...