1

Pensieve: 2009

 2 years ago
source link: https://blog.xiaket.org/2020/pensieve-2009.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Pensieve: 2009

2020-09-25 08:49

所观所读所听

Ars Technica几个游戏主题的视频值得一看: 这儿有一个是关于Diablo的一个关于Civilization的. 实话实话, 看完后对这两位的敬意少了一点儿. Diablo本来是个回合制的游戏, 被总部建议改成即时制. David Brevik当时强烈反对这个改动, 组内投票才硬着头皮同意, 跟暴雪总部再多要一点开发资源, 结果一个晚上的时间就把这个本以为要数周的改动给完成了, 后面就转变观念觉得这是一个好主意了. 类似的, Civilization的One more turn也不是Sid一开头的主意, 这个上口的梗更多来自于玩家社区.

雪中悍刀行重读完了这是第三还是第四遍. 主要缺点是故事拖得太长主次不分, 导致最后给人戛然而止的感觉, 而且为了追求爽感, 很多时候给了一个类似漫画的画面感, 结果是本可以刻画得更细致的场景就粗粗带过了. 但是人物塑造称得上有血有肉.

Kittens Game花了我大量时间, 刷到了时间科技后觉得后面的升级还茫茫然无止境, 就放下了. 不过这个游戏的整体设计还是挺不错的, 就是坑深了点儿. 为什么大家都不愿意做那种一开始就知道几个小时可以玩穿放下, 后面会不由自主地回来玩的游戏呢?

go-git

之前说过, 我用go写了一个命令行程序来自定义命令提示符. 这个月发现它有点卡顿了, 就想办法优化了下, 对应的修改可以参考这两个commit: 240c54b548e0. 下面简要讲一下这个过程中做的尝试.

先介绍一下背景, 我之前的那个版本慢主要是卡在调用系统git命令上. 我怀疑是由于我最近升级了git客户端, 所以导致一些之前执行速度过得去的命令变慢了, 所以总体上让我感觉到了卡顿. 于是, 我们要做的最重要的事情是将这些系统命令调用改成go语言实现. 于是自然是找一个go语言原生的git库来. 我调研后看到两个伯仲之间的选项, 一个是go-git, 另一个是git2go. 前者是用go从头写的, 后者是libgit2这个C库的兼容层. 我用go-git写了一个版本出来, 前面几个命令都还好, 到最后列git status的时候, 这个库无比卡. 一个git status需要150毫秒的目录里跑这段代码需要2.5秒左右. 尝试看了下源码, 发现这个库不算太靠谱, 志愿者贡献的代码质量参差不齐, 而且git本身又是一个很考验优化能力的技术, 所以回头进了git2go的门. 优化完以后速度提示很明显: 比如, 我在我的etc目录里面跑git status, 耗时大概是40毫秒, 而我运行编译好的ps1命令的时候, 耗时大概是50毫秒, 这基本属于人感知不到的范围了.

结论: go-git坑多, 不要踩, 绕路去git2go也许是更好的选择.

StackSet

StackSet是一个大坑, 这是我深入使用这个产品两个月后的感受.

这个产品的出发点是一次部署多个Stack. 但是一般正常应用级的内容不会要求同时部署到多账户多区域: 应用一般需要部署到一个或少数几个不同环境的账号, 而且还存在发布控制的需求, 不太可能也不太适合用StackSet来部署. 因此, 这个产品实际上大部分使用场景是云账号的管理员将一些全局性, 策略性的Stack部署到部分或所有账户中的一个或多个区域里. 讲到这儿, 我们必须提一下AWS Organizations里面的另一个特性, 叫Organization Unit. 例如一个公司有若干个部门, 每个部门对于AWS的使用有不同的要求, 所以一个部门映射一个OU, 这样可以实现不同部门的账户采用不同的管理方式/策略. StackSet支持部署到一个或多个账号, 也支持部署到一个或多个OU. 好吧, 目前为止, 这一切看起来还不错.

那么现在, 除了账号和OU这两种部署方式外, 再给你加上一个自由度: StackSet的管理维护和Stack Instance的管理维护是两码事. 比如, 你可以部署完Stack Instances之后对于某一个OU或者某一些账号(取决于你的部署方式)针对某个区域删除这些Stack Instances. 这个操作会成功, 但是对维护者来说, 这个操作很难被察觉到, 因为Stack Instance没有一个一致可靠的描述字段. 又比如, 你想要把Stack A部署到OU1的悉尼区, 再部署到OU2的美国东1区, 经过这样的混合部署后, 除了一个个分析每个Stack Instance是在哪个OU哪个区域外, 你没有办法从单个API的单个字段拿到这些信息. 这样的行为对IaC很不友好, 我们期望的是能够定义一些部署目标, StackSet能够自动分析这些部署目标, 并将定义好的Stack部署到这些目标中去. 回头我们使用API查询一个StackSet状态的时候, 也能一目了然地看到这些部署目标, 心里有底.

再加上一些小坑:

  • 删账号一时爽, 不过这些已经停用账号里的Stack Instances删不掉怎么办? 我们摸索出来的办法是把被停用的账号放到一个特定的OU, 然后如果那个StackSet里面不包含这个OU, 强行部署一遍(这样肯定会失败, 不过没关系), 然后再强行删除一遍, 这样繁琐的操作只是为了除掉那些记录, 方便StackSet的后续维护操作. 当然, 最正确的办法是删账号时不要急, 先把这些账号放到一个特定的不部署任何StackSet的OU里一段时间, 等StackSet/Stack Instance的删除操作都完成后再去删账号.
  • StackInstance的状态也有些莫名的小瑕疵. 比如, 你决定删掉一个OU里部署的Stack Instances, 没问题, 界面上还是调API都可以做到. 接下来, 如果你在中途改了主意, 停掉了这个操作, 部分Stack Instances被删除, 其余的Stack Instances显示OUTDATED, 这也可以理解. 那么接下来, 我对这个OU重新部署一遍, 我期望的结果是所有这些Stack Instances都变成CURRENT. 但实际上StackSet的行为是那些OUTDATED的instances的状态不变, 而后面补回的那些Instances的状态是CURRENT. 要修正, 只能再去调API.

所以, 我自己写代码在StackSet上面再包装了一层, 实现类似这样的API:

stack_set = StackSet(
    name="some-stack-name",
    template=template_url,
    params=params,
    tags=TAGS,
    iam=True,
)

stack_set.deploy(
    targets=[
        {"regions": [some_regions], "ouids": some_ou_ids},
        {"regions": [other_regions], "ouids": other_ou_ids},
    ],
)

这样, 我们需要在代码里面维护StackSet的部署目标, 上面的代码示例中, 我们把这个StackSet部署到some_ou_idssome_regions中去, 也要将其部署到other_ou_idsother_regions中去. 如果需要增减部署目标, 直接用这儿提供的API来完成.

simplicity is the ultimate sophistication. 为了实现这样简单的API, 我写了大概类似这样的代码:

  if not stackset.exists:
    create-stackset
  else:
    wait-for-existing-operations
    describe-stackset
    if template/parameter/tag/capabilities changes:
      update-stackset
  deploy-stack-instances

其中, deploy-stack-instances的逻辑如下:

list-stack-instances | sort by ou/region
to_add, to_del = diff stack-instances with deploy-targets
create-stack-instances(to_add)
delete-stack-instances(to_del)

有了上面这样的代码, 不管是第一次部署还是后续更新, 不管是添加还是删除部署目标, 直接改高级API上的参数就可以了.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK