golang the efficient way/lib to get a key from json string,and use this key to do geoip,then add geoip info to json

huangapple go评论83阅读模式
英文:

golang the efficient way/lib to get a key from json string,and use this key to do geoip,then add geoip info to json

问题

我明白你的问题。你想用Go语言解析JSON格式的消息,并获取xrealip,然后使用xrealip进行地理位置查询,并将地理位置信息添加到该消息中。你目前的方法效率较低,你希望找到更好的方法以提高处理速度。

以下是一个可能的改进方案:

首先,你可以定义一个结构体来表示JSON消息的结构,然后使用json.Unmarshal函数将JSON字符串解析为该结构体的实例。这样可以更方便地访问和修改消息的各个字段。

type Message struct {
    Type       string `json:"type"`
    XRealIP    string `json:"xrealip"`
    Scheme     string `json:"scheme"`
    LogTime    string `json:"log_time"`
    HttpMethod string `json:"http_method"`
    Hostname   string `json:"hostname"`
    URL        string `json:"url"`
    HTTPCode   string `json:"http_code"`
    SendByte   int    `json:"send_byte"`
    UserAgent  string `json:"user_agent"`
    Timestamp  string `json:"@timestamp"`
    ProcessTime int    `json:"process_time"`
    CacheStatus string `json:"cache_status"`
    Refer      string `json:"refer"`
}

// 解析JSON消息并返回Message实例
func parseMessage(msg string) (*Message, error) {
    var m Message
    err := json.Unmarshal([]byte(msg), &m)
    if err != nil {
        return nil, err
    }
    return &m, nil
}

接下来,你可以使用你的地理位置查询方法(例如ip17mon.Find)来获取IP地址的地理位置信息,并将其添加到消息中。

// 获取IP地址的地理位置信息
func getGeoInfo(ip string) (map[string]string, error) {
    loc, err := ip17mon.Find(ip)
    if err != nil {
        return nil, err
    }
    iplocation := map[string]string{"country": loc.Country, "region": loc.Region, "isp": loc.Isp}
    return iplocation, nil
}

最后,你可以修改geoInfoAdd函数,使用上述方法解析消息、获取地理位置信息并将其添加到消息中。

// 解析JSON消息,添加地理位置信息并返回新的消息
func geoInfoAdd(msg string) ([]byte, error) {
    m, err := parseMessage(msg)
    if err != nil {
        return nil, err
    }

    iplocation, err := getGeoInfo(m.XRealIP)
    if err != nil {
        return nil, err
    }

    m.IPLocation = iplocation

    newmsg, err := json.Marshal(m)
    if err != nil {
        return nil, err
    }

    return newmsg, nil
}

这样,你可以通过调用geoInfoAdd函数来解析消息、获取地理位置信息并将其添加到消息中。希望这个改进方案能够提高你的处理速度。如果你有任何其他问题,请随时问我。

英文:

just as title,I want to use golang to do geoip,the msg is json format like below

> {"type":"big_platform","xrealip":"8.8.8.8","scheme":"http","log_time":"24/Feb/2017:15:36:10 +0800","http_method":"GET","hostname":"XXX.com","url":"/v126330.apk","http_code":"206","send_byte":20972063,"user_agent":"63(android;KOOMII-K8;6.0;480x854;WIFI;1118.24)","@timestamp":"2017-02-24T15:36:10+08:00","process_time":59463,"cache_status":"TCP_HIT","refer":"-"}

I want use Go to parse this message and get xrealip,use xrealip to do geoip.then apped geoip info to this msg.

now I do it like blew

//parse json string ,add geoip info and return new msg
func geoInfoAdd(msg string) ([]byte, error) {
        data := make(map[string]interface{})
        err := json.Unmarshal([]byte(msg), &data)
        if err != nil {
                return nil, err
        }
        //type assert value
        var ok bool
        if ipValue, ok = data[ipKey].(string); !ok {
                // ask_price is not a string
                return nil, errors.New("ipvalue not string")
        }

        //get ip location
        loc, err := ip17mon.Find(ipValue)
        if err != nil {
                return nil, err
        }
        iplocation := map[string]string{"country": loc.Country, "region": loc.Region, "isp": loc.Isp}

        //newdata := data
        data["iplocation"] = iplocation
        newmsg, err := json.Marshal(data)
        if err != nil {
                return nil, err
        }

        return newmsg, nil
}

but thats realy slow,cost lots of cpu,i need to do this action like 70000/second. and i really need better way to do this.

thanks

答案1

得分: 1

如果你真的只需要从这个JSON中获取xrealip,那就手动完成你需要的工作。这可能会更快(你需要进行基准测试),正如Adam在下面所说,你在网络上花费的时间可能比解析这个JSON的时间更重要。

// 寻找关键字
key := xrealip":"
i := strings.Index(data,key) + len(key)
if i == -1 {
return errors.New("no ip")
}

// 提取IP地址(最大长度为15,适用于IPv4)
ip := data[i:i+15]

// 仅保留IP地址部分
q := strings.Index(ip,")
if q > -1 {
ip = ip[:q]
}

你的函数应该使用字节而不是字符串,并通过扫描而不是查找"来进行处理,但上述代码是基于你的函数的。

还有其他的JSON包(https://github.com/pquerna/ffjson),但主要问题是在你只想要一个键时处理所有这些数据。

英文:

If you truly need just the xrealip from this json, just do the work you need by hand. This is probably a lot faster (you'd need to benchmark), as Adam said below your time on the network might be more significant than time spent parsing this json:

// Find the key
key := `xrealip":"`
i := strings.Index(data,key) + len(key)
if i == -1 {
  return errors.New("no ip")
}
  
// Extract ip up to max ip len (IPV4)
ip := data[i:i+15]

// Cut to just ip 
q := strings.Index(ip,`"`)
if q > -1 {
  ip = ip[:q]
}

Your functions should probably work with bytes, not strings, and scan through rather than cutting by finding " but the above is based on your function.

There are other json packages (https://github.com/pquerna/ffjson), but the main problem is processing all this data when you only want one key.

答案2

得分: 0

你是否已经测量了JSON序列化以显示它是问题所在?
可能的替代方案有:

  • 编写一个直接的字符串解析器
  • 使用自定义结构体和json:"arg_name"

然而,我预计你大部分时间都会在这里:

loc, err := ip17mon.Find(ipValue)

考虑到你正在使用Go语言,对于我来说,使用goroutines和channels是改善吞吐性能的明显第一步。

  1. 将每个新的IP推送到ipChannel进行处理
  2. 在'lookup' goroutine中从ipChannel读取,进行查找并处理结果
  3. 使用错误通道处理出现的问题

根据需要使用尽可能多的'lookup'通道。

英文:

Have you measured the json serialization to show it's the problem?
Alternatives could be;

  • write a straight string parser
  • use custom struct with json:"arg_name"

However I'd expect most of you time to be here;

loc, err := ip17mon.Find(ipValue)

Given you are using go, goroutines and channels would be an obvious first step to improve throughput performance for me.

  1. push each new ip to process to a ipChannel
  2. read from ipChannel in 'lookup' goroutine do lookup and process result
  3. use error channel for things that go wrong

have as many 'lookup' channels as you need.

huangapple
  • 本文由 发表于 2017年2月24日 15:44:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/42433227.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定