这周有用户将数据从某个 S3 兼容的平台迁移到 QingStor 对象存储,但是在使用 qscamel 的时候遇到了一些问题,所以我去做了一些技术支持,原因果然出在这 S3 兼容上。

每次遇到 S3 兼容的服务的报签名错误,我们首先需要猜测它是不是不支持 AWS Signature Version 4,改成了 v2 之后返回的报错变成了 TimeTooSkewed。我让远程的同事检查一下 client & server 的时间,相差 1 分钟不到,应该在容忍的范围内(一般会允许 15 分钟的偏差)。跟用户解释了很久这是服务器的报错,并不是迁移客户端的问题之后,终于说动了他去查服务器的日志,最后日志大意是这样的:“请求使用的时区是 UTC,跟服务器使用的 GMT 时区差异过大”。我缓缓地在用户群里发出了疑问:“UTC 和 GMT 不是同一个时区吗?时间应该应该相同吧。。”

无论如何,用户是大爷。我按照他们服务的要求修改了 Date Header 使用的时区:

-       v2.Request.Header["date"] = []string{v2.Time.In(time.UTC).Format(time.RFC1123)}
+       v2.Request.Header["date"] = []string{v2.Time.In(time.FixedZone("GMT", 0)).Format(time.RFC1123)}

在改好时区之后,qscamel 终于能用起来了,但是用户反馈在源端没有 List 出数据。在尝试了很多选项的组合之后,我发现只有使用 Path Style 才能 List 出数据。

彳亍口巴,S3 兼容真的是太棒啦。


这周我们合并了前端同学 Flutter PR,整个项目总算是有了个雏形。我感受了一下 Dart,看起来好像比 JavaScript 更好懂一些。

import 'package:flutter/material.dart';

class PageToolbar extends StatelessWidget {
  final String title;
  final List<Widget> children;

  PageToolbar({ this.title, this.children });

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 56.0,
      alignment: Alignment.center,
      margin: EdgeInsets.only(bottom: 16.0),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Expanded(
            child: SelectableText(
              title, style: Theme.of(context).textTheme.headline6),
          ),
          ...children,
        ]
      ),
      decoration: new BoxDecoration(
        border: Border(
          bottom: BorderSide(
            style: BorderStyle.solid,
            color: Color.fromRGBO(228, 235, 241, 1),
          )
        ),
      ),
    );
  }
}

后端这边重写了任务的调度,解决了丢任务 & 死锁的问题,踩了不少 NATS 使用中的坑:比如没有 Subscriber 的时候,发给 NATS 的消息会被直接丢掉,还没有任何报错。后来我们的解决方案是引入了打卡机制。

  • Leader 启动时 subscribe 特定的 subject
  • Worker 启动后向这个 subject 发消息来打开上班
  • Leader 在确认 Worker 都已经上班之后再分发任务
  • Worker 在打开上班的同时还会 subscribe 打卡下班的通知
  • Leader 在确认任务完成后会给大家发通知
  • Worker 收到之后就会自行下班

这个机制目前还比较简陋,等到后续实现分布式迁移的时候,我们会重新审视一下。

这周已经开始准备做 release 了,但是发现 go:embed 并不是很好用:

  • 不支持软链接
  • 不支持引用父级目录
  • http.FileServer & gin.StaticFS 一起用的时候还有点 buggy,没法访问 index.html

要是这周解决不了的话,下周可能就放弃 go:embed 这个方案了。


下周再见!