msgbyte / tailchat

Next generation noIM application in your own workspace, not only another Slack/Discord/Rocket.chat
https://tailchat.msgbyte.com/
Apache License 2.0
2.84k stars 307 forks source link

是否有替换 MinIO 为 阿里云OSS 的方法? || Is there a way to replace MinIO with Alibaba Cloud OSS? #104

Closed antscript closed 1 year ago

antscript commented 1 year ago

环境变量里没看到相关可以配置的,是否已经有替换的功能?还是需要单独开发?感谢🙏


I don’t see anything that can be configured in the environment variables. Is there a replacement function? Or does it need to be developed separately? Thanks 🙏

moonrailgun commented 1 year ago

阿里云oss协议不兼容minio解决方案,你可以考虑替换为aws s3.

如果一定要支持各种国内oss的话每家都需要单独开发一套。欢迎pr


The Alibaba Cloud oss ​​protocol is not compatible with the minio solution, you may consider replacing it with aws s3.

If it is necessary to support various domestic oss, each company needs to develop a separate set. Welcome pr

moonrailgun commented 1 year ago

我发现阿里云oss支持s3兼容协议。你可以尝试把MINIO_URL, MINIO_USER, MINIO_PASS 换成阿里云s3兼容的对应信息,然后配置STATIC_HOST为阿里云的对外cdn地址即可


I found that Alibaba Cloud oss ​​supports the S3 compatible protocol. You can try to replace MINIO_URL, MINIO_USER, MINIO_PASS with the corresponding information compatible with Alibaba Cloud s3, and then configure STATIC_HOST as Alibaba Cloud’s external cdn address

antscript commented 1 year ago

配置完后上传图片报错: { "name": "S3Error", "message": "Error status : 502 from mirror host, should return 200 OK.", "code": "MirrorFailed" } 能排查的都排查了,没找到问题,有人成功的吗?

moonrailgun commented 1 year ago

配置完后上传图片报错: { "name": "S3Error", "message": "Error status : 502 from mirror host, should return 200 OK.", "code": "MirrorFailed" } 能排查的都排查了,没找到问题,有人成功的吗?

https://blog.xgblack.cn/alioss-image-back-to-the-source-failure-solution/

看看这个呢?

antscript commented 1 year ago

配置完后上传图片报错: { "name": "S3Error", "message": "Error status : 502 from mirror host, should return 200 OK.", "code": "MirrorFailed" } 能排查的都排查了,没找到问题,有人成功的吗?

https://blog.xgblack.cn/alioss-image-back-to-the-source-failure-solution/

看看这个呢?

之前看过,但这个是 CDN 回源的问题,我目前是不能上传成功。

antscript commented 1 year ago

另外,目前的实现是先把图片上传到服务器,服务器再上传到 oss 吗?如果是这样的话也有问题,需要重新实现一下客户端直传。


In addition, the current implementation is to upload the picture to the server first, and then the server uploads it to oss? If this is the case, there is also a problem, and it is necessary to re-implement the direct transmission of the client.

moonrailgun commented 1 year ago

另外,目前的实现是先把图片上传到服务器,服务器再上传到 oss 吗?如果是这样的话也有问题,需要重新实现一下客户端直传。

In addition, the current implementation is to upload the picture to the server first, and then the server uploads it to oss? If this is the case, there is also a problem, and it is necessary to re-implement the direct transmission of the client.

问题是什么?

服务器做中转的目的是隐藏对象存储的端口与连接细节。传输是通过流式传输

antscript commented 1 year ago

另外,目前的实现是先把图片上传到服务器,服务器再上传到 oss 吗?如果是这样的话也有问题,需要重新实现一下客户端直传。 In addition, the current implementation is to upload the picture to the server first, and then the server uploads it to oss? If this is the case, there is also a problem, and it is necessary to re-implement the direct transmission of the client.

问题是什么?

服务器做中转的目的是隐藏对象存储的端口与连接细节。传输是通过流式传输

image https://help.aliyun.com/document_detail/112718.html?spm=a2c4g.267439.0.0.57cc2286F98XgD

moonrailgun commented 1 year ago

说白了就是除了网络没有缺点。

等到网络是缺点的时候,你的用户已经达到一个非常夸张的数量级了,短期内应该不会遇到这个瓶颈

另外就是通过应用服务器时应用服务器会记录一些文件信息用于后续维护,直传的话会数据存在不可信的问题。


To put it bluntly, there is no disadvantage except the network.

When the network is a shortcoming, your users have reached a very exaggerated order of magnitude, and you should not encounter this bottleneck in the short term

In addition, when passing through the application server, the application server will record some file information for subsequent maintenance. If the data is transmitted directly, the data will be untrustworthy.

moonrailgun commented 1 year ago

我比较关心是否跑通了oss存储,因为我没有使用阿里云没法测试。


I am more concerned about whether the oss storage is running through, because I do not use Alibaba Cloud and cannot test it.

antscript commented 1 year ago
  1. 没跑通
  2. 直传也有阿里云触发的回调可以解决信任问题
  3. Didn't work
  4. The direct transmission also has a callback triggered by Alibaba Cloud, which can solve the trust problem
moonrailgun commented 1 year ago
  1. 没跑通

  2. 直传也有阿里云触发的回调可以解决信任问题

  3. Didn't work

  4. The direct transmission also has a callback triggered by Alibaba Cloud, which can solve the trust problem

  1. 我有机会研究一下。
  2. 阿里云有回调不代表其他的服务也有回调。。因为tailchat的文件存储是s3协议。回调不是s3协议的一部分
antscript commented 1 year ago
  1. 没跑通
  2. 直传也有阿里云触发的回调可以解决信任问题
  3. Didn't work
  4. The direct transmission also has a callback triggered by Alibaba Cloud, which can solve the trust problem
  1. 我有机会研究一下。
  2. 阿里云有回调不代表其他的服务也有回调。。因为tailchat的文件存储是s3协议。回调不是s3协议的一部分

理解,只是在我们的常规架构里没使用过服务端代传的模式(不值得在服务器端花费额外的性能和带宽),客户端直传是已经比较成熟的解决方案,后续如果实现了会提PR。


  1. Didn't work
  2. The direct transmission also has a callback triggered by Alibaba Cloud, which can solve the trust problem
  3. Didn't work
  4. The direct transmission also has a callback triggered by Alibaba Cloud, which can solve the trust problem
  1. I have a chance to research it.
  2. Just because Alibaba Cloud has callbacks does not mean that other services also have callbacks. . Because the file storage of tailchat is the s3 protocol. Callbacks are not part of the s3 protocol

I understand, it’s just that we haven’t used the server-side transfer mode in our regular architecture (it’s not worth spending extra performance and bandwidth on the server side), client-side direct transfer is a relatively mature solution, and if it is implemented in the future, it will improve PR.

moonrailgun commented 1 year ago

Document: https://tailchat.msgbyte.com/docs/advanced-usage/external-storage

SanQianQVQ commented 10 months ago

有任何人跟进此线程吗?我对 nodejs 和 minio 不是很熟悉。 我尝试使用 Cloudflare S3 兼容 Api,在填写 Endpoint 的时候发现问题

如果不带协议头 https:// 那么会被 301 Move 从而导致程序终止(看起来似乎是没有 region 导致的?或者客户端使用了http而不是https?)

unhandledRejection S3Error: Moved Permanently
    at getError (/app/tailchat/node_modules/.pnpm/minio@7.1.1/node_modules/minio/dist/main/transformers.js:131:15)
    at /app/tailchat/node_modules/.pnpm/minio@7.1.1/node_modules/minio/dist/main/transformers.js:140:14
    at Transform._flush (/app/tailchat/node_modules/.pnpm/minio@7.1.1/node_modules/minio/dist/main/transformers.js:77:10)
    at Transform.prefinish (/app/tailchat/node_modules/.pnpm/readable-stream@3.6.1/node_modules/readable-stream/lib/_stream_transform.js:122:10)
    at Transform.emit (node:events:517:28)
    at Transform.emit (node:domain:489:12)
    at prefinish (/app/tailchat/node_modules/.pnpm/readable-stream@3.6.1/node_modules/readable-stream/lib/_stream_writable.js:568:14)
    at finishMaybe (/app/tailchat/node_modules/.pnpm/readable-stream@3.6.1/node_modules/readable-stream/lib/_stream_writable.js:575:5)
    at endWritable (/app/tailchat/node_modules/.pnpm/readable-stream@3.6.1/node_modules/readable-stream/lib/_stream_writable.js:593:3)
    at Writable.end (/app/tailchat/node_modules/.pnpm/readable-stream@3.6.1/node_modules/readable-stream/lib/_stream_writable.js:534:22)
    at IncomingMessage.onend (node:internal/streams/readable:716:10)
    at Object.onceWrapper (node:events:631:28)
    at IncomingMessage.emit (node:events:529:35)
    at IncomingMessage.emit (node:domain:489:12)
    at endReadableNT (node:internal/streams/readable:1368:12)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
  code: 'MovedPermanently',
  amzRequestid: null,
  amzId2: null,
  amzBucketRegion: null
}

如果带协议头,那么就会抛出

 Unable to start all services. MinioInitializationError: getaddrinfo ENOTFOUND https
    at /app/tailchat/server/packages/sdk/dist/services/mixins/minio.mixin.js:693:19
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Promise.all (index 14) {
  code: 500,
  type: 'MINIO_INITIALIZATION_ERROR',
  data: {},
  retryable: false
}
[Runner] getaddrinfo ENOTFOUND https MinioInitializationError: getaddrinfo ENOTFOUND https
    at /app/tailchat/server/packages/sdk/dist/services/mixins/minio.mixin.js:693:19
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Promise.all (index 14) {
  code: 500,
  type: 'MINIO_INITIALIZATION_ERROR',
  data: {},
  retryable: false
}
 ELIFECYCLE  Command failed with exit code 1.
 ELIFECYCLE  Command failed with exit code 1.
moonrailgun commented 10 months ago

@SanQianQVQ 请检查文档,确保每个环境变量都是正确的。特别是 MINIO_PATH_STYLE 你需要人工判断是哪一类地址格式


@SanQianQVQ Please check the documentation to make sure every environment variable is correct. Especially for MINIO_PATH_STYLE, you need to manually determine what type of address format it is

SanQianQVQ commented 10 months ago

@moonrailgun 感谢您的回复,我之前在尝试使用其他项目时,Cloudflare 的 S3 兼容Api 是支持 VirtualHosted 和 Path 的,并且我两个都尝试了一下,对错误的抛出没有影响。

根据 Cloudflare 的文档Tailchat 的文档

我在 docker-compose.env 是这样写的:

MINIO_URL=<ACCOUNT_ID>.r2.cloudflarestorage.com 
MINIO_USER=Access Key ID 
MINIO_PASS=Secret Access Key 
MINIO_BUCKET_NAME=tailchat  
MINIO_PATH_STYLE=Path

然后抛出的错误为

unhandledRejection S3Error: Moved Permanently
    at getError (/app/tailchat/node_modules/.pnpm/minio@7.1.1/node_modules/minio/dist/main/transformers.js:131:15)
    at /app/tailchat/node_modules/.pnpm/minio@7.1.1/node_modules/minio/dist/main/transformers.js:140:14
    at Transform._flush (/app/tailchat/node_modules/.pnpm/minio@7.1.1/node_modules/minio/dist/main/transformers.js:77:10)
    at Transform.prefinish (/app/tailchat/node_modules/.pnpm/readable-stream@3.6.1/node_modules/readable-stream/lib/_stream_transform.js:122:10)
    at Transform.emit (node:events:517:28)
    at Transform.emit (node:domain:489:12)
    at prefinish (/app/tailchat/node_modules/.pnpm/readable-stream@3.6.1/node_modules/readable-stream/lib/_stream_writable.js:568:14)
    at finishMaybe (/app/tailchat/node_modules/.pnpm/readable-stream@3.6.1/node_modules/readable-stream/lib/_stream_writable.js:575:5)
    at endWritable (/app/tailchat/node_modules/.pnpm/readable-stream@3.6.1/node_modules/readable-stream/lib/_stream_writable.js:593:3)
    at Writable.end (/app/tailchat/node_modules/.pnpm/readable-stream@3.6.1/node_modules/readable-stream/lib/_stream_writable.js:534:22)
    at IncomingMessage.onend (node:internal/streams/readable:716:10)
    at Object.onceWrapper (node:events:631:28)
    at IncomingMessage.emit (node:events:529:35)
    at IncomingMessage.emit (node:domain:489:12)
    at endReadableNT (node:internal/streams/readable:1368:12)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
  code: 'MovedPermanently',
  amzRequestid: null,
  amzId2: null,
  amzBucketRegion: null
}

在 Cloudflare 文档的描述中,region 可以传递空值,所以我想应该不是region的问题?

moonrailgun commented 10 months ago

这个就不清楚了,看上去是r2返回了301 也许需要尝试一下 https://<ACCOUNT_ID>.r2.cloudflarestorage.com?

moonrailgun commented 10 months ago

因为我看示例是带https的


Because I see that the example is with https

ACnoway commented 10 months ago

因为我看示例是带https的

Because I see that the example is with https

带上https会返回 getaddrinfo ENOTFOUND https

SanQianQVQ commented 10 months ago

这个就不清楚了,看上去是r2返回了301 也许需要尝试一下 https://<ACCOUNT_ID>.r2.cloudflarestorage.com?

@moonrailgun 不行的,我在前面的回复中贴了报告,url填写协议头的话会报错。

 Unable to start all services. MinioInitializationError: getaddrinfo ENOTFOUND https
    at /app/tailchat/server/packages/sdk/dist/services/mixins/minio.mixin.js:693:19
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Promise.all (index 14) {
  code: 500,
  type: 'MINIO_INITIALIZATION_ERROR',
  data: {},
  retryable: false
}
[Runner] getaddrinfo ENOTFOUND https MinioInitializationError: getaddrinfo ENOTFOUND https
    at /app/tailchat/server/packages/sdk/dist/services/mixins/minio.mixin.js:693:19
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Promise.all (index 14) {
  code: 500,
  type: 'MINIO_INITIALIZATION_ERROR',
  data: {},
  retryable: false
}
 ELIFECYCLE  Command failed with exit code 1.
 ELIFECYCLE  Command failed with exit code 1.
SanQianQVQ commented 10 months ago

@moonrailgun

尝试检索了一下报错给出的文件路径和行数,会不会是因为构造的请求是 HTTP:// , 但 R2 是必须 HTTPS:// ,所以产生了301跳转 https://github.com/msgbyte/tailchat/blob/84db4a27c19fe701721dced7baeac03e2b3fa5d3/server/packages/sdk/src/services/mixins/minio.mixin.ts#L581-L722


@moonrailgun

I tried to retrieve the file path and line number given in the error report. Could it be because the constructed request is HTTP://, but R2 requires HTTPS://, so a 301 jump was generated? https://github.com/msgbyte/tailchat/blob/84db4a27c19fe701721dced7baeac03e2b3fa5d3/server/packages/sdk/src/services/mixins/minio.mixin.ts#L581-L722

SanQianQVQ commented 10 months ago

这一串代码关闭了useSSL

https://github.com/msgbyte/tailchat/blob/84db4a27c19fe701721dced7baeac03e2b3fa5d3/server/services/core/file.service.ts#L41-L50


This string of code turns off useSSL

https://github.com/msgbyte/tailchat/blob/84db4a27c19fe701721dced7baeac03e2b3fa5d3/server/services/core/file.service.ts#L41-L50

moonrailgun commented 10 months ago

@SanQianQVQ 感谢你的review 也许你是对的,介意帮忙测试一下如果把这个打开以后可以正常运行的么?欢迎提pr


@SanQianQVQ thank you for your review Maybe you are right, would you mind helping me test if it can run normally after opening this? Welcome to submit pr

SanQianQVQ commented 10 months ago

@moonrailgun

我不是编译运行的,而是通过 docker-compose,然后就会出现非常尴尬的局面——没法修改docker容器内的文件,因为就算docker exec进去修改参数,但只要重新启动docker,修改就会被覆盖


@moonrailgun

I did not compile and run it, but through docker-compose, and then a very embarrassing situation would arise - the files in the docker container could not be modified, because even if docker exec went in to modify the parameters, as long as docker was restarted, the modifications would be Override

moonrailgun commented 10 months ago

你可以通过docker restart 重启而不是docker compose up -d 重启 注意需要修改编译后的代码


You can restart via docker restart instead of docker compose up -d Note that the compiled code needs to be modified

SanQianQVQ commented 10 months ago

你可以通过docker restart 重启而不是docker compose up -d 重启 注意需要修改编译后的代码

You can restart via docker restart instead of docker compose up -d Note that the compiled code needs to be modified

好,看起来编译后的应该是在 tailchat-service-core-1 这里?

moonrailgun commented 10 months ago

yes

SanQianQVQ commented 10 months ago

@moonrailgun 好消息,看起来确实是受到 useSSL 的影响。坏消息,仍然抛出错误,但是至少指明了方向。 在修改了文件(dist/server/services/core/file.service.js)中的 useSSL 为 true 后,错误抛出变成了

Unable to start all services. MinioInitializationError: write EPROTO 582BBFC3C57F0000:error:0A00010B:SSL routines:ssl3_get_record:wrong version number:../deps/openssl/openssl/ssl/record/ssl3_record.c:354:

    at /app/tailchat/server/packages/sdk/dist/services/mixins/minio.mixin.js:693:19
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Promise.all (index 14) {
  code: 500,
  type: 'MINIO_INITIALIZATION_ERROR',
  data: {},
  retryable: false
}
[Runner] write EPROTO 582BBFC3C57F0000:error:0A00010B:SSL routines:ssl3_get_record:wrong version number:../deps/openssl/openssl/ssl/record/ssl3_record.c:354:
 MinioInitializationError: write EPROTO 582BBFC3C57F0000:error:0A00010B:SSL routines:ssl3_get_record:wrong version number:../deps/openssl/openssl/ssl/record/ssl3_record.c:354:

    at /app/tailchat/server/packages/sdk/dist/services/mixins/minio.mixin.js:693:19
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Promise.all (index 14) {
  code: 500,
  type: 'MINIO_INITIALIZATION_ERROR',
  data: {},
  retryable: false
}
 ELIFECYCLE  Command failed with exit code 1.
 ELIFECYCLE  Command failed with exit code 1.
unhandledRejection Error: write EPROTO 58FB54AFCC7F0000:error:0A00010B:SSL routines:ssl3_get_record:wrong version number:../deps/openssl/openssl/ssl/record/ssl3_record.c:354:

    at WriteWrap.onWriteComplete [as oncomplete] (node:internal/stream_base_commons:94:16) {
  errno: -71,
  code: 'EPROTO',
  syscall: 'write'
}

也就是,之前的301确实是因为协议不正确,应该使用 https,但是minio使用了http导致的,但是新的问题是看起来 minio 使用的 SSL/TLS 协议不被 R2 认可,猜测可能使用了不安全的 TLS1.0?

moonrailgun commented 10 months ago

想确认一下是否在服务器上启用了代理之类的中转服务?


Want to confirm whether a relay service such as a proxy is enabled on the server?

SanQianQVQ commented 10 months ago

想确认一下是否在服务器上启用了代理之类的中转服务?

Want to confirm whether a relay service such as a proxy is enabled on the server?

没有,服务器位于芬兰,因此与 Cloudflare 连接不需要通过 Proxy, 只有 docker 网桥和宿主机的交换

moonrailgun commented 10 months ago

确实很奇怪。我没有r2账号也没办法复现。 不过应该不是协议的问题,因为在堆栈报错中显示了使用的是ssl3_record.c.

你可以尝试在使用useSSL: true的情况下分别加上https:// 和 http:// 和 不加任何协议头 来尝试


Strange indeed. I don’t have an r2 account and I can’t reproduce it. But it shouldn’t be a protocol problem, because the stack error shows that ssl3_record.c is used.

You can try using useSSL: true and adding https:// and http:// respectively without adding any protocol headers to try

SanQianQVQ commented 10 months ago

确实很奇怪。我没有r2账号也没办法复现。 不过应该不是协议的问题,因为在堆栈报错中显示了使用的是ssl3_record.c.

你可以尝试在使用useSSL: true的情况下分别加上https:// 和 http:// 和 不加任何协议头 来尝试

Strange indeed. I don’t have an r2 account and I can’t reproduce it. But it shouldn’t be a protocol problem, because the stack error shows that ssl3_record.c is used.

You can try using useSSL: true and adding https:// and http:// respectively without adding any protocol headers to try

我明白了,查阅了 minio 的文档和 Stackoverflow 后,这一部分控制的实质上是 minio 本身。由于 docker-compose.yml 里是非标端口+无cert配置,所以才在初始化阶段就抛出了 SSL 错误。而修改之前是可以正常初始化客户端的,只是在 handle 过程中出现了301导致退出... 也就是这一部分控制的应该是 minio 的客户端初始化,而不是初始化之后与 S3 类服务的连接... 问题又回到了原点 (SAD)

https://github.com/msgbyte/tailchat/blob/84db4a27c19fe701721dced7baeac03e2b3fa5d3/server/services/core/file.service.ts#L41-L50

SanQianQVQ commented 10 months ago

确实很奇怪。我没有r2账号也没办法复现。 不过应该不是协议的问题,因为在堆栈报错中显示了使用的是ssl3_record.c.

你可以尝试在使用useSSL: true的情况下分别加上https:// 和 http:// 和 不加任何协议头 来尝试

Strange indeed. I don’t have an r2 account and I can’t reproduce it. But it shouldn’t be a protocol problem, because the stack error shows that ssl3_record.c is used.

You can try using useSSL: true and adding https:// and http:// respectively without adding any protocol headers to try

协议头无法添加,只要在env中添加就会抛出

 Unable to start all services. MinioInitializationError: getaddrinfo ENOTFOUND https
    at /app/tailchat/server/packages/sdk/dist/services/mixins/minio.mixin.js:693:19
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Promise.all (index 14) {
  code: 500,
  type: 'MINIO_INITIALIZATION_ERROR',
  data: {},
  retryable: false
}
[Runner] getaddrinfo ENOTFOUND https MinioInitializationError: getaddrinfo ENOTFOUND https
    at /app/tailchat/server/packages/sdk/dist/services/mixins/minio.mixin.js:693:19
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Promise.all (index 14) {
  code: 500,
  type: 'MINIO_INITIALIZATION_ERROR',
  data: {},
  retryable: false
}
 ELIFECYCLE  Command failed with exit code 1.
 ELIFECYCLE  Command failed with exit code 1.
moonrailgun commented 10 months ago

我明白了,查阅了 minio 的文档和 Stackoverflow 后,这一部分控制的实质上是 minio 本身。由于 docker-compose.yml 里是非标端口+无cert配置,所以才在初始化阶段就抛出了 SSL 错误。而修改之前是可以正常初始化客户端的,只是在 handle 过程中出现了301导致退出... 也就是这一部分控制的应该是 minio 的客户端初始化,而不是初始化之后与 S3 类服务的连接... 问题又回到了原点 (SAD)

这很奇怪,如果你不介意的话能否开一个测试桶然后在tailchat nightly 私信给我呢?我来看下


I understand, after consulting minio's documentation and Stackoverflow, this part actually controls minio itself. Since docker-compose.yml contains non-standard ports + no cert configuration, an SSL error was thrown during the initialization phase. Before the modification, the client could be initialized normally, but a 301 occurred during the handle process, causing the exit... That is, this part should control the initialization of the minio client, not the connection with the S3 service after initialization... The problem is back to square one (SAD)

This is weird. If you don't mind, could you open a test bucket and send me a private message on tailchat nightly? Let me take a look

ACnoway commented 10 months ago

@SanQianQVQ 佬,请问您配置好r2了吗,我迁移之后一直出问题,发现文件结构不一样,不知道您怎么解决的


@SanQianQVQ Guys, have you configured r2? I kept having problems after the migration and found that the file structure was different. I don’t know how you solved it