配置中心

在之前 tcp的yaml配置 介绍了如何监听yaml文件变化然后更新配置。

当然假如我们有很多实例,那么yaml改动将是非常痛苦的事情,那么如何做到配置文件统一管理,实时更新呢?

我们可以引入配置中心,从而达到这样的效果。

业界已经有非常多配置中心了,这里为了简化内容,将选用etcd作为配置中心来介绍实现。

etcd

etcd 是一个分布式键值对存储系统。

设计用于可靠存储不频繁更新的数据,并提供可靠的观察查询。

etcd 暴露键值对的先前版本来支持不昂贵的快速和观察历史事件(“time travel queries”)。

对于这些使用场景,持久化,多版本,并发控制的数据模型是非常适合的。

ectd 使用多版本持久化键值存储来存储数据。

当键值对的值被新的数据替代时,持久化键值存储保存先前版本的键值对。

键值存储事实上是不可变的;它的操作不会就地更新结构,替代的是总是生成一个新的更新后的结构。

在修改之后,key的所有先前版本还是可以访问和观察的。为了防止随着时间的过去为了维护老版本导致数据存储无限增长,存储应该压缩来脱离被替代的数据的最旧的版本。

所以其非常适合作为配置中心,每一个配置变动都是有序的。

使用 etcd

大家测试可以使用docker 实验

docker run -p 2479:2479 -p 2480:2480 --mount type=bind,source=$(shell pwd)/tmp/etcd-data.tmp,destination=/etcd-data --name etcd \
gcr.io/etcd-development/etcd:v3.5.0 \
/usr/local/bin/etcd \
--name s1 \
--data-dir /etcd-data \
--listen-client-urls http://0.0.0.0:2479 \
--advertise-client-urls http://0.0.0.0:2479 \
--listen-peer-urls http://0.0.0.0:2480 \
--initial-advertise-peer-urls http://0.0.0.0:2480 \
--initial-cluster s1=http://0.0.0.0:2480 \
--initial-cluster-token tkn \
--initial-cluster-state new \
--log-level info \
--logger zap \
--log-outputs stderr

cli

可以使用 cli 工具: https://github.com/etcd-io/etcd/tree/main/etcdctl

./etcdctl put foo bar --lease=1234abcd
# OK
./etcdctl get foo
# foo
# bar
./etcdctl put foo --ignore-value # to detache lease
# OK

ui

或者使用ui工具: https://github.com/evildecay/etcdkeeper

实践

以下内容更新到 openresty-dev-1.rockspec

-- 依赖包
dependencies = {
"lua-resty-etcd >= 1.9.0",
}

然后执行

luarocks install openresty-dev-1.rockspec --tree=deps --only-deps --local

代码内容:

worker_processes  1;        #nginx worker 数量
error_log logs/error.log; #指定错误日志文件路径
events {
worker_connections 1024;
} http {
log_format main '$remote_addr [$time_local] $status $request_time $upstream_status $upstream_addr $upstream_response_time';
access_log logs/access.log main buffer=16384 flush=3; #access_log 文件配置 lua_package_path "${prefix}deps/share/lua/5.1/?.lua;${prefix}deps/share/lua/5.1/?/init.lua;${prefix}?.lua;${prefix}?/init.lua;;./?.lua;/usr/local/openresty/luajit/share/luajit-2.1.0-beta3/?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/usr/local/openresty/luajit/share/lua/5.1/?.lua;/usr/local/openresty/luajit/share/lua/5.1/?/init.lua;";
lua_package_cpath "${prefix}deps/lib64/lua/5.1/?.so;${prefix}deps/lib/lua/5.1/?.so;;./?.so;/usr/local/lib/lua/5.1/?.so;/usr/local/openresty/luajit/lib/lua/5.1/?.so;/usr/local/lib/lua/5.1/loadall.so;";
# 开启 lua code 缓存
lua_code_cache on; upstream nature_upstream {
server 127.0.0.1:6699; #upstream 配置为 hello world 服务 # 一样的balancer
balancer_by_lua_block {
local balancer = require "ngx.balancer"
local upstream = ngx.ctx.api_ctx.upstream
local ok, err = balancer.set_current_peer(upstream.host, upstream.port)
if not ok then
ngx.log(ngx.ERR, "failed to set the current peer: ", err)
return ngx.exit(ngx.ERROR)
end
}
} # 换为init_worker 是因为 init 不允许请求etcd
init_worker_by_lua_block { node = nil
-- 匹配路由, 为了演示,这里简化为单个节点,并且路由处理也去掉了
router_match = function()
return node
end -- 从etcd 加载配置,同理为了演示简单,这里只做单个节点
local etcdlib = require("resty.etcd").new({
protocol = "v3",
api_prefix = "/v3",
http_host = 'http://127.0.0.1:2479',
key_prefix = '/test/'
}) -- 这里为了简单,展示轮询方式, watch 的方式可以参考 https://github.com/fs7744/nature/blob/main/nature/config/etcd.lua
ngx.timer.every(1, function()
local res, err = etcdlib:get('node')
local json = require('cjson.safe') if res ~= nil and res.body ~= nil and res.body.kvs ~= nil and res.body.kvs[1] ~= nil then
node = res.body.kvs[1].value
ngx.log(ngx.ERR, json.encode(node))
end
end)
} server {
#监听端口,若你的8699端口已经被占用,则需要修改
listen 8699 reuseport; location / { # 在access阶段匹配路由
access_by_lua_block {
local upstream = router_match()
if upstream then
ngx.ctx.api_ctx = { upstream = upstream }
else
ngx.exit(404)
end
} proxy_http_version 1.1;
proxy_pass http://nature_upstream; #转发到 upstream
}
} #为了大家方便理解和测试,我们引入一个hello world 服务
server {
#监听端口,若你的6699端口已经被占用,则需要修改
listen 6699;
location / {
default_type text/html; content_by_lua_block {
ngx.say("HelloWorld")
}
}
}
}

启动服务并测试

$ openresty -p ~/openresty-test -c openresty.conf #启动
$ curl --request GET 'http://127.0.0.1:8699/aa/d' #第一次测试
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
</body>
</html>
$ ./etcdctl put /test/node {"host":"127.0.0.1","port":6699} # 写入测试节点数据
$ curl --request GET 'http://127.0.0.1:8699/aa/d' #第二次测试
HelloWorld

可以看到获取到了etcd的配置变化

目录

构建api gateway之 基于etcd实现动态配置同步的更多相关文章

  1. Yii2 advanced版API接口开发 基于RESTful架构的 配置、实现、测试

    参考地址: http://www.xiaoxiangzi.com/Programme/PHP/3348.html http://www.cnblogs.com/ganiks/p/yii2-restfu ...

  2. 基于通用jar、动态配置、组件编排的会员任务中心系统设计

    # 一.聊聊本文想说什么:   为更好帮助商家的会员快速成长,保持用户活性,完善用户的成长体系,有赞用户中心-会员成长团队基于现有的业务场景,设计了一套较完备任务中心系统.同时也有很多通用技术组件能够 ...

  3. 实战:基于 Spring 的应用配置如何迁移至阿里云应用配置管理 ACM

    最近遇到一些开发者朋友,准备将原有的Java Spring的应用配置迁移到 阿里云应用配置管理 ACM 中.迁移过程中,遇到不少有趣的问题.本文将通过一个简单的样例来还原迁移过程中遇到的问题和相关解决 ...

  4. [转载] 构建微服务:使用API Gateway

    原文: http://mp.weixin.qq.com/s?__biz=MzA5OTAyNzQ2OA==&mid=206889381&idx=1&sn=478ccb35294c ...

  5. 0601-Zuul构建API Gateway-API gateway简介、基础使用、路由配置、负载配置

    一.API Gateway简介 参看:http://www.cnblogs.com/bjlhx/p/8794437.html 二.zuul简介[路由器和过滤器:Zuul] 在微服务架构的组成部分进行路 ...

  6. 基于etcd插件的CoreDNS动态域名添加

    前提条件:已经有一个可用的etcd环境. 一.CoreDNS简介 CoreDNS是一个DNS服务器,和Caddy Server具有相同的模型:它链接插件.CoreDNS是云本土计算基金会启动阶段项目. ...

  7. 基于aws api gateway的asp.net core验证

    本文是介绍aws 作为api gateway,用asp.net core用web应用,.net core作为aws lambda function. api gateway和asp.net core的 ...

  8. 谈谈微服务中的 API 网关(API Gateway)

    前言 又是很久没写博客了,最近一段时间换了新工作,比较忙,所以没有抽出来太多的时间写给关注我的粉丝写一些干货了,就有人问我怎么最近没有更新博客了,在这里给大家抱歉. 那么,在本篇文章中,我们就一起来探 ...

  9. 微服务中的 API 网关(API Gateway)

    API 网关(API Gateway)提供高性能.高可用的 API 托管服务,帮助用户对外开放其部署在 ECS.容器服务等云产品上的应用,提供完整的 API 发布.管理.维护生命周期管理.用户只需进行 ...

  10. API Gateway微服务

    微服务中的 API 网关(API Gateway)   前言 又是很久没写博客了,最近一段时间换了新工作,比较忙,所以没有抽出来太多的时间写给关注我的粉丝写一些干货了,就有人问我怎么最近没有更新博客了 ...

随机推荐

  1. Rust构建环境搭建

    ###安装涉及的概念rustup : 安装rust和管理版本的工具,当前rust尚处于发展阶段,存在三种类型的版本,稳定版.测试版.每日构建版本,使用rustup可以在这三种的版本之间切换,默认是稳定 ...

  2. 微服务系列之服务注册发现 Consul

    1.为什么需要服务注册与发现   微服务架构中,服务于服务之间内部通信必不可少,比如A服务调用B服务,起初我们的做法是,A服务从配置文件中拿到B服务的IP.端口地址,进行访问,本身是没什么问题的,但是 ...

  3. day24-服务器端渲染技术02

    服务器端渲染技术02 11.EL表达式 11.1EL表达式介绍 EL表达式全称:Expression Language,是表达式语言 EL表达式主要是代替jsp页面的表达式脚本 EL表达式输出数据时, ...

  4. 规则引擎Drools在贷后催收业务中的应用

    作者:vivo 互联网服务器团队- Feng Xiang 在日常业务开发工作中我们经常会遇到一些根据业务规则做决策的场景.为了让开发人员从大量的规则代码的开发维护中释放出来,把规则的维护和生成交由业务 ...

  5. 喜欢用Map却从未遭遇内存泄露的Java程序员上辈子都是神仙

    前言 点进来这篇文章的大概有两种人,一种是喜欢用Map的想看看自己是不是有可能也会踩雷,一种是不喜欢用Map的想进来看看那些喜欢用的人是怎么踩雷的. 那你要失望了,我只是单纯把公司最近代码审查时一个关 ...

  6. MYSQL快速安装整理

    参考教程:https://www.cnblogs.com/brad93/p/16650780.html [检查是否已安装过] find / -name mysql [快速安装开始] groupadd  ...

  7. 【大数据课程】高途课程实践-Day01:Python编写Map Reduce函数实现各商品销售量展示(类似wordcount)

    〇.概述 1.工具 http://www.dooccn.com/python3/ 在线运行Python代码 2.步骤 (1)⽣成代码测试数据 (2)编写Mapper逻辑 (3)编写Reducer逻辑 ...

  8. [数据结构]单向链表及其基本操作(C语言)

    单向链表 什么是单向链表 链表是一种物理储存单元上非连续.非顺序的储存结构.它由一系列结点(链表中每一个元素称为结点)组成,结点可动态生成.每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存 ...

  9. GitHub上的一个Latex模板

    代码下载:GitHub的项目地址或者在LATEX项目报告模板下载. 编译环境:Latex的编译器,如Ctex软件. 把源码clone或者下载到本地后,根据他的说明 如何开始 使用report.tex开 ...

  10. 4、Idea设置显示多行文件

    使用IDEA时,可能会没有注意到,一旦打开过多的Java文件时,默认会堆积在一行显示,就像浏览器打开了多个标签一样,此时需要通过右侧箭头筛选的方式来选择其他文件.为了解决这一问题,需要打开多行显示的方 ...