本节内容:
    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. centos7 vmd-1.9.3安装

    1. 下载安装包 安装包下载地址是http://www.ks.uiuc.edu/Research/vmd/,选择自己合适的版本,我下载1.9.3版本 2. 安装必要库 yum install free ...

  2. Google word/sheets 常见的使用:

    Google Sheets: 1, sheets 里面的单元格设置自动换行: 选中单元格: --> Format --> Text Wrapping --> Wrap(自动换行)/C ...

  3. Elasticsearch.安装插件(head)

    Elasticsearch.安装插件(head) 环境: Linux 7.x jdk1.8 目录结构(跟目录多了两个文件) /resources   ### 存放软件源 /u01/          ...

  4. linux 中的 vim 设置粘贴板

    https://blog.csdn.net/zhangxiao93/article/details/53677764 亲测有效

  5. C# 求链表 list 中 属性的 最大值 最小值

    获取链表List中对象属性最大值最小值(Max,Min)的方法: 1.创建一个类,类中有一个属性A /// <summary> /// 用于测试属性的类 /// </summary& ...

  6. Nginx 修改用户权限

    [1]Nginx 修改用户权限 (1)修改前:Nginx系统默认用户权限是nobody 查看可知: (2)修改方法 欲使用root权限启动的. 修改 /usr/local/nginx/conf/ 下n ...

  7. Linux代理服务器—squid正向代理实验

    1.代理服务器squid简介 Squid cache(简称为Squid)是一个流行的自由软件(GNU通用公共许可证)的代理服务器和Web缓存服务器.Squid有广泛的用途,从作为网页服务器的前置cac ...

  8. uploadify上传图片的使用

    一:引用jquery.uploadify.js 二:代码 <body> <table> <tr> <td style="width: 15%; te ...

  9. Java8过滤器(Filter)

    1.在Java之前对List进行过滤的方式 public class BeforeJava8 { public static void main(String[] args) { List<Pe ...

  10. Spring AOP 简介

    Spring AOP 简介 如果说 IoC 是 Spring 的核心,那么面向切面编程就是 Spring 最为重要的功能之一了,在数据库事务中切面编程被广泛使用. AOP 即 Aspect Orien ...