英文:
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是改善吞吐性能的明显第一步。
- 将每个新的IP推送到ipChannel进行处理
- 在'lookup' goroutine中从ipChannel读取,进行查找并处理结果
- 使用错误通道处理出现的问题
根据需要使用尽可能多的'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.
- push each new ip to process to a ipChannel
- read from ipChannel in 'lookup' goroutine do lookup and process result
- use error channel for things that go wrong
have as many 'lookup' channels as you need.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论