MENU

脑抽记录:etcd

January 28, 2021 • 折腾

etcd-horizontal-color.png
上图采自 etcd 在 Github 的项目页:https://github.com/etcd-io/etcd

etcd 是 CoreOS 团队于 2013 年 6 月发起的开源项目,它的目标是构建一个高可用的分布式键值(key-value)数据库。etcd 内部采用 raft 协议作为一致性算法,etcd 基于 Go 语言实现。

前言

2016 年至 2020 年期间,我曾开发过一套适用于模拟飞行业务的自动化运行体系,主要是处理各类数据的更新,各个子系统之间的协同。做了一套无状态的通讯接口,好吧说人话就是,基于 HTTP 的 WebAPI。那么随着时间的推移,自己能力的提升,当然也是需要随着技术的发展,尝试一些新东西,作为一个 Gopher,etcd 就是一个非常合适的切入点,在使用的同时,也可以拜读一下源码,进一步学习,业务和学习两不误。

2021.1.27 当头一棒 HTTP 404 NOT FOUND

第一个场景,就是逐渐重写原先那套用了近 4 年的 WebAPI,主要使用的语言是 PHP,当然近一年 Golang 实现的之后计划也要随之做改动。先前是用自己实现的 PHP 一套简约框架,主要实现了路由,调用各个类,十分简单。那么这次是选用 ThinkPHP6 来重构,有了先前的基础,以及得益于 ThinkPHP 的封装,开发速度和代码可读性提高了不少。(其实一开始想选用 Laravel 的,但实在是看手册看的太累。)

在使用之前就了解到,我目前是用的版本 v3,相较于 v2,已经将效率不高的 HTTP API 转变成了 JSON gRPC 接口,但是依旧保留了 HTTP 的 Gateway,也就是说还是可以用 HTTP 的方式来操作 etcd 的,这对 PHP 十分友好,维护长连接不是 PHP 适合的事,尤其是在无状态接口的具体实现中添加长连接的代码。我尝试了官方文档中给出的示例,如下

curl -L http://localhost:2379/v3beta/kv/put -X POST -d '{"key": "Zm9v", "value": "YmFy"}'

说白了就是,用 POST 请求,发送一个 JSON String,Key 和 Value 的实体均用 Base64 编码,来实现对 etcd 的 kv 存储操作。
结果却得出:404 NOT FOUND。

  • 解决:在 etcd v3.3 版本之后,使用带 yaml 配置启动时,如果不显式指定enable-grpc-gateway: true,则不启用 HTTP 功能。
    增加配置即可解决。

2021.1.28 不断增长的内存

自己的 VPS,剩余的内存不多了,大概只有两三百兆,应付简单的服务还是足够的,毕竟我不开发 Java。
随着 etcd 的不断运行,我发现内存占用逐渐变大,磁盘占用也多了,etcd v3 的更新之后,是会保存每一个更新的数据版本,那么怎么抛弃掉无用的呢?

  • 解决:在启动时添加参数--auto-compaction-retention=1只保留最近一个小时的更新记录,自动压缩数据。

2021.2.18 拙劣的 API 结合

就贴代码吧,没什么技术含量,只是简单再封装了\Etcd\Client,让他更适合自己的业务,由于 lease 长度已经超过了 int32 最大能表示的范围,故建议在 64 位平台运行。

<?php
namespace app\extend;
use think\facade\Cache;
use think\facade\Config;
class apiNodeEtcdClient
{

    private $lease;
    private $etcdClient;

    public function __construct(){
        $this->etcdClient = new \Etcd\Client(Config::get('etcd.host'),"v3");
        $this->lease = Cache::get('apiEtcdLease.Global');
    }

    public function keepAlive(){
        if($this->etcdClient->timeToLive($this->getLease())['TTL'] == '-1'){
            $this->lease = $this->etcdClient->grant(1800);
            Cache::set('apiEtcdLease.Global', $this->lease['ID']);
        }
        return $this->etcdClient->keepAlive($this->getLease());
    }
    public function revoke(){
        $this->etcdClient->revoke($this->getLease());

    }
    public function put($key, $value)
    {
        return $this->etcdClient->put($key, $value, ['lease' => $this->getLease()]);
    }

    public function get($key)
    {
        return $this->etcdClient->get($key);
    }
    public function getAllKeys()
    {
        return $this->etcdClient->getAllKeys();
    }
    public function getKeysWithPrefix($prefix)
    {
        return $this->etcdClient->getKeysWithPrefix($prefix);
    }
    private function getLease(){
        return (integer)$this->lease;
    }
}
Last Modified: February 18, 2021
Archives QR Code
QR Code for this page
Tipping QR Code