当前位置:网站首页>go-etcd
go-etcd
2022-07-01 06:52:00 【ALEX_CYL】
1.etcd简介
高可用的分布式key-val存储,可以用于配置共享和服务发现
类似项目:zookeeper(java)和consul(go)
开发语言:go
接口:提供restful的http接口,使用简单
实现算法:基于raft一致性算法的强一致性、高可用(多个备份)的服务存储目录。
etcd 与redis:
redis集群一般是一主两从,主写入数据,从读出数据,故可能存在信息更新延迟;etcd的强一致性确保热和任何节点的数据都是一致的。故对与强一致性要求高的选用etcd,一致性要求不是很严的可选用redis,redis的读取速度优秀。
etcd 使用场景:
1.服务注册和服务发现
2.配置中心
3.分布式锁(强一致性)
4.master选举
2. etcd安装
安装etcd+etcdkeeper合集
启动etcd,使用etcdctl执行命令操作,默认端口"2379"
3.go 使用etcd的基础知识
3.1.context包的使用:
context包定义了context. Context 类型,它携带跨越 API 边界和进程之间的截止日期、取消信号和其他请求范围的值。对服务器的传入请求应该创建一个上下文,对服务器的传出调用应该接受一个上下文。它们之间的函数调用链必须传播 Context,可选择将其替换为使用 WithCancel、WithDeadline、WithTimeout 或 WithValue 创建的派生 Context。当一个上下文被取消时,所有从它派生的上下文也被取消。
3.1.1 WithCancel
package main
import (
"context"
"fmt"
"time"
)
func main() {
// gen generates integers in a separate goroutine and
// sends them to the returned channel.
// The callers of gen need to cancel the context once
// they are done consuming generated integers not to leak
// the internal goroutine started by gen.
gen := func(ctx context.Context) <-chan int {
dst := make(chan int)
n := 1
go func() {
//后台持续运行
for {
select {
case <-ctx.Done():
fmt.Println("goroutine exit")
return // returning not to leak the goroutine
case dst <- n:
fmt.Println("goroutine run")
n++
}
}
}()
fmt.Println("返回")
return dst
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel() // cancel when we are finished consuming integers
for n := range gen(ctx) {
fmt.Println(n)
if n == 5 {
break
}
}
time.Sleep(time.Second)
}
输出
返回
goroutine run
1
2
goroutine run
goroutine run
3
4
goroutine run
goroutine run
5
3.1.2 WithDeadline
package main
import (
"context"
"fmt"
"time"
)
const shortDuration = 1 * time.Millisecond
func main() {
d := time.Now().Add(shortDuration)
ctx, cancel := context.WithDeadline(context.Background(), d)
// Even though ctx will be expired, it is good practice to call its
// cancellation function in any case. Failure to do so may keep the
// context and its parent alive longer than necessary.
defer cancel()
select {
case <-time.After(1 * time.Second):
fmt.Println("overslept")
case <-ctx.Done():
fmt.Println(ctx.Err())
}
}
3.1.3 WithTimeout
package main
import (
"context"
"fmt"
"io/ioutil"
"net/http"
"time"
)
type Result struct {
r *http.Response
err error
}
func process() {
// 基础ctx
baseCtx := context.Background()
// 设定context.WithTimeout
ctx, cancel := context.WithTimeout(baseCtx, 2*time.Second)
defer cancel()
tr := &http.Transport{
}
client := &http.Client{
Transport: tr}
c := make(chan Result, 1)
req, err := http.NewRequest("Get", "http://www.baidu.com", nil) //http://google.com
if err != nil {
fmt.Println("http request failed, err:", err)
return
}
go func() {
resp, err := client.Do(req)
pack := Result{
r: resp, err: err}
c <- pack
}()
select {
case <-ctx.Done():
tr.CancelRequest(req) //超时,取消http请求,
res := <-c //client.Do(),由于请求取消返回一个错误
fmt.Println("Timeout!,errr:", res.err)
case res := <-c:
if res.err != nil {
fmt.Println("Server Response ,client.Do() err:", err)
} else {
defer res.r.Body.Close()
out, _ := ioutil.ReadAll(res.r.Body)
fmt.Printf("Server Response :%s\n", out)
}
}
return
}
func main() {
process()
}
3.1.4 WithValue
package main
import (
"context"
"fmt"
)
type favContextKey string
func process1(ctx context.Context, k favContextKey) {
if ret := ctx.Value(k); ret != nil {
fmt.Println("found value:", ret)
return
}
fmt.Println("Not found key", k)
}
func process(ctx context.Context) {
ret, ok := ctx.Value("trace_id").(int)
if !ok {
ret = 12161844
}
fmt.Printf("ret:%d\n", ret)
if s := ctx.Value("session"); s != nil {
fmt.Println("found value:", s)
} else {
fmt.Println("not found key:", "session")
}
}
func main() {
basectx := context.Background()
// contex.WithValue()
var k favContextKey = "trace_id"
ctx := context.WithValue(basectx, k, 12161811)
process1(ctx, k)
ctx = context.WithValue(ctx, "session", "day-1") //ctx 可继承的树状结构
process(ctx)
}
3.2 etcd 使用
3.2.1 etcd_connect
package main
import (
"fmt"
"time"
etcd_client "github.com/coreos/etcd/clientv3"
)
func main() {
cli, err := etcd_client.New(etcd_client.Config{
Endpoints: []string{
"localhost:2379", "localhost:22379", "localhost:32379"},
DialTimeout: 5 * time.Second,
})
if err != nil {
fmt.Println("connect failed,err :", err)
return
}
defer cli.Close()
fmt.Println("connect succ")
}
3.2.2 etcd_example
get/put使用
package main
import (
"context"
"fmt"
"time"
etcd_client "github.com/coreos/etcd/clientv3"
)
func main() {
cli, err := etcd_client.New(etcd_client.Config{
Endpoints: []string{
"localhost:2379", "localhost:22379", "localhost:32379"},
DialTimeout: 5 * time.Second,
})
if err != nil {
fmt.Println("connect failed,err :", err)
return
}
fmt.Println("connect succ")
defer cli.Close()
baseCtx := context.Background()
ctx, cancel := context.WithTimeout(baseCtx, time.Second)
_, err = cli.Put(ctx, "/logagent/conf/", "sample_value")
cancel()
if err != nil {
fmt.Println("put failed,err:", err)
return
}
ctx, cancel = context.WithTimeout(baseCtx, time.Second)
resp, err := cli.Get(ctx, "/logagent/conf/")
cancel()
if err != nil {
fmt.Println("get failed,err:", err)
return
}
for _, ev := range resp.Kvs {
fmt.Printf("%s:%s\n", ev.Key, ev.Value)
}
}
3.2.3 etcd_wath
监听配置/节点配置信息的更新
package main
import (
"fmt"
"time"
"github.com/coreos/etcd/Godeps/_workspace/src/golang.org/x/net/context"
etcd_client "github.com/coreos/etcd/clientv3"
)
func main() {
cli, err := etcd_client.New(etcd_client.Config{
Endpoints: []string{
"localhost:2379", "localhost:22379", "localhost:32379"},
DialTimeout: 5 * time.Second,
})
if err != nil {
fmt.Println("connect failed,err :", err)
return
}
fmt.Println("connect succ")
defer cli.Close()
for {
//持续监听,配置是否有变化 watch 主动告知配置有变
rch := cli.Watch(context.Background(), "/logagent/conf/") //阻塞在此处,有新变化,管道输出信息
for wresp := range rch {
for _, ev := range wresp.Events {
fmt.Printf("%s %q : %q\n", ev.Type, ev.Kv.Key, ev.Kv.Value)
}
}
}
}
边栏推荐
- buildroot override 机制
- 产品学习(一)——结构图
- 【LINGO】求七个城市最小连线图,使天然气管道价格最低
- Esp32 - ULP coprocessor reading Hall sensor in low power mode
- 2022 年江苏省职业院校技能大赛(中职) 网络搭建与应用赛项公开赛卷
- Solve the problem that the class defined in meta-inf.services cannot be read
- SQL learning notes 2
- ctfshow-web352,353(SSRF)
- 发现了一个 MySQL 的巨坑:update 更新别再用影响行数做判断了!!!
- 【MATLAB】求解非线性规划
猜你喜欢

(I) apple has open source, but so what?

Solve the problem of "unexpected status code 503 service unavailable" when kaniko pushes the image to harbor

图解事件坐标screenX、clientX、pageX, offsetX的区别
![[Tikhonov] image super-resolution reconstruction based on Tikhonov regularization](/img/49/719496e014f4766d22aba44dbed19e.png)
[Tikhonov] image super-resolution reconstruction based on Tikhonov regularization

比赛即实战!中国软件杯发布全新产业创新赛项,校企可联合参赛

Spark入门(一篇就够了)

Notes on probability theory

ESP32 ESP-IDF ADC监测电池电压(带校正)

【FPGA帧差】基于VmodCAM摄像头的帧差法目标跟踪FPGA实现

Why are so many people turning to product managers? What is the development prospect of product manager?
随机推荐
WiFi settings for raspberry Pie 4
在长城证券上做基金定投安全吗?
Jena default inference query based on OWL
Esp32 esp-idf GPIO key interrupt response
(I) apple has open source, but so what?
Some pits designed by NOC
【MATLAB】求解非线性规划
数据库笔记
Problem: officeexception: failed to start and connect (III)
【Tikhonov】基于Tikhonov正则化的图像超分辨率重建
Spark入门(一篇就够了)
Principle of introducing modules into node
Router 6/ 以及和Router5 的区别
产品学习(一)——结构图
Why did grayscale fall from the altar?
Record an online interface slow query problem troubleshooting
MySQL data type learning notes
TDB中多个model情况下使用fuseki查询
How the esp32 deep sleep current is lower than 10uA
【微信小程序】一文解决button、input、image组件