最近在金蝶云苍穹的开发服务云里预览应用时,我遇到了一个看起来很像网络故障的问题。
点击预览后,页面直接提示功能异常,服务端的关键报错是:
请求FormService:createConfig失败,原因:未发现AppIdName(r1h7_office_manage)服务或访问服务网络异常.错误码:1002
错误里带着“访问服务网络异常”,一开始很容易把注意力放到 Kubernetes 网络、Dubbo 或 Zookeeper 上。但最后查下来,网络并没有问题,真正漏掉的是对应 .lib 文件中的一项应用配置。
这次使用的是金蝶云苍穹/星瀚 8.0.4.4,本地部署在 Kubernetes 中,命名空间为 ierp-cluster。出问题的应用编码是 r1h7_office_manage,它建在已有的低代码/开发云下,并不是新建了一个云。
从日志确认服务没有注册
查看 mservice 日志时,我发现 Dubbo/Zookeeper 没有找到这个应用对应的 provider:
group=r1h7_office_manage
urls: [empty://0.0.0.0/...]
invokers not available
也就是说,预览时 mservice 想调用 r1h7_office_manage 对应的 DispatchService,但运行时根本没有注册这个应用的服务。
多个页面预览时都出现了相同错误,而且报错都集中在 FormService:createConfig 和 AppIdName 服务查找上,因此基本可以排除某个页面控件或表单字段配置错误。
走过的弯路:给容器设置 appids
看到应用服务没有注册后,我先尝试给 mservice 增加环境变量:
sudo kubectl set env deployment/mservice \
-n ierp-cluster \
appids=r1h7_office_manage,r1h7_test1
环境变量确实进入了容器,但重启后日志里依然没有出现下面这类注册记录:
Register dubbo service kd.bos.service.DispatchService ... group=r1h7_office_manage
我也试过大小写不同的 appIds,结果反而让系统出现了更严重的不可用提示。到这里可以确认,单独设置 Kubernetes 环境变量并不能解决这个问题。
真正容易混淆的地方也在这里:后面要修改的 <appIds> 是 .lib 文件中的 XML 节点,不是容器环境变量 appids。
真正生效的是 nocode.lib
根据 domain 部署模式的资源加载方式,容器启动时会通过 BOSLIBS、TRDLIBS、BIZLIBS、CUSLIBS、libs、domain 等参数从应用仓库加载资源。已有云下面新增应用时,还需要把应用编码写进对应 .lib 文件的 <appIds> 节点。
我先列出了 appstore 中的 .lib 文件:
sudo find /kingdee/cosmic/nginx-appstatic/store/appstatic/appstore/cosmic \
-maxdepth 2 -type f -name "*.lib" 2>/dev/null \
| sort
低代码云对应的文件是:
/kingdee/cosmic/nginx-appstatic/store/appstatic/appstore/cosmic/nocode.lib
查看文件内容:
sudo sed -n '1,160p' \
/kingdee/cosmic/nginx-appstatic/store/appstatic/appstore/cosmic/nocode.lib
当时文件里的配置是:
<root>
<libs>
<lib>bos/bos.xml,bos-nocode.xml</lib>
<lib>trd/trd.xml</lib>
</libs>
<appIds>nocode</appIds>
</root>
问题到这里就清楚了:运行时只加载了 nocode,并不知道新应用 r1h7_office_manage 的存在。mservice 启动后自然不会注册它的 DispatchService,预览时也就找不到 group=r1h7_office_manage。
修改配置
先备份原文件:
lib=/kingdee/cosmic/nginx-appstatic/store/appstatic/appstore/cosmic/nocode.lib
sudo cp "$lib" "$lib.bak.$(date +%Y%m%d%H%M%S)"
然后把新应用编码追加到 <appIds> 中。修改前是:
<appIds>nocode</appIds>
修改后是:
<appIds>nocode,r1h7_office_manage</appIds>
可以直接执行:
sudo sed -i \
's#<appIds>nocode</appIds>#<appIds>nocode,r1h7_office_manage</appIds>#' \
"$lib"
sudo sed -n '1,80p' "$lib"
确认 .lib 文件无误后,清掉之前试错时加入的环境变量,并让 mservice 使用 nocode.lib:
ns=ierp-cluster
sudo kubectl set env deployment/mservice \
-n "$ns" \
appids- appIds- libs=nocode.lib
sudo kubectl rollout status deployment/mservice -n "$ns"
不要只看 Pod 启动成功
Pod 正常运行并不代表应用服务已经注册。重启完成后,我先检查了容器中的环境变量:
pod=$(sudo kubectl get pods \
-n "$ns" \
-l app=mservice \
-o jsonpath='{.items[0].metadata.name}')
sudo kubectl exec -n "$ns" "$pod" -- sh -c \
'env | egrep "domain|libs|appids|appIds|appSplit|APPSTORE_URL"'
这里应该能看到:
libs=nocode.lib
同时不应该再有之前误加的 appids 或 appIds。
最后,再从日志中确认目标应用的服务注册情况:
sudo kubectl exec -n "$ns" "$pod" -- sh -c \
'grep -R -n "r1h7_office_manage\|group=r1h7_office_manage\|Register dubbo service kd.bos.service.DispatchService" /mservice/logs 2>/dev/null | tail -120'
看到类似下面的记录,才说明配置真正生效:
Register dubbo service kd.bos.service.DispatchService ... group=r1h7_office_manage
再次打开应用预览后,页面恢复正常。
出问题时怎么回滚
如果修改后服务出现异常,可以恢复最近一次备份,再移除相关环境变量:
sudo cp \
"$(ls -t /kingdee/cosmic/nginx-appstatic/store/appstatic/appstore/cosmic/nocode.lib.bak.* | head -1)" \
/kingdee/cosmic/nginx-appstatic/store/appstatic/appstore/cosmic/nocode.lib
sudo kubectl set env deployment/mservice \
-n ierp-cluster \
libs- appids- appIds-
sudo kubectl rollout status deployment/mservice -n ierp-cluster
最后总结
这次最费时间的地方,不是命令有多复杂,而是两个长得很像的配置很容易被当成一回事:
.lib文件中的<appIds>决定已有云需要加载哪些应用。- Kubernetes 环境变量
appids并不能替代这里的 XML 配置。 - 这次是在已有低代码云下新增应用,不需要另写一个
cloud-r1h7.lib。 - 修改前要备份,修改后要从日志确认目标
group已经完成服务注册。
以后再遇到“未发现 AppIdName 服务”,我会先看对应应用有没有出现在运行时使用的 .lib 文件里,再去排查网络和注册中心。至少在这次环境中,这比直接给容器追加环境变量有效得多。