首页 > 默认 > HZERO PaaS平台-Docker版demo笔记(二)Docker版测试 问题5-9

HZERO PaaS平台-Docker版demo笔记(二)Docker版测试 问题5-9

2025年12月9日

问题五、知识问答涉及的跨域访问问题,HKMS服务访问问题和大模型APIkey问题。

测试知识问答,浏览器控制台看到的错误信息是:

Access to XMLHttpRequest at ‘http://aigc.hzero.com.cn/v1/open/image-emb/common’ from origin ‘http://dev.hzero.com.cn’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

分析:这是跨域访问被阻止了,按照元宝建议,nginx反向代理添加内容:

        # 添加CORS响应头

        add_header ‘Access-Control-Allow-Origin’ ‘http://dev.hzero.com.cn’ always;

        add_header ‘Access-Control-Allow-Methods’ ‘GET, POST, OPTIONS, PUT, DELETE’ always;

        add_header ‘Access-Control-Allow-Headers’ ‘DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization’ always;

        add_header ‘Access-Control-Expose-Headers’ ‘Content-Length,Content-Range’ always;

        add_header ‘Access-Control-Allow-Credentials’ ‘true’ always;

重启动nginx

知识库问答执行错误:

控制台错误显示交叉验证策略阻止了访问。

分析:

Aigc.hzero.com.cn是个反向代理地址,浏览器发现有跨域访问,会给目标跨域地址发个预检请求(options类型), 反向代理默认会把所有请求发给被代理的服务,也就是后端的hzero-aip-app:8088, hzero-aip-app会怎么处理呢?看hzero-aip-app的application.yml,其中关于跨域访问的配置是:

    # 跨域配置

    cors:

      allowed-origins:

      – ${HZERO_AIP_CORS_ALLOWED_ORIGINS:*}

      allowed-headers:

      – ${HZERO_AIP_CORS_ALLOWED_HEADERS:*}

      allowed-methods:

      – ${HZERO_AIP_CORS_ALLOWED_METHODS:*}

也就是说允许任何来源任何方法(按理应该包含options预检方法),所以正常应该是可以的。然后有重新翻了下开放平台上AIGC的部署文档,发现在反向代理的配置的地方跟原来的版本有变化,按照新的变化,更新了nginx反向代理的配置:

  server {

        listen       80;

        server_name  aigc.hzero.com.cn;

        location / {

          proxy_pass http://hzero-aip-app:8088;

          proxy_set_header Host $host:$server_port;

          proxy_set_header X-Real-IP $remote_addr;

          proxy_set_header Host $host;

          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

          proxy_buffering off;

        }

  }

重启nginx,再测试:

这次没有报跨域访问的错误,只是说链接KMS出了问题,不过这并不稳定,全部容器重启后再次访问,还是出现跨域访问被block的问题,提示很明确:No ‘Access-Control-Allow-Origin’ header is present on the requested resource. 看了哪些网络请求,确实也没提供 Access-Control-Allow-Origin

解决方案:还是在nginx中配置aigc.hzero.com.cn反向代理的地方修改,按照豆包建议做各种nginx的配置修改都没用,最后还是恢复文档中简单配置就又好用了。而且在正常好用的情况下,也没在请求标头中看到Access-Control-Allow-Origin,单独打开没有缓存的chrome测试也是好的。那看来所谓的不稳定表现是原来Edge浏览器缓存原因? nginx配置上不复杂,就按文档就行?后面在多测测吧。

连接KMS的问题:

链接KMS出了什么问题呢?我们查hzero-aip-app服务的日志:

2025-11-29T22:33:19.068+08:00 ERROR 1 — [hzero-aip-app] [r-http-epoll-16] o.h.a.k.domain.search.SearcherWithFlux : HKMS 调用异常:

org.springframework.web.reactive.function.client.WebClientRequestException: finishConnect(..) failed: Connection refused: hzero-hkms/172.18.0.27:18080

从日志看,hzero-aip-app链接HKMS时,链接被拒绝了。那我们先测试这两个容器之间的连通性:

Hzero-aip-app 容器测试访问hzero-hkms:

# echo ‘public class Test { public static void main(String[] args) { try (java.net.Socket s = new java.net.Socket()) { s.connect(new java.net.InetSocketAddress(“hzero-hkms”, 18080), 3000); System.out.println(“✅ 连通成功!”); } catch (Exception e) { System.out.println(“❌ 连通失败: ” + e.getMessage()); } } }’ > Test.java && javac Test.java && java Test && rm -f Test.java Test.class

Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8 -Duser.language=zh -Duser.region=zh_CN -Duser.country=zh_CN

Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8 -Duser.language=zh -Duser.region=zh_CN -Duser.country=zh_CN

❌ 连通失败: Connection refused

测试下来就是联通失败,看hzero-hkms容器的ip地址,确实是172.18.0.27,而在hzero-aip-app的application.yml中关于HKMS服务的配置是:
      llama:

        gateway-path: ${HZERO_KNOWLEDGE_LLAMA_GATEWAY_PATH:http://hzero-hkms:18080}

这么说,aip-aip-app服务,根据配置中的hzero-hkms这个容器服务名正确的解析了其IP地址。也就是网络可达,但链接被拒绝了。猜测是 HKMS的服务访问策略里面做了什么设置,拒绝了某些来源的链接。通常这种设置在哪里呢?我们在浏览器直接访问hkms服务 http://locaohost:18080 是有响应的。

那么拒绝访问的设置是在hkms服务的web配置中?

我先在容器外,linux 主机中测试下链接HKMS服务,是否能成功:

# echo ‘public class Test { public static void main(String[] args) { try (java.net.Socket s = new java.net.Socket()) { s.connect(new java.net.InetSocketAddress(“localhost”, 18080), 3000); System.out.println(“✅ 连通成功!”); } catch (Exception e) { System.out.println(“❌ 连通失败: ” + e.getMessage()); } } }’ > Test.java && javac Test.java && java Test && rm -f Test.java Test.class
✅ 连通成功!

突然发现自己好傻,18080端口是映射到容器外的端口,在容器里面当然访问不了。

解决方案:

更改 hzero-aip-app的application.yml 更改hkms服务的端口,从 18080 改成80

      llama:

        gateway-path: ${HZERO_KNOWLEDGE_LLAMA_GATEWAY_PATH:http://hzero-hkms:80}

对hzero-hype服务调用的配置端口也要改成80;

同样的问题在hzero-aip-server中也存在,hzero-hkms服务的端口要改成80.

修改完成后,重新构建jar, docker镜像,重启动hzero-aip-app服务 和hzero-aip-server服务。

再次测试知识库问答:

这次没有之前连不上HKMS的错误了,提示了一个新的错误,好型跟大模型调用有关:

查hzero-aip-app服务日志

Caused by: org.springframework.web.client.ResourceAccessException: I/O error on POST request for “https://ark.cn-beijing.volces.com/api/v3/chat/completions”: ark.cn-beijing.volces.com

是调用大模型API遇到了IO意外,没有更详细的信息,不过类似的问题在文档向量化处理时提供了更详细的信息,其实就是无法解析大模型API中的域名:

难道是我们把hzero-aip-app放到容器内去运行了,容器内只能解析docker网络内的容器服务名,确实无法解析大模型API的域名?

在模型账号对接的测试的地方也是遇到同样的问题了:出现了DNS 错误。

想着问下豆包如何解决容器内服务访问外网问题,但是豆包断网了。嗯,想起来了,已经是凌晨12点了,家里的wifi设置了自动断网,

临时链接下手机热点,继续问豆包,但是,突然想起这可能是我断网导致的吧,于是再测试模型账号对接测试:发现正常了。确实是断网的原因。

再做文档向量同步也成功了:

知识问答,报了另外一个错误,说是API KEY 错误,大概是重排模型的APIkey 还没填进去

输入正确的api Key之后再测,知识库问答就OK了:

所以核心问题是容器服务hzero-hkms 的端口问题,我们正常再hzero-aip-app服务和hzero-aip-server服务的application.yml中配置的是容器映射到外面的端口,但是在docker compose 网络内部,不能用映射到外面的端口18080,必须是容器内的端口80。

不过,仔细一想,我们在hzero-aip-app和hzero-aip-server的yml配置文件中对hkms访问的端口改成容器的端口也不行,因为我们还要兼容hzero-aip-app和hzero-aip-server两个服务本身没有在docker 容器内运行的情况。所以最合理的做法是保持hzero-aip-app和hzero-aip-server 的yml配置中的18080端口,但是把HKMS的nginx 的web服务端口从80改成18080,这样hkms容器内外端口就保持一致,可以兼容hzero-aip-app和hzero-aip-server服务在docker compose网络内访问和网络外访问的情况。

执行:

Hzero-aip-app 和hzero-aip-server 对hkms的访问端口配置还是恢复到18080, 更改hkms容器Nginx的web服务端口为18080; 更改hkms 容器的docker-compose.yml中的端口映射为18080:18080;

hype服务也要类似做更改,hype容器之前配置的时候,没有把容器内的web服务配置文件挂载出来,所以在hype的docker-compose.yml中要做下挂载

先在volumes中新建hype目录

$ cd /d01/hzero-dockers/volumes

$ mkdir hype

$ sudo chown -R 33:33 ../volumes/hype

$ sudo chmod -R 755 ../volumes/hype

启动hype 容器

$ cd /d01/hzero-dockers/hzero-hype-docker

$ docker compose up -d

#把原来的web服务启动文件拷贝出来

$ docker cp hzero-hype:/root/execute/bin/start.sh /d01/hzero-dockers/volumes/hype/

#关闭容器

更改 /d01/hzero-dockers/volumes/hype/start.sh, 把端口从80改成10080

#docker-compose.yml中挂载

    volumes:

      – ${DOCKER_VOLUME_DIRECTORY:-../volumes}/hype/start.sh:/root/execute/bin/start.sh

#再启动容器,OK了:

不过有个问题始终存在,那就是每次容器服务全部重启之后再去测试《我的HZERO运营知识库》知识库问答的时候,当我们开始输入问题的时候,系统就会去找相似问题提供选择,这时就会调用aigc.hzero.com.cn 网关中的API了,这个时候涉及跨域,因为我们的原始域是dev.hzero.com.cn , 浏览器发送请求给aigc.hzero.com.cn的时候会告诉服务端这是跨域,等服务端返回消息,要看返回消息中是否包含 响应头(服务器配置):Access-Control-Allow-Origin,并且Access-Control-Allow-Origin 明确是包含了发送的原始域,或者*(所有域);如果返回的消息中没包含,那么浏览器就拒绝把响应消息返回给浏览器前端用户,直接阻塞掉了。

目前测试中发现,当nginx 和 hzero-aip-app 都放在docker容器中运行的时候,nginx的配置中反向代理的域名aigc.hzero.com.cn 指向容器服务名hzero-aip-app:8088 的时候,服务返回的响应中没有Access-Control-Allow-Origin,从而导致被浏览器的Cors(跨域资源共享)策略阻塞。这个时候,如果我们在nginx.conf中配置加上 Access-Control-Allow-Origin: ‘dev.hzero.com.cn’ 也会促发错误,错误信息是Access-Control-Allow-Origin只允许有一条,但实际有两条Access-Control-Allow-Origin: ‘dev.hzero.com.cn’  和 Access-Control-Allow-Origin: ‘*’ , 我们在hzero-aip-app的服务yml配置中明确是:

    # 跨域配置

    cors:

      allowed-origins:

      – ${HZERO_AIP_CORS_ALLOWED_ORIGINS:*}

      allowed-headers:

      – ${HZERO_AIP_CORS_ALLOWED_HEADERS:*}

      allowed-methods:

      – ${HZERO_AIP_CORS_ALLOWED_METHODS:*}

所以,正常hzero-aip-app服务返回的响应中肯定是包含Access-Control-Allow-Origin: ‘*’ 的,加上nginx中配置增加的Access-Control-Allow-Origin: ‘dev.hzero.com.cn’就会出现浏览器提示的错误。 不过诡异的是: 既然浏览器能获得后端服务返回的Access-Control-Allow-Origin: ‘*’ ,那为什么在我的nginx配置中没有增加Access-Control-Allow-Origin: ‘dev.hzero.com.cn’的时候他就获取不到呢? 好了,因为我们在nginx配置中国增加了Access-Control-Allow-Origin而出现重复的Access-Control-Allow-Origin错误之后,我们在nginx配置中把这一条删除掉了,浏览器就不报错了,然后就能正常访问了。这个时候我们可以明确看到,响应头中包含了我们在nginx配置中曾经添加的 Access-Control-Allow-Origin: ‘dev.hzero.com.cn’

那为什么我们明确的已经在nginx的配置文件中删除了这条配置了,他还能在响应头中出现呢?是因为缓存吗? 是哪里的缓存呢?

  1. 删除浏览器数据,刷新,重新登录,响应头中依然包含。工作正常,看起来不是客户端本地缓存。
  2. 重启nginx服务,刷新,响应头中依然包含。工作正常,看起来不是web服务端缓存。
  3. 重启hzero-aip-app服务,响应头中依然包含。工作正常,看起来不是后端服务端缓存。
  4. 重启hzero-gateway服务,响应头中依然包含。工作正常,看起来不是后端服务端缓存。
  5. 究竟是哪里缓存的呢?

#Nginx容器内执行:
# curl -H ‘Origin: dev.hzero.com.cn’ \

-H ‘Authorization: Bearer 7a67e4b8-998d-4e74-a9b8-0f2da0f4da9e’ \

http://hzero-aip-app:8088/v1/open/knowledge/search-question?tenantId=0 \

-i> > >

HTTP/1.1 200 OK

Vary: Origin

Vary: Access-Control-Request-Method

Vary: Access-Control-Request-Headers

Access-Control-Allow-Origin: dev.hzero.com.cn

Access-Control-Expose-Headers: date, content-encoding, server, etag, vary, Cache-Control, Last-Modified, content-type, transfer-encoding, connection, x-application-context, content-disposition

Access-Control-Allow-Credentials: true

Content-Type: application/json

Content-Length: 95

Cache-Control: no-cache, no-store, max-age=0, must-revalidate

Pragma: no-cache

Expires: 0

X-Content-Type-Options: nosniff

X-Frame-Options: DENY

X-XSS-Protection: 0

Referrer-Policy: no-referrer

以上是不通过代理,直接访问http://hzero-aip-app:8088,在给了Origin: dev.hzero.com.cn后,返回包含了Access-Control-Allow-Origin: dev.hzero.com.cn,说明这个确实是后端服务hzero-aip-app返回的,不是nginx返回的。

说明:Access-Control-Allow-Origin: dev.hzero.com.cn 既不是 nginx 配置残留,也不是缓存,而是 后端 hzero-aip-app 的 Spring Boot CORS 框架「动态生成」的!

为什么后端配置 allowed-origins: *,却返回了具体的 dev.hzero.com.cn?

这是 Spring Boot CORS 框架的「隐式适配逻辑」,专门针对「带凭证的跨域请求」:

你的后端配置了 Access-Control-Allow-Credentials: true(响应头中已显示);

根据 CORS 标准:带凭证(Cookie/Token)的跨域请求,Access-Control-Allow-Origin 不能是 *(浏览器会拒绝);

因此 Spring Boot CORS 框架会「智能适配」:当配置 allowed-origins: * 且 allow-credentials: true 时,框架不会返回字面的 *,而是 动态返回请求头中的 Origin 值(即 dev.hzero.com.cn),既满足标准,又实现了「允许所有源 + 带凭证」的需求。

这就是一直困惑的核心原因 —— 后端配置的 * 是「逻辑上允许所有源」,但实际返回的是「请求的具体源」,而非字面的 *。

但是,但是。。。为啥第二天重启平台服务之后,他又会报CORS错误了?

  • 切换到浏览器无痕模式再试,响应头中依然包含。工作正常,看起来也不是缓存问题。
  • 关闭系统代理开机自启,重启服务器,重启整个平台服务,用浏览器无痕模式,再试:

问题就重现了:

第一次调用,响应标头是空的:

第二次调用,响应表头,有内容,并且有明确的错误提示:

我们把注意力集中在502 Bad Gateway上:

这个时候先看nginx中的log:
#1
172.18.0.1 – – [01/Dec/2025:06:49:45 +0000] “OPTIONS /v1/open/knowledge/search-question?tenantId=0 HTTP/1.1” 502 559 “http://dev.hzero.com.cn/” “Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0” “-“

#2

2025/12/01 06:49:45 [error] 32#32: *7 connect() failed (113: No route to host) while connecting to upstream, client: 172.18.0.1, server: aigc.hzero.com.cn, request: “OPTIONS /v1/open/knowledge/search-question?tenantId=0 HTTP/1.1”, upstream: “http://172.18.14.48:8088/v1/open/knowledge/search-question?tenantId=0”, host: “aigc.hzero.com.cn”, referrer: “http://dev.hzero.com.cn/”

#3

172.18.0.1 – – [01/Dec/2025:06:56:17 +0000] “GET / HTTP/1.1” 200 4959 “-” “Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134” “-“

172.18.0.1 – – [01/Dec/2025:06:56:18 +0000] “GET /adfs/probe HTTP/1.1” 200 4959 “-” “Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134” “-“

在nginx的日志中,
#1我们看到一条来自客户端 172.18.0.1的options预检请求:

这个172.18.0.1 是我们运行的docker compose网络的网关,也就是运行该docker网络的linux虚拟机的IP地址。

$ docker network inspect hzero-demo | grep -E “Subnet|Gateway”
“Subnet”: “172.18.0.0/16”,
“Gateway”: “172.18.0.1”

   #2这里的upstream指的是上游服务器,说是针对来自172.18.0.1的options预检请求,去链接上游服务器172.18.14.48:8088的时候报错了。这当然会报错,因为不在一个网段内,nginx是运行在容器网络里面的,其自己的IP地址可以看到是:

$ docker inspect –format ‘{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}’ nginx-hzero
172.18.0.2

所以会报bad gateway;

这也就解释了:为什么nginx运行在linux 本机而不是容器内时,不会出问题了。

而 upstream: “http://172.18.14.48:8088/v1/open/knowledge/search-question?tenantId=0″表明nginx把反向代理的配置 hzero-aip-app这个docker容器的服务名错误的

我们来捋一捋:

把这个问豆包,豆包说上游服务器是指具体业务服务,那应该不是172.18.14.48,应该是hzero-aip-app服务乃容器对应的IP才对。

按理说容器内的nginx应该去解析容器服务名hzero-aip-app在容器网络中IP地址,为什么会去解析到容器外的linux主机IP地址?那豆包说了:Nginx 默认不会动态解析服务名(hzero-aip-app),而是在启动时缓存一次 DNS 结果。而 Docker 的服务名解析依赖内置 DNS 服务器(127.0.0.11),若 Nginx 未指定该 DNS,可能会走系统默认 DNS,导致解析错误。

在容器内执行解析命令(用nslookup或ping,若没有nslookup可先装:apt update && apt install dnsutils):

核心修复:给 Nginx 配置「Docker 内置 DNS 解析器」

Nginx 默认不会动态解析服务名(hzero-aip-app),而是在启动时缓存一次 DNS 结果。而 Docker 的服务名解析依赖内置 DNS 服务器(127.0.0.11),若 Nginx 未指定该 DNS,可能会走系统默认 DNS,导致解析错误。

在server块或http块中添加resolver配置,强制 Nginx 使用 Docker 内置 DNS,并设置短缓存(避免解析过时)

    # 核心:添加Docker内置DNS解析器(必须加!)

    resolver 127.0.0.11 valid=60s;  # 127.0.0.11是Docker默认DNS,valid=60s定期刷新解析

resolver_timeout 5s;  # DNS解析超时时间

重启nginx 后问题解决。

回顾:我们之前曾经在windows的hosts文件中添加过对hzero-aip-app的解析,如果碰到异常场景就可能出现这种问题:

异常场景 :Nginx 未配置 resolver(依赖容器默认 DNS)

此时容器内的 Nginx 会使用容器 /etc/resolv.conf 中的 DNS 顺序(优先 127.0.0.11,后备宿主机 DNS):

正常情况下,还是会通过 127.0.0.11 解析到正确的容器 IP,Windows hosts 配置依然无效;

极端情况(比如 Docker 内置 DNS 故障,概率极低):若 127.0.0.11 无法响应,Nginx 会 fallback 到宿主机 DNS;

此时宿主机 DNS 解析 hzero-aip-app 时,会先查询 Windows hosts 文件 —— 如果 hosts 中配置了该域名的映射(如 1.2.3.4),就会返回这个错误 IP,导致 Nginx 代理失败。

但这不是 “冲突”,而是 “配置不规范导致的解析异常”:根源是 Nginx 未显式配置 resolver,而非 hosts 文件和 Docker DNS 的冲突。

问题六、无痕模式下,本地存在代理(VPN)的情况下无法访问:

现象,打开浏览器的无痕模式,访问dev.hzero.com.cn,结果出现:

点继续浏览后,就被阻塞了,死活无法进入下一步,打开检查发现:返回网关错误,去访问什么一个本地的7890端口去了。

元宝分析

根本原因分析:​​

代理端口冲突​(核心原因)

  1. 无痕模式未正确加载代理扩展或配置,导致请求被发送到 127.0.0.1:7890(本地代理端口)
    1. 该端口无活跃代理服务监听,造成网关错误(502)

解决方案:关闭本地系统代理软件。

再次访问,可以继续了。。

问题七、垃圾文件太多的问题

现象:在hzero_hfile.hfle_file表中发现大量的来自接口平台的定时任务的健康检查日志文件,每分钟产生2个文件,所以文件和文件表中的记录就非常多。

看了下定时任务的配置情况:

解决方案:

  1. 在 平台/调度服务/调度管理/调度任务 菜单进入,搜索“接口健康检查”先停掉接口平台健康检查的定期任务。
  2. 执行接口平台日志清理任务:

虽然显示完成了,但去hfle_file表看,并没有清除表中记录:

3、清除调度日志:

但实际只清除了hsdr_job_log表

并没有连带清除 hfle_file表,hfle_file表里面数据没变化.

去平台/开发管理/数据清理/数据清理配置处,执行了平台的数据清理日志和调度日志清理,也没有删除hfle_file表中的日志文件记录:

其他地方找不到系统界面上还有能清除的地方了,那么接下来只能手工清理了:

4、清除文件:在平台/文件管理/文件汇总查询的地方:

查询条件:HITF.HELTH_CHECK, 批量:100条,彻底删除,删除前,先看下minio桶里面的文件:

我看看执行后,是不是minio桶的文件也一并清除了:

实验结果,确实是minio桶的文件也一并被清除了。

不过每次100条,有4万多条要删除,这样删太慢了,接下来,直接删表删文件

select count(1) from hzero_file.hfle_file a where a.directory =’hsdr01/’ and a.file_name like ‘HITF.HEALTH_CHECK%’

–38890 条;

select count(1) from hzero_file.hfle_file a where a.directory =’hsdr01/’ 

–38891 条;

也就是说,目前调度任务日志都是接口平台的健康检查日志,所以一会儿去minio桶里头删除文件的时候,可以把hsdr01/0/MINO目录下的文件全部删除:

执行:

  1. 数据库记录删除:delete from hzero_file.hfle_file a where a.directory =’hsdr01/’ 
  2. MINO桶文件删除:进入hz-hsdr/hsdr01/0/MINIO目录,全选文件,然后点删除。

删除完成发现:hsdr01目录及其所有子目录都被删除掉了

这下OK了,只有100多个真正有用的文件记录了。

后续处理:

在 平台/调度服务/请求定义

找到接口平台健康检查,日志策略改成:仅记录异常。

但实际上这样还不够,直接禁用掉才行

这里禁用也不够,需要在调度服务/调度管理/调度任务 把接口平台的健康检查任务的自动初始化关掉:编辑,把“自动初始化”去掉,否则每次调度服务重启,会自动把这个终止的任务拉起来,而且还会把日志策略初始化成“全量记录”。

注意只有在启用状态才能编辑,非启用状态只能看详情,需要重启调度服务,才能回到启用状态,然后进行编辑。

备注(2025/12/09): 最近rebuild更新了hzero-file服务的jar包,发现清除调度日志的时候已经可以把相关联文件一起删除掉了。

问题八、文件在线编辑不能保存的问题

打开文件编辑之后,修改后点【保存并关闭】按钮后,界面没有提示信息,但后台hzero-file服务有错误日志,保存未成功。

后台日志关键错误信息是:

2025-12-08T10:31:17.514+08:00 ERROR 1 — [hzero-file] [ XNIO-1 task-2] .h.s.f.s.i.OnlyOfficeFeedBackServiceImpl : only office update text failed, callback : OnlyOfficeCallbackDTO{url=’http://onlyoffice-hzero:8800/cache/files/data/17651609109511b5aeb2_351/output.docx/output.docx?md5=1NJT1GsXAaXy9lv1ilKyVw&expires=1765161978&shardkey=17651609109511b5aeb2&filename=output.docx’, key=’17651609109511b5aeb2′, changesurl=’http://onlyoffice-hzero:8800/cache/files/data/17651609109511b5aeb2_351/changes.zip/changes.zip?md5=bK5BsAXe1FWgHbQ6muCZhw&expires=1765161978&shardkey=17651609109511b5aeb2&filename=changes.zip’, users=[2], status=2, notmodified=false} and key : 17651609109511b5aeb2

分析:该日志显示onlyoffice 通过回调API让hzero-file服务去系在onlyoffice缓存中更新后的文件时出错了。

onlyoffice容器日志也有对应的详细错误信息:

日志发给元宝分析,支持下载失败几种可能性,逐一分析:

1、网络连接问题:hzero-file的url api可以获得onlyoffice提供的编辑页面,说明网络连接没问题。

2、安全令牌(JWT)错误:我已经禁用了JWT验证,不是这个原因。

3、回调接口和逻辑是否有问题:hzero-file服务的jar包 和 onlyoffice的版本,docker-compose.yml中的配置跟非全容器环境是一样的,在非全容器环境是可以正常保存的,所以这种原因也排除掉。

4、文件路径或权限问题:OnlyOffice 服务端生成的用于更新的文件临时路径不正确,或 hzero-file 服务没有权限访问该路径,这个要仔细查一下:

我能想到的就是,挂载出来的文件目录权限是否足够,还有就是default.json中除了允许privateIP ,是否还要运行metaIP?

有个差别是我看了当初构建全容器环境的onlyoffice的挂载目录的时候是手工新建的挂载目录结构,但非全容器环境的话目录结构是容器启动时自动生成的,嗯,先尝试把原来目录结构删除掉,重启容器让目录结构也自动生成:

$ cd /d01/hzero-dockers/onlyoffice-docker

$ docker compose down

$ rm -rf /d01/hzero-dockers/volumes/onlyoffice/DocumentServer

#先注释掉docker-compose.yml中的default.json的挂载

$ docker compose up -d

#查看:相关挂载目录已经自动生成

#把default.json拷贝出来

$ docker cp onlyoffice-hzero:/etc/onlyoffice/documentserver/default.json ../volumes/onlyoffice/DocumentServer/

#更改default.json中的设置:”allowPrivateIPAddress”: false

#去掉docker-compose.yml中的default.json的挂载的注释

#重启onlyoffice容器

再次测试文件在线编辑功能,结果问题依旧,看起来不是这个原因。想到安全策略应该是优先被排查的原因,尝试把default.json中的 allowMetaIPAddress 设置为 true ,重启容器再试,结果问题依旧。看来也不是这个配置问题。

把hzero-file服务日志中的错误的文件下来连接地址,在hzero-file容器中直接访问:

# curl -v http://onlyoffice-hzero:8800/cache/files/data/176516391613405bf89d_852/output.docx/output.docx?md5=f9DLPCl-LnrOZBDQ3XcySA&expires=1765165594&shardkey=176516391613405bf89d&filename=output.docx

# *   Trying 172.18.0.9:8800…

* connect to 172.18.0.9 port 8800 failed: Connection refused

* Failed to connect to onlyoffice-hzero port 8800 after 0 ms: Connection refused

* Closing connection 0

#发现居然被拒绝了,想到之前在搜default.json中的private字符串时还有个参数:blockPrivateIP 默认是true, 尝试改成: “blockPrivateIP”: false, 重启onlyoffice容器, 再测试:问题依旧。

突然发现自己傻了,8800是onlyoffice容器外访问的端口,容器网络内应该是80端口,所以对于docker网络内的hzero-file服务也要也要跟容器外实现统一8800端口访问的话,需要更改onlyoffice的nginx端口,从80改成8800端口。

那为什么在hzero-file的application.yml中配置的是8800端口,前端可以成功打开编辑文件呢?也就是成功访问了onlyoffice-hzero:8800呢? 答:那个场景中,hzero-file的API接口 url 只是把onlyoffice-hzero:8800当做拼接字符串的一部分,拼接完成后返回给前端浏览器,真正访问这个地址的是前端浏览器,这是在容器外访问的。跟这里场景不一样,这里回调的时候是hzero-file容器真的要去访问这个地址的。

尝试像以前一样,把容器内的服务的web端口 从默认80改成跟对外映射一样的8800:

备注:这种更改对于简单的Nginx服务很容易,但对于onlyoffice这样的应用未必有用,如果官方未提供更改方法,其配置和规则设置比较多的话,就不一定能改成功了,只能试一试

=======试验开始===============

$ cd /d01/hzero-dockers/onlyoffice-docker

$ docker cp onlyoffice-hzero:/etc/onlyoffice/documentserver/nginx/ds.conf ../volumes/onlyoffice/DocumentServer/

#更改端口为8800

  listen 0.0.0.0:8800;

  listen [::]:8800 default_server;

保存,挂载

– ${DOCKER_VOLUME_DIRECTORY:-../volumes}/onlyoffice/DocumentServer/ds.conf:/etc/onlyoffice/documentserver/nginx/ds.conf

端口映射也改成:

    ports:

      – “8800:8800”

重启onlyoffice容器,再测试: 这次报了个不能下载的错误:

Hzero-file后台服务日志没有错误,onlyoffice 容器日志没有对应的错误

请求 URL 是http://onlyoffice-hzero:8800/…,而onlyoffice-hzero这个域名被解析成了172.18.14.48(这是 OnlyOffice 服务对应的容器的实际 IP),8800是该服务监听的端口。所以 “远程地址 172.18.14.48:8800” 就是你这次请求要连接的目标服务端(OnlyOffice 服务)的 IP 和端口

这没有错,对于浏览器来说,他是在容器网络外的。

对于更改onlyoffice Nginx端口这个事,豆包的分析是:

把 OnlyOffice 的 Web 端口从 80 改成 8800本身不会直接导致 403 错误,但如果端口修改时未同步更新所有相关配置,会间接引发 403(核心是「签名验证 / URL 匹配失败」),具体原因如下:

1. 最可能的原因:签名生成时的端口不匹配

OnlyOffice 缓存文件的md5签名是基于 ** 完整请求 URL(含端口)** 生成的(比如生成签名时会包含http://onlyoffice-hzero:80/…)。

若你仅修改了访问端口为 8800,但:

OnlyOffice 服务端验证签名时,会用实际请求的 URL(http://onlyoffice-hzero:8800/…)重新计算签名。

此时「生成签名的 URL(带 80)」和「实际请求的 URL(带 8800)」不一致,导致md5验证失败,直接返回 403。

这个要访问的edit.bin可以在缓存文件中看到:

那这种情况就要清缓存

# rm -rf /var/lib/onlyoffice/*

# rm -rf /var/cache/nginx/*

继续测试:

这个错误应该是onlyoffice报的错,在hzero-file服务日志和onlyoffice的容器日志中都没有错误信息。

这样,把onlyoffice容器重置一下,再试验:

先把default.json 和 ds.conf 拷贝到 d01\hzero-dockers\volumes\onlyoffice

更改docker-compose.yml的挂载位置:

    volumes:

      – ${DOCKER_VOLUME_DIRECTORY:-../volumes}/onlyoffice/default.json:/etc/onlyoffice/documentserver/default.json

      – ${DOCKER_VOLUME_DIRECTORY:-../volumes}/onlyoffice/ds.conf:/etc/onlyoffice/documentserver/nginx/ds.conf

然后删除 d01\hzero-dockers\volumes\onlyoffice\Documentserver目录

然后重启onlyoffice容器

再次测试依然是 “打开文件时发生错误”, 看起来清缓存解决不了这个问题。

那按照元宝的说法,可能是我这种更改nginx端口的方法不对。

多次实验发现,ds.conf 这个文件不能挂载,挂载会导致混乱,而且在onlyoffice容器启动的时候,提示简历这位文件的软连接失败。

去掉这个挂载以后就可以回到成功打开文件编辑,只是保存失败的问题。

===========试验结束==================

上面的试验表明想通过更改nginx配置的方式来更改onlyoffice容器的web端口从原来的80改为8800,也不可行:onlyoffice的内部各种规则配置有点复杂,不是简单改一个Nginx配置的地方就能无故障使用。

那只能用其他方法绕了,绕的前提是不用为容器环境和非容器环境分别打包jar, 那么可以通过docker-compose.yml配置环境变量的方法,在纯容器环境的docker-compose.yml中,针对回调地址通过extra host 在hzero-file服务的容器内强行把onlyoffice-hzero解析到host机,从host机的8800端口访问,测试也不行,找不到路由。

忽然灵机一动,是不是可以通过反向代理搞定?

我们来捋一捋:

目的:容器内外通过统一域名端口访问onlyoffice的80端口

此图发给豆包,豆包基本明白我的意思,描述基本正确,漏了几点:

你漏了几点:

1、部署了3个容器,除了你说的两个,还有一个nginx容器

2、在nginx容器里面做了反向代理,把onlyoffice.hzero.com.cn 反向代理到dokcer网络内的onlyoffice容器的80端口

我要实现的目的是:在容器网络外的浏览器 和通过docker 网络内的hzero-file容器内都可以通过统一的域名onlyoffice-hzero.com.cn:80来访问 docker 网络内的onlyoffice的80端口。

你觉得我能实现目的吗?

豆包说能:

访问端访问地址实际路由链路
容器内 hzero-fileonlyoffice.hzero.com.cn:80hzero-file → hzero-demo 网络 → Docker DNS 解析别名 → onlyoffice 容器 80(无 nginx 中转)
容器外浏览器onlyoffice.hzero.com.cn:80浏览器 → Linux 宿主机 80 → nginx 容器 80 → 反向代理 → onlyoffice 容器 80

修改点:

  1. hzero-file 的application.yml配置中
  2. doc-server-url 设置成onlyoffice.hzero.com.cn(80端口默认可以省略掉)
  3. onlyoffice容器增加别名:onlyoffice.hzero.com.cn

    networks:

      hzero-demo:

        aliases:

          – onlyoffice.hzero.com.cn  # 配置你要的域名别名(核心)

  • Windows Host中增加解析:172.18.14.48 onlyoffice.hzero.com.cn(如果不是本地demo环境,是企业内网,在内部DNS中添加此解析)
  • nginx容器增加反向代理配置:

server {

    listen 80;

    server_name onlyoffice.hzero.com.cn;  # 匹配统一域名

    # 反向代理到Docker网络内的onlyoffice容器80端口(直接用别名)

    location / {

        proxy_pass http://onlyoffice.hzero.com.cn:80;  # 直接指向onlyoffice容器别名

        proxy_set_header Host $host;

        proxy_set_header X-Real-IP $remote_addr;

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_connect_timeout 300s;

        proxy_send_timeout 300s;

        proxy_read_timeout 300s;

    }

}

改完后再次运行测试:

查看nginx容器日志:

2025/12/09 05:10:26 [error] 37#37: *15 connect() failed (113: No route to host) while connecting to upstream, client: 172.18.0.1, server: onlyoffice.hzero.com.cn, request: “GET /web-apps/apps/api/documents/api.js HTTP/1.1”, upstream: “http://172.18.14.48:80/web-apps/apps/api/documents/api.js”, host: “onlyoffice.hzero.com.cn”, referrer: “http://dev.hzero.com.cn/”

看起来容器内的nginx把onlyoffice.hzero.com.cn的IP地址解析错误了,应该解析到docker网络内的IP地址而不是host主机地址。为避免混淆,直接更改nginx的方向代理配置:直接用onlyoffice-hzero的容器服务名,不用别名

server {

    listen 80;

    server_name onlyoffice.hzero.com.cn;  # 匹配统一域名

    # 反向代理到Docker网络内的onlyoffice容器80端口(直接用别名)

    location / {

        proxy_pass http://onlyoffice-hzero:80;  # 直接指向onlyoffice容器服务名

        proxy_set_header Host $host;

        proxy_set_header X-Real-IP $remote_addr;

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_connect_timeout 300s;

        proxy_send_timeout 300s;

        proxy_read_timeout 300s;

    }

}

这次可以正常打开了:

修改后保存,看hzero-file的后台服务日志,已经成功,在更新表了:

下载打开该文件可以看到,更新已经生效:

问题九、如何让配置管理更清晰?

关于文件服务,我决定做些优化,让配置管理更清晰:

一、Minio文件服务:

  1. 在平台/文件管理/文件存储配置/MINIO 处,EndPoint还是改成:oss.hzero.com.cn:9000
  2. 容器服务minio-hzero添加别名:oss.hzero.com.cn
  3. Windows hosts 文件添域名解析:172.18.14.48  oss.hzero.com.cn              #minio 文件服务域名(客户端直接预览PDF需要),去掉对minio-hzero名称的解析。
  4. 修数据:

文档地址

UPDATE hzero_aip.hdoc_document_version SET document_url = REPLACE(document_url, ‘minio-hzero:9000′,’oss.hzero.com.cn:9000’ );

UPDATE hzero_aip.hdoc_document_version SET source_key = REPLACE(source_key, ‘minio-hzero:9000′,’oss.hzero.com.cn:9000’ )

文件地址:

update hzero_file.hfle_file set file_url=REPLACE(file_url, ‘minio-hzero:9000′,’oss.hzero.com.cn:9000’ )

  • kkfielview文件预览服务:
  • 容器服务kkfileview-hzero添加别名:kkv.hzero.com.cn

   之前添加的extra_hosts可以去掉了。

  • Windows hosts 文件添域名解析:172.18.14.48  kkv.hzero.com.cn              # 文件预览服务域名。
  • 更改hzero-file文件服务的application.yml :    

kk-file-view-url: http://kkv.hzero.com.cn:8012/onlinePreview   # kkFileView的文件预览地址

重新构建hzero-file jar包和docker镜像
重启hzero-file服务。

这修改之后,客户端window hosts文件就保留6条解析,别的不用了:
172.18.14.48  dev.hzero.com.cn         #hzero-demo环境 Nginx服务器地址

172.18.14.48  gateway.hzero.com.cn     #网关的地址

172.18.14.48  aigc.hzero.com.cn        # ai-app服务的反向代理

172.18.14.48  kkv.hzero.com.cn        # kkfileview文件预览服务域名

172.18.14.48  oss.hzero.com.cn        # minio文件服务域名(客户端直接预览PDF需要)

172.18.14.48  onlyoffice.hzero.com.cn   # minio 文档在线编辑服务

 

 

关于作者:

昵称:Jack.shang
档案信息:jack.shang 程序员->项目经理->技术总监->项目总监->部门总监->事业部总经理->子公司总经理->集团产品运营支持
联系方式:你可以通过syfvb@hotmail.com联系作者
点击查看发表过的所有文章...
本文永久链接: http://blog.retailsolution.cn/archives/4858

 

 

对本文的评价:

 

 

分类: 默认 标签:
本文的评论功能被关闭了.