使用Go语言重构Python数据采集功能

Python和Go真是一对难兄难弟

大家好,这篇文章主要是在我做需求的时候的所思所感,很多代码没优化甚至写的相当矬,期望大家勇于提出问题大家一块进步。

剖析需求

我们公司主要做的是某款电商APP,主要数据分为两种一是支撑OLTP的业务数据,二是支撑OLAP的历史数据和日志数据,对于业务数据一般是存在Mysql中,这个无需详细展开,对于历史数据,记录的是某些数据的历史状态变化,从而根据需求发掘出数据本身的价值,对于日志数据,主要记录的是用户的行为数据,这次的需求主要是针对前端埋点日志数据进行采集落地。
一般来说,采集的最普遍的方法就是,APP端产生的埋点日志数据在服务器上沉淀成文件,用ftp或者利用开源工具flume直接采集到kafka或者其他消息队列中等待消费或者直接落地,但现在的需求是APP端不沉淀文件,直接利用服务接口实时发送数据,然后落地到阿里云的odps上。

Python实现数据采集

主要步骤:
1.利用python写一个Http服务,并暴露接口
2.接收JSON数据完成数据格式化
3.利用python中logging模块将格式化的数据转发给阿里云的loghub,odps消费。
代码还是很简单的,直接附上:

# coding=utf-8
import os
import sys
import datetime
import requests
import flask_cors
from flask import request, Flask, jsonify
import logging
import logging.config
import json
sys.path.append(os.path.join( os.path.dirname(__file__), '../'))
#加载配置文件
logging.config.fileConfig('/root/logservice/Logservice/logging.conf', disable_existing_loggers=False)
#拿到sls的自定义日志输出,其中handler转发
logger = logging.getLogger('sls')
#flask框架初始化
app = Flask(__name__)
#实现跨域通信
CORS(app, supports_credentials=True)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
//指定路由,指定methods
@app.route('/api/logservice/info', methods=['post'])
def Log_sevice_info():
    #通过request.form.get获取对应的数据即json_arr字段后面对应的json串
    json_arr = request.form.get('json_arr')
    try:
        #转换成字典类型,以utf-8编码
        jsonArray = json.loads(json_arr, encoding='utf-8')
    except:
        print('**************')
        print(type(json_arr))
    #遍历字典json串,我接收的json的每个k-v结构的k是需要替换的,下面的title_dic就是需要替换的,如果原先的k是1就换成event_name,以此类推。
    for jb in jsonArray:
       title_dic={"event_name":"1","event_time":"2","user_id":"3","adid":"4","trace_id":"5","source":"6","platform":"7",
                     "creat_version":"8","action_version":"9","pagename":"10","seatindex":"11","from_page":"12","to_page":"13",
                     "expand_value":"14"}
        try:
            jb["event_name"] = jb.pop(title_dic['event_name'])
            jb["event_time"] = jb.pop(title_dic['event_time'])
            jb["user_id"] = jb.pop(title_dic['user_id'])
            jb["adid"] = jb.pop(title_dic['adid'])
            jb["trace_id"] = jb.pop(title_dic['trace_id'])
            jb["source"] = jb.pop(title_dic['source'])
            jb["platform"] = jb.pop(title_dic['platform'])
            jb["creat_version"] = jb.pop(title_dic['creat_version'])
            jb["action_version"] = jb.pop(title_dic['action_version'])
            jb["pagename"] = jb.pop(title_dic['pagename'])
            jb["seatindex"] = jb.pop(title_dic['seatindex'])
            jb["from_page"] = jb.pop(title_dic['from_page'])
            jb["to_page"] = jb.pop(title_dic['to_page'])
            jb["expand_value"] = jb.pop(title_dic['expand_value'])
            //转发格式化后的json
            logger.info(jb)
        except:
            pass
    return jsonify({'code':"000000",'data':"",'message':'成功'})
    //ip 和 port
if __name__ == '__main__':
    app.run(host='172.20.10.61', port=4000, debug=False,threaded=True)

后面是贴的日志转发模块的conf,很简单,大家看看就明白了。

[loggers]
keys=root,sls

[handlers]
keys=consoleHandler, slsHandler

[formatters]
keys=simpleFormatter, rawFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler

[logger_sls]
level=INFO
handlers=consoleHandler, slsHandler
qualname=sls
propagate=0



[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)

[handler_slsHandler]
class=aliyun.log.QueuedLogHandler
level=INFO
formatter=rawFormatter
args=(os.environ.get('', ''), os.environ.get('', ''), os.environ.get('', ''), os.environ.get('', ''), "", None, None, None, None, None, None, None, None, True)


[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s


[formatter_rawFormatter]
format=%(message)s

Go语言重构

使用Go语言主要是看中了他的运行效率和他的写服务的速度,但是两天前我Go语言都不知道是啥,真的就是硬写,用完Go语言我才发现python是真好使,Go语言的数据类型转换是真的费劲,不知道是不是我技术不行。。。
还有一个重要的一点就是领导想要完全舍弃阿里云,使用原生的组件自己搭建集群。
主要步骤:
1.利用Go写一个Http服务,并暴露接口
2.接收JSON数据完成数据格式化
3.利用三方包推入kafka
代码还是很简单的,直接附上(go语言这个仅供参考一切还是根据业务出发根据上面的python还是能看出逻辑的,写的我自己都不想看,真的矬。。。):

package main

import (
	"encoding/json"
	//"encoding/json"
	"fmt"
	"github.com/astaxie/beego"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)
type User struct {

	Id string

	Name string

	Pwd string

}
type Animal struct {
	Name  string
	Order string
}
type HanController struct {
beego.Controller
}
type MainController struct {
beego.Controller
}
func (this *MainController) Post() {
	mapss  := map[string]string{"event_name": "1", "event_time": "2", "user_id": "3", "adid": "4", "trace_id": "5", "source": "6",
		"platform": "7",
		"creat_version": "8", "action_version": "9", "pagename": "10", "seatindex": "11", "from_page": "12",
		"to_page": "13",
		"expand_value": "14"}
	jsonmap := make(map[string]string,14)
	newjsonmap :=make(map[string]string,14)
	var zhz string
	var pinjie string
	sumpinjie :=""
	//var messages string
	jsar   :=this.GetString("jsar")
    afteranashuzu:=strings.Split(strings.Split(strings.Split(jsar, "[")[1],"]")[0],"},")
    fmt.Println(len(afteranashuzu))
    for _,v:=range afteranashuzu{fmt.Println(v)}
    for i:=0;i< len(afteranashuzu);i++{
 	  if i !=(len(afteranashuzu)-1) {
		  zhz=afteranashuzu[i]+"}"
		  //fmt.Println(zhz)
		  //json格式的数据变成map
		  err :=json.Unmarshal([]byte(zhz),&jsonmap)
		  if err !=nil{println(err)}
		  //替换jsonmap中的key
		  for k,v :=range jsonmap{
			  for  k2,_ :=range mapss{
				  if k==mapss[k2]{
					  newjsonmap[k2]=v
				  }
			  }
		  }
		  	for j:=0;j< len(afteranashuzu);j++{

				for k,v:=range newjsonmap{
					if j!= len(afteranashuzu)-2 {
						pinjie=k+":"+v
						sumpinjie=sumpinjie+pinjie+","
					}else {
						pinjie=k+":"+v
						sumpinjie=sumpinjie+pinjie+","
					}
				}
				afteranashuzu[j]=strings.TrimRight(sumpinjie,",")
		        sumpinjie=""
			}
	}
	if i== (len(afteranashuzu)-1){
		  //fmt.Println(zhz)
		  //json格式的数据变成map
		  err :=json.Unmarshal([]byte(zhz),&jsonmap)
		  if err !=nil{println(err)}
		  //替换jsonmap中的key
		  for k,v :=range jsonmap{
			  for  k2,_ :=range mapss{
				  if k==mapss[k2]{
					  newjsonmap[k2]=v
				  }
			  }
		  }
		for k,v:=range newjsonmap{

			pinjie=k+":"+v
			sumpinjie=sumpinjie+pinjie+","
		}
		afteranashuzu[len(afteranashuzu)-1]=strings.TrimRight(sumpinjie,",")
	  }
 }

//最终替换的json串存储在数组中,后面要写传入kafka然后flink进行消费
//这块就不粘了。。

}
func main() {

	beego.BConfig.Listen.HTTPAddr="192.167.99.113"
	beego.BConfig.Listen.HTTPPort=8080
	beego.BConfig.CopyRequestBody=true
	beego.BConfig.WebConfig.ViewsPath="views"
	//路由注册,第一个参数就是用户请求的地址,后面的控制器用于把请求分发到不同的控制器
	beego.Router("/api/logservice/exposure", &MainController{})
    beego.Run()
}

上面的主要用的是beego框架,数据格式化的时候我是真没找到三方的包费死个劲了,我的go充其量算个入门吧,大家多多指正!!有大神给我讲讲beego也行啊哈哈哈哈。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值