本节内容:
    1. etcd介绍与使用
    2. ElastcSearch介绍与使用

1. etcd介绍与使用
    概念:高可用的分布式key-value存储,可以使用配置共享和服务发现
    类似项目:zookeeper和consul
    开发语言:Go
    接口:提供restful的http接口,使用简单
    实现算法:基于raft算法的强一致性、高可用的服务存储目录

2. etcd的应用场景
    a. 服务发现和服务注册
    b. 配置中心
    c. 分布式存储
    d. master选举

3. etcd搭建
    a. 下载etcd release版本:https://github.com/etcd-io/etcd/releases 版本
    b. 解压后,进入到etcd的根目录,直接执行./etcd 可以启动etcd
    c. 使用etcdctl工具更改配置

4. context使用介绍
    a. 如何控制goroutine
    b. 如何保存上下文数据

 (1)使用context处理超时
    ctx, cancel = context.With.Timeout(context.Background(), 2*time.Second)

示例是通过设置ctx超时时间为2s,如果2s类无法接收到baidu的请求返回,则超时异常。

 package main

 import (
"context"
"fmt"
"io/ioutil"
"net/http"
"time"
)
type Result struct {
r *http.Response
err error
} func process() {
ctx, cancel := context.WithTimeout(context.Background(), *time.Second)
defer cancel()
tr := &http.Transport{}
client := &http.Client{Transport: tr}
c := make(chan Result, )
req, err := http.NewRequest("GET", "http://www.baidu.com", nil)
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)
res := <-c
fmt.Println("Timeout! err:", res.err)
case res := <-c:
defer res.r.Body.Close()
out, _ := ioutil.ReadAll(res.r.Body)
fmt.Printf("Server Response: %s", out)
}
return
}
func main() {
process()
}

ctx_timeout

(2) 使用context保存上下文
    利用context来保存上下文值:

 package main

 import (
"context"
"fmt"
) func process(ctx context.Context) {
ret,ok := ctx.Value("trace_id").(int)
if !ok {
ret =
} fmt.Printf("ret:%d\n", ret) s , _ := ctx.Value("session").(string)
fmt.Printf("session:%s\n", s)
} func main() {
ctx := context.WithValue(context.Background(), "trace_id", )
ctx = context.WithValue(ctx, "session", "sdlkfjkaslfsalfsafjalskfj")
process(ctx)
}

ctx_value

同时还有context ctx_cancel 和 ctx_deadline

 package main

 import (
"context"
"fmt"
"time"
) func gen(ctx context.Context) <-chan int {
dst := make(chan int)
n :=
go func() {
for {
select {
case <-ctx.Done(): //当43行的test函数执行结束之后,执行defer cancel(),则会触发该行
fmt.Println("i exited")
return // returning not to leak the goroutine
case dst <- n:
n++
}
}
}()
return dst
} func test() {
// 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.
ctx, cancel := context.WithCancel(context.Background())
defer cancel() // cancel when we are finished consuming integers
intChan := gen(ctx)
for n := range intChan {
fmt.Println(n)
if n == {
break
}
}
}
func main() {
test()
time.Sleep(time.Hour)
}

ctx_cancel

 package main

 import (
"context"
"fmt"
"time"
) func main() {
d := time.Now().Add( * time.Millisecond)
ctx, cancel := context.WithDeadline(context.Background(), d) // Even though ctx will be expired, it is good practice to call its
// cancelation 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( * time.Second):
fmt.Println("overslept")
case <-ctx.Done():
fmt.Println(ctx.Err()) //context deadline exceeded
} }

ctx_deadline

5. etcd介绍与使用
    etcd使用示例 (由于虚拟机出现问题,后面的程序全在Windows上面操作):

(1)客户端连接 etcd server端

 package main

 import (
"fmt"
//etcd_client "github.com/coreos/etcd/clientv3"
etcd_client "go.etcd.io/etcd/clientv3"
"time"
) func main() { cli, err := etcd_client.New(etcd_client.Config{
Endpoints: []string{"localhost:2379", "localhost:22379", "localhost:32379"},
DialTimeout: * time.Second,
})
if err != nil {
fmt.Println("connect failed, err:", err)
return
} fmt.Println("connect succ")
defer cli.Close()
}

etcd_conn

(2)put 和 get

 package main

 import (
"context"
"fmt"
"go.etcd.io/etcd/clientv3"
"time"
) func main() { cli, err := clientv3.New(clientv3.Config{
Endpoints: []string{"localhost:2379", "localhost:22379", "localhost:32379"},
DialTimeout: * time.Second,
})
if err != nil {
fmt.Println("connect failed, err:", err)
return
} fmt.Println("connect succ")
defer cli.Close()
//设置1秒超时,访问etcd有超时控制
ctx, cancel := context.WithTimeout(context.Background(), *time.Second)
//操作etcd
_, err = cli.Put(ctx, "/logagent/conf/", "192.168.0.1")
//操作完毕,取消etcd
cancel()
if err != nil {
fmt.Println("put failed, err:", err)
return
}
//取值,设置超时为1秒
ctx, cancel = context.WithTimeout(context.Background(), *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)
}
}

put_get

(3)watch(观测key值发生变化)

 package main

 import (
"context"
"fmt"
"time" etcd_client "go.etcd.io/etcd/clientv3"
) func main() { cli, err := etcd_client.New(etcd_client.Config{
Endpoints: []string{"localhost:2379", "localhost:22379", "localhost:32379"},
DialTimeout: * time.Second,
})
if err != nil {
fmt.Println("connect failed, err:", err)
return
}
defer cli.Close() fmt.Println("connect succ") ctx, cancel := context.WithTimeout(context.Background(), *time.Second)
_, err = cli.Put(ctx, "/logagent/conf/", "")
if err != nil {
fmt.Println("put failed, err:", err)
return
}
cancel() fmt.Println("put succ") for {
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)
}
}
}
}

watch

运行上面的watch程序监控key(/logagent/conf/)操作的变化,然后再运行(2)的程序,结果如下:

kafka消费示例代码:

 package main

 import (
"fmt"
"strings"
"sync" "github.com/Shopify/sarama"
) var (
wg sync.WaitGroup
) func main() { consumer, err := sarama.NewConsumer(strings.Split("192.168:30.136:9092", ","), nil)
if err != nil {
fmt.Println("Failed to start consumer: %s", err)
return
}
partitionList, err := consumer.Partitions("nginx_log")
if err != nil {
fmt.Println("Failed to get the list of partitions: ", err)
return
} fmt.Println(partitionList) for partition := range partitionList {
pc, err := consumer.ConsumePartition("nginx_log", int32(partition), sarama.OffsetNewest)
if err != nil {
fmt.Printf("Failed to start consumer for partition %d: %s\n", partition, err)
return
}
defer pc.AsyncClose() go func(pc sarama.PartitionConsumer) {
wg.Add()
for msg := range pc.Messages() {
fmt.Printf("Partition:%d, Offset:%d, Key:%s, Value:%s", msg.Partition, msg.Offset, string(msg.Key), string(msg.Value))
fmt.Println()
}
wg.Done()
}(pc)
}
//time.Sleep(time.Hour)
wg.Wait()
consumer.Close()
}

kafka消费示例代码

6. sync.WaitGroup介绍
1)等待一组groutine结束
2)使用Add方法设置等待的数量加1
3)使用Delete方法设置等待的数量减1
4)当等待的数量等于0,Wait函数返回

sync.WaitGroup实例:

 package main

 import (
"fmt"
"sync"
"time"
) func main() {
wg := sync.WaitGroup{}
for i := ; i < ; i++ {
wg.Add()
go calc(&wg, i)
} wg.Wait() //阻塞,等待所有groutine结束
fmt.Println("all goroutine finish")
} func calc(w *sync.WaitGroup, i int) {
//注意: wg.Add(1) 放到这会有问题,也就是main函数结束比wg.Add(1)要快
fmt.Println("calc:", i)
time.Sleep(time.Second)
w.Done()
}

waitGroup示例

7. ElastcSearch安装及go操作es

(1)安装 es
   1)下载ES,下载地址:https://www.elastic.co/products/elasticsearch,我下载的是 elasticsearch-6.7.1.zip。
   2)修改在解压后根目录下的 /config/elasticsearch.yml 配置:

放开注释并将 youIP换成你自己机器的 ip

cluster.name: my-application
node.name: node-
network.host: youIP
http.port:

3)修改 /config/jvm.options 文件,当然如果机器性能好也可以不用修改:

-Xms512m
-Xmx512m

4)进入根目录,启动es,.\bin\elasticsearch.bat

(2)go 操作 es 示例

安装第三方插件:

go get gopkg.in/olivere/elastic.v2

示例:注意将程序里面的 url = "http://yourIP:9200/",yourIP替换为你安装es机器的 ip:

 package main

 import (
"fmt" elastic "gopkg.in/olivere/elastic.v2"
) type Tweet struct {
User string
Message string
} var (
url = "http://yourIP:9200/"
) func main() {
client, err := elastic.NewClient(elastic.SetSniff(false), elastic.SetURL(url))
if err != nil {
fmt.Println("connect es error", err)
return
} fmt.Println("conn es succ") tweet := Tweet{User: "olivere", Message: "Take Five"}
_, err = client.Index().
Index("twitter").
Type("tweet").
Id("").
BodyJson(tweet).
Do()
if err != nil {
// Handle error
panic(err)
return
} fmt.Println("insert succ")
}

es示例

链式存储:

 package main

 import "fmt"

 type Stu struct {
Name string
Age int
} func (p *Stu) SetName(name string) *Stu {
p.Name = name
return p
} func (p *Stu) SetAge(age int) *Stu {
p.Age = age
return p
} func (p *Stu) Print() {
fmt.Printf("age:%d name:%s\n", p.Age, p.Name)
} func main() {
stu := &Stu{}
stu.SetAge().SetName("stu01").Print()
//stu.SetName("stu01")
//stu.Print()
}

链式存储示例

Go语言学习之12 etcd、contex、kafka消费实例、logagent的更多相关文章

  1. C 语言学习 第12次作业总结

    作业总结 本次课堂的内容为字符串相关的几个函数还有结构体. 字符串相关函数 在此之前的课程中,输入主要都是使用scanf这个函数.而在这节课上,冯老师讲解了字符串获取函数gets.在不需要控制符的情况 ...

  2. Kafka消费与心跳机制

    1.概述 最近有同学咨询Kafka的消费和心跳机制,今天笔者将通过这篇博客来逐一介绍这些内容. 2.内容 2.1 Kafka消费 首先,我们来看看消费.Kafka提供了非常简单的消费API,使用者只需 ...

  3. 12天学好C语言——记录我的C语言学习之路(Day 12)

    12天学好C语言--记录我的C语言学习之路 Day 12: 进入最后一天的学习,用这样一个程序来综合考量指针和字符串的关系,写完这个程序,你对字符串和指针的理解应该就不错了. //输入一个字符串,内有 ...

  4. 12天学好C语言——记录我的C语言学习之路(Day 11)

    12天学好C语言--记录我的C语言学习之路 Day 11: 因为指针部分比较的难,所以我们花费的时间也是最长的,希望大家耐的住性子,多多理解,多多打代码.好了,废话不多说,来看第11天的学习. //编 ...

  5. 12天学好C语言——记录我的C语言学习之路(Day 10)

    12天学好C语言--记录我的C语言学习之路 Day 10: 接着昨天的指针部分学习,有这么一个题目: //还是四个学生,四门成绩,只要有学生一门功课没及格就输出这个学生的所有成绩 /*//progra ...

  6. 12天学好C语言——记录我的C语言学习之路(Day 9)

    12天学好C语言--记录我的C语言学习之路 Day 9: 函数部分告一段落,但是我们并不是把函数完全放下,因为函数无处不在,我们今后的程序仍然会大量运用到函数 //转入指针部分的学习,了解指针是什么 ...

  7. 12天学好C语言——记录我的C语言学习之路(Day 8)

    12天学好C语言--记录我的C语言学习之路 Day 8: 从今天开始,我们获得了C语言中很有力的一个工具,那就是函数.函数的魅力不仅于此,一个程序到最后都是由众多函数组成的,我们一定要用好函数,用熟练 ...

  8. 12天学好C语言——记录我的C语言学习之路(Day 7)

    12天学好C语言--记录我的C语言学习之路 Day 7: 昨天进行了一天的数组学习,今天大家可以先写几个昨天的程序热热身,回顾回顾,然后今天第一个新程序也是关于数组的,比较难,准备好就开始啦! //输 ...

  9. 12天学好C语言——记录我的C语言学习之路(Day 6)

    12天学好C语言--记录我的C语言学习之路 Day 6: 今天,我们要开始学习数组了. //①数组部分,数组的大小不能够动态定义.如下: //int n;   scanf("%d,& ...

随机推荐

  1. iOS 上架注意

    一.推送证书 配置推送证书的流程说明:https://docs.aws.amazon.com/zh_cn/pinpoint/latest/developerguide/apns-setup.html ...

  2. 一张图解释IaaS,PaaS,SaaS

    图片来源于MVA教程:快速入门——面向IT专业人员的Windows Azure IaaS

  3. VMware卸载有残留,再安装时报错提示MSI Failed

    引用自吾爱破解论坛:https://www.52pojie.cn/thread-455779-1-1.html 解决方法:软件自动清理法: 软件 地址:下载地址1:链接:http://pan.baid ...

  4. JDK8 BigDecimal API-创建BigDecimal源码浅析三

    第三篇 先介绍以BigInteger为构造参数的构造器 public BigDecimal(BigInteger val) {// 根据BigInteger创建BigDecimal对象 scale = ...

  5. 平衡树-Splay

    #include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #def ...

  6. 解决CentOS(6和7版本),/etc/sysconfig/下没有iptables的问题

    一.Centos 6版本解决办法: 1.任意运行一条iptables防火墙规则配置命令: iptables -P OUTPUT ACCEPT 2.对iptables服务进行保存: service ip ...

  7. 微信扫描二维码安卓弹出默认浏览器(苹果打开App Store)打开下载链接

    使用微信推广的用户经常都会遇到推广链接被拦截导致无法下载app的情况,此时用户在微信中打开会提示“ 已停止访问该网页 ”.这对于使用微信营销的商家来说就很不友好且损失非常大,因为用户是不知道为什么打不 ...

  8. 用Nuget部署程序包

    用Nuget部署程序包 Nuget是.NET程序包管理工具(类似linux下的npm等),程序员可直接用简单的命令行(或VS)下载包.好处: (1)避免类库版本不一致带来的问题.GitHub是管理源代 ...

  9. datatable的select()结果直接修改,会体现在表上

    如果你只是要修改DataTable里的DataRow的话没有必要找到它的行号,直接在Select后得到的DataRow上修改就行了,它的修改会直接反映到DataTable上(其实就是直接修改了Data ...

  10. Linux基础命令---ipcs显示进程通信

    ipcs ipcs指令用来显示进程间通信状况.“-i”选项允许指定特定的资源id.将只打印有关此id的信息. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.Fedora.SUS ...