为Java开发人员启动Beats

上周,我写了一篇关于如何从Java开发人员的背景开始开发Logstash插件的文章 。 但是,通过收购Packetbeat,Logstash现在可以从Beats获得帮助,将数据推送到Elasticsearch。 Beats是用Go开发的,这对传统Java开发人员来说是另一个挑战。 本周,我尝试将Logstash Reddit插件移植到专用的Beat。 这篇文章记录了我的发现(破坏者:我发现它比使用Ruby容易得多)。

搭建环境

在OSX上,安装go可执行文件很容易:

brew install go

尽管Java或Ruby(或我所知道的任何一种语言)可以驻留在本地文件系统上的任何位置,但是Go项目必须全部位于一个单独的专用位置,该位置在$GOPATH环境变量下可用。

创建项目

至于Logstash插件,可以从模板创建Beats项目。 做到这一点的文档非常简单。 鉴于Go对文件系统位置的严格要求,只需按照说明进行操作即可生成一个新的即用型Go项目。

默认模板代码将在控制台中重复发送带有递增计数器的事件:

 ./redditbeat -e -d "*"
2016/12/13 22:55:56.013362 beat.go:267: INFO
  Home path: [/Users/i303869/projects/private/go/src/github.com/ajavageek/redditbeat]
  Config path: [/Users/i303869/projects/private/go/src/github.com/ajavageek/redditbeat]
  Data path: [/Users/i303869/projects/private/go/src/github.com/ajavageek/redditbeat/data]
  Logs path: [/Users/i303869/projects/private/go/src/github.com/ajavageek/redditbeat/logs]
2016/12/13 22:55:56.013390 beat.go:177: INFO Setup Beat: redditbeat; Version: 6.0.0-alpha1
2016/12/13 22:55:56.013402 processor.go:43: DBG  Processors:
2016/12/13 22:55:56.013413 beat.go:183: DBG  Initializing output plugins
2016/12/13 22:55:56.013417 logp.go:219: INFO Metrics logging every 30s
2016/12/13 22:55:56.013518 output.go:167: INFO Loading template enabled.
Reading template file:
  /Users/i303869/projects/private/go/src/github.com/ajavageek/redditbeat/redditbeat.template.json
2016/12/13 22:55:56.013888 output.go:178: INFO Loading template enabled for Elasticsearch 2.x.
Reading template file:
  /Users/i303869/projects/private/go/src/github.com/ajavageek/redditbeat/redditbeat.template-es2x.json
2016/12/13 22:55:56.014229 client.go:120: INFO Elasticsearch url: http://localhost:9200
2016/12/13 22:55:56.014272 outputs.go:106: INFO Activated elasticsearch as output plugin.
2016/12/13 22:55:56.014279 publish.go:234: DBG  Create output worker
2016/12/13 22:55:56.014312 publish.go:276: DBG  No output is defined to store the topology.
  The server fields might not be filled.
2016/12/13 22:55:56.014326 publish.go:291: INFO Publisher name: LSNM33795267A
2016/12/13 22:55:56.014386 async.go:63: INFO Flush Interval set to: 1s
2016/12/13 22:55:56.014391 async.go:64: INFO Max Bulk Size set to: 50
2016/12/13 22:55:56.014395 async.go:72: DBG  create bulk processing worker (interval=1s, bulk size=50)
2016/12/13 22:55:56.014449 beat.go:207: INFO redditbeat start running.
2016/12/13 22:55:56.014459 redditbeat.go:38: INFO redditbeat is running! Hit CTRL-C to stop it.
2016/12/13 22:55:57.370781 client.go:184: DBG  Publish: {
  "@timestamp": "2016-12-13T22:54:47.252Z",
  "beat": {
    "hostname": "LSNM33795267A",
    "name": "LSNM33795267A",
    "version": "6.0.0-alpha1"
  },
  "counter": 1,
  "type": "redditbeat"
}

关于命令行参数: -e记录到标准err,而-d "*"启用所有调试选择器。 有关参数的完整列表,请键入./redditbeat --help

编码

Go代码位于.go的文件(一个惊喜......)中的项目子文件夹$GOPATH/src文件夹中。

配置类型

第一个有趣的文件是config/config.go ,它定义了一个struct来声明Beat的可能参数。 对于以前的Logstash插件,让我们添加一个subreddit参数,并将其设置为默认值:

typeConfigstruct{
    Periodtime.Duration`config:"period"`
    Subredditstring`config:"subreddit"`
}

varDefaultConfig=Config{
    Period:15*time.Second,
    Subreddit:"elastic",
}

打浆机类型

Beat本身的代码可在beater/redditbean.go找到。 默认模板为Beat和三个函数创建一个struct

  1. Beat构造函数-它读取配置:
    funcNew(b*beat.Beat,cfg*common.Config)(beat.Beater,error){...}
  2. Run功能-应该循环播放Beat的主要功能:
    func(bt*Redditbeat)Run(b*beat.Beat)error{...}
  3. Stop功能可正常关闭:
    func(bt*Redditbeat)Stop(){...}
Go中没有明确的接口实现。 仅从接口实现所有方法都会创建一个隐式继承关系。 出于文档目的,这是Beater接口:键入Beater接口{Run(b * Beat)error Stop()}

因此,由于Beat结构同时实现RunStop ,因此它 Beater

Go中没有类的概念,因此无法在具体类型上声明方法。 但是,它存在扩展功能的概念:可以向类型(在单个程序包内)添加行为的功能。 它需要声明接收者类型:这是在fun关键字和函数名称之间完成的-在这里,它是Redditbeat类型(或更正确的是,指向Redditbeat类型的指针,但是存在隐式转换)。

构造函数和Stop函数可以保持不变,无论要开发什么功能,都必须在Run函数中。 在这种情况下,功能是调用Reddit REST API并为每个Reddit帖子发送一条消息。

最终代码如下所示:

func(bt*Redditbeat)Run(b*beat.Beat)error{
    bt.client=b.Publisher.Connect()
    ticker:=time.NewTicker(bt.config.Period)
    reddit:="https://www.reddit.com/r/"+bt.config.Subreddit+"/.json" (1)
    client:=&http.Client{} (2)
    for{
        select{
        case<-bt.done:
            returnnil
        case<-ticker.C:
        }
        req,reqErr:=http.NewRequest("GET",reddit,nil) (3)
        req.Header.Add("User-Agent","Some existing header to bypass 429 HTTP") (4)
        if(reqErr!=nil){ (5)
            panic(reqErr) (6)
        }
        resp,getErr:=client.Do(req) (7)
        if(getErr!=nil){
            panic(getErr)
        }
        body,readErr:=ioutil.ReadAll(resp.Body) (8)
        deferresp.Body.Close() (9)
        if(readErr!=nil){
            panic(readErr)
        }
        trimmedBody:=body[len(prefix):len(body)-len(suffix)] (10)
        messages:=strings.Split(string(trimmedBody),separator) (11)
        fori:=0;i<len(messages);i++{
            event:=common.MapStr{ (12)
                "@timestamp":common.Time(time.Now()),
                "type":b.Name,
                "message":"{"+messages[i]+"}",
            }
            bt.client.PublishEvent(event) (13)
        }
    }
}

这是最重要的部分的说明:

  1. 通过串联字符串(包括配置Subreddit参数)创建Reddit REST URL。 请记住,其默认值已在config.go文件中定义。
  2. 获取有关新的HTTP客户端类型的参考
  3. 创建一个新的HTTP请求。 请注意,Go允许多个返回值。
  4. 如果未设置标准请求标头,则Reddit的API将返回429状态代码
  5. 执行标准错误不会通过异常处理,而是会与常规返回值一起返回。 根据Golang Wiki:
    向调用者指示错误条件应通过返回错误值来完成
  6. panic()函数类似于在Java中引发异常,爬升堆栈直到处理完毕。 有关更多信息,请参阅相关文档
  7. 执行HTTP请求
  8. 将响应主体读入字节数组
  9. 关闭体液。 注意defer关键字:
    defer语句将函数的执行推迟到周围的函数返回之前。
  10. 创建一个切片 -对整个响应正文字节数组的一部分数组的引用。 本质上,它删除前缀和后缀以保留相关的JSON值。 将字节数组解析为JSON可能会过大。
  11. 分割切片以分别获取每个JSON片段
  12. 将消息创建为简单的字典结构
  13. 发送

配置,构建和启动

可以在项目根目录的redditbeat.yml文件中找到默认配置参数。 请注意, redditbeat.full.yml中列出了其他常见的Beat参数以及相关注释。

Beats的有趣之处在于,它们的消息可以直接发送到Elasticsearch或Logstash进行进一步处理。 这是在上述配置文件中配置的。

redditbeat:
  period:10s
output.elasticsearch:
  hosts:["localhost:9200"]
output.logstash:
  hosts:["localhost:5044"]
  enabled:true

此配置代码段将每隔10秒钟遍历Run方法,并将消息发送到在端口5044上的本地主机上运行的Logstash实例。运行Beat时,可​​以覆盖此实例(请参见下文)。

为了使Logstash接受来自Beats的消息,必须安装Logstash Beat插件,并且必须为Beats配置Logstash输入:
input {
  beats {
    port => 5044
  }
}

要构建项目,请在项目的根目录下键入make 。 它将创建一个可以运行的可执行文件。

./redditbeat -e -E redditbeat.subreddit=java

-E标志可能会覆盖在嵌入式redditbeat.yml配置文件中找到的参数(请参见上文)。 在这里,它会将要读取的子reddit设置为“ java”,而不是默认的“ elastic”。

输出如下所示:

2016/12/17 14:51:19.748329 client.go:184: DBG  Publish: {
  "@timestamp": "2016-12-17T14:51:19.748Z",
  "beat": {
    "hostname": "LSNM33795267A",
    "name": "LSNM33795267A",
    "version": "6.0.0-alpha1"
  },
  "message": "{
    \"kind\": \"t3\", \"data\": {
      \"contest_mode\": false, \"banned_by\": null,
      \"domain\": \"blogs.oracle.com\", \"subreddit\": \"java\", \"selftext_html\": null,
      \"selftext\": \"\", \"likes\": null, \"suggested_sort\": null, \"user_reports\": [],
      \"secure_media\": null, \"saved\": false, \"id\": \"5ipzgq\", \"gilded\": 0,
      \"secure_media_embed\": {}, \"clicked\": false, \"report_reasons\": null,
      \"author\": \"pushthestack\", \"media\": null, \"name\": \"t3_5ipzgq\", \"score\": 11,
      \"approved_by\": null, \"over_18\": false, \"removal_reason\": null, \"hidden\": false,
      \"thumbnail\": \"\", \"subreddit_id\": \"t5_2qhd7\", \"edited\": false,
      \"link_flair_css_class\": null, \"author_flair_css_class\": null, \"downs\": 0,
      \"mod_reports\": [], \"archived\": false, \"media_embed\": {}, \"is_self\": false,
      \"hide_score\": false, \"spoiler\": false,
      \"permalink\": \"/r/java/comments/5ipzgq/jdk_9_will_no_longer_bundle_javadb/\",
      \"locked\": false, \"stickied\": false, \"created\": 1481943248.0,
      \"url\": \"https://blogs.oracle.com/java-platform-group/entry/deferring_to_derby_in_jdk\",
      \"author_flair_text\": null, \"quarantine\": false,
      \"title\": \"JDK 9 will no longer bundle JavaDB\", \"created_utc\": 1481914448.0,
      \"link_flair_text\": null, \"distinguished\": null, \"num_comments\": 4,
      \"visited\": false, \"num_reports\": null, \"ups\": 11
    }
  }",
  "type": "redditbeat"
}

结论

奇怪的是,我发现开发Beat比使用Logstash插件容易。 Go的层次较低,有些概念确实很陌生(例如隐式接口实现),但是生态系统要简单得多-因为语言是最新的。 此外,Beats更具通用性,因为它们可以发送到Elasticsearch和/或Logstash。

这篇文章的完整源代码可以在Github上找到。

翻译自: https://blog.frankel.ch/starting-beats-development-for-java-developers/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值