- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
在之前 tcp的yaml配置 介绍了如何监听yaml文件变化然后更新配置.
当然假如我们有很多实例,那么yaml改动将是非常痛苦的事情,那么如何做到配置文件统一管理,实时更新呢?
我们可以引入配置中心,从而达到这样的效果.
业界已经有非常多配置中心了,这里为了简化内容,将选用etcd作为配置中心来介绍实现.
etcd 是一个分布式键值对存储系统.
设计用于可靠存储不频繁更新的数据,并提供可靠的观察查询.
etcd 暴露键值对的先前版本来支持不昂贵的快速和观察历史事件(“time travel queries”).
对于这些使用场景,持久化,多版本,并发控制的数据模型是非常适合的.
ectd 使用多版本持久化键值存储来存储数据.
当键值对的值被新的数据替代时,持久化键值存储保存先前版本的键值对.
键值存储事实上是不可变的;它的操作不会就地更新结构,替代的是总是生成一个新的更新后的结构.
在修改之后,key的所有先前版本还是可以访问和观察的。为了防止随着时间的过去为了维护老版本导致数据存储无限增长,存储应该压缩来脱离被替代的数据的最旧的版本.
所以其非常适合作为配置中心,每一个配置变动都是有序的.
大家测试可以使用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 工具: 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工具: 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的配置变化 。
最后此篇关于构建apigateway之基于etcd实现动态配置同步的文章就讲到这里了,如果你想了解更多关于构建apigateway之基于etcd实现动态配置同步的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我们正在使用 AWS API Gateway,我正在使用 CloudFormation 注册域和 A 记录,如下所示: Domain: Type: AWS::ApiGateway::Dom
我有以下 CF 模板 { "Conditions":{ "CreatedProdStage" : {...} } ... "Resources":{
我目前正在将 AWS Lambda 用于我的内部应用程序到使用 jreSTLess 实现的 spring 框架的应用程序调用。 应用程序调用的应用程序完美运行,延迟适中(理想情况下约为 10-15 毫
我们有一个返回 gzip 编码的端点。我们想要缓存该值,我们正在使用 ApiGateway 来为我们做到这一点。资源方法定义如下, GetManifestApiGatewayMethod: # ver
我正在处理swagger文件,要在aws apigateway中创建授权者。但是这次我会在swagger文件中提到一些函数和api。但是它不会在Apigateway中生效。一旦我删除了堆栈,它就会生效
在使用 Cognito 和 API Gateway 访问我们的 REST API 时遇到问题 我这辈子都找不到一个简单的例子来说明如何在我们的 AWS 服务器上调用安全的 REST API。 我打电话
我正在使用 AWS CDK 构建我的 lambda,我想从 lambda 的 CDK 堆栈注册端点。 我发现我可以使用 fromRestApiId(scope, id, restApiId) 获取现有
我使用此配置部署到“Prod”阶段: "ApiGatewayApi": { "Type": "AWS::Serverless::Api", "Properties": {
我有一个 API 网关集成,其中数据直接发送到 dynamodb。 x-amazon-apigateway-integration 定义了响应代码映射,因此我的目的是在客户端获取 dynamodb 抛
下面是我的cloudformation模板。我想将 aws:SourceVpc 转换为资源策略文档中的列表。我尝试了溢出但低于错误。 政策文件无效。请检查策略语法并确保主体有效。 (服务:Amazon
我有一个由多个 lambda 组成的状态机,我使用 Cloudformation 模板设置了这些 lambda,该模板执行一些处理并最终将文件保存到 S3;除非有要求,否则我不会在这里添加它,因为它可
我正在使用 vert.x 和 RxJava 开发 Apigateway。我想发送 2 个 Api 的响应式(Reactive)请求,从它们那里获取响应并通过 HttpServer 发送组合的 JSON
我正在使用 AWS SignV4 签署调用 AWS API Gateway 的请求。使用带 header 的请求不适合我的用例,因此主动使用签名网址和查询字符串。 我用过AWS Sample Pyth
我正在为我的电子商务应用程序创 build 计。它将拥有由 AWS Lambda 支持的多项服务。 Orderservice、InventoryService、PaymentService、Loggi
我能够使用 Cloudformation/无服务器应用程序模型定义和部署我的 API 网关 + Lambda 堆栈,并希望向我的 API 添加模型。 我已在 YAML 中创建了模型,但它似乎无法引用我
我看不到更新 AWS APIGateway 自定义域上的证书的方法。如果我使用新证书创建新的自定义域,则无法使用现有的 *.cloudfront.net 域。我将不得不更新 DNS 以指向新域。 有没
刚刚通过 AWS 学习 - 我有一个 APIGateway REST API 设置与 Lambda 代理集成。 API 定义了一个模型,并使用该模型在主体上请求验证设置。 假设模型是 { "$
没有找到任何有关如何实现 Cloudfront + MTLS 或 Api Gateway + MTLS 的资料。可能吗?如果没有,是否有其他方法可以使用 CloudFront + ApiGateway
我在 ApiGateway 中使用 Lambda 代理和 Cognito 用户池授权器。在 Lambda 函数中,我可以通过事件对象访问路径等变量。除此之外,我想访问经过身份验证的用户的声明。在它写的
如何使用 AWS-CDK 从 apigateway 迁移到 apigatewayv2? 具体来说:我正在使用 LambdaRestApi和 restApiId和 deploymentStage从那个资
我是一名优秀的程序员,十分优秀!