不会飞的章鱼

熟能生巧,勤能补拙;念念不忘,必有回响。

场景题_从A服务获取用户id,从B服务获取用户信息

题目描述

有这样一个场景,需要你从A服务中获取多个用户id,然后根据用户id请求B服务获取用户信息,如何用Golangchannel和协程来实现?

问题思考和实现

方法一

由于从A服务中获取的是一个数组形式的用户id,所以我可以考虑从A服务获取用户id后,再用for range循环遍历每一个用户id,给每个用户建立一个通道,开个协程请求B服务获取用户信息,再通过通道传回来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
type UserInfo struct {

}

var userinfo UserInfo

//1,请求A服务获取用户id
userids := GetAserver()

//2,请求B服务获取用户信息
for _,userid := range userids {
userid_chan := make(chan userinfo)
go GetBserver(userid_chan,userid)
go func(){
select {
case info := <- userid_chan:
return info
}
}()
}

存在的问题

  • 每个用户新建一个channel,很浪费
  • 数据量大了,这样做很不好

方法二(待完善)

建立2个channel和2个协程 一个协程用来获取用户id数组g1,一个协程服务负责请求B服务获取用户信息g2, g1通过channel给g2,然后g2将请求到的用户信息再通过channel反馈回去。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
type UserInfo struct {

}

var userinfo UserInfo

go g1()
go g2()

ch1 := make(chan string)
ch2 := make(chan userinfo)

//g1通过`channel`给g2
func g1(){

}

func g2(){

}

方法三(待完善)

核心思路是,A服务的携程不能阻塞,尽量并发等待B的数据。
A要新建一个go用来接收B发过来的数据,A的ID可以直接用chan发送到B,B用一个单独的chan一次一个的方式发送结构体到新建的go,新建的go可以打包发给A,或者直接转发给A,所有数据接收完成后,新建的go退出;
ID可以一次批量发送,结构体可以用chan,一次一个的处理,也可以打包批次处理,这个可以看需求。

1
2
3
4
5
type UserInfo struct {

}

var userinfo UserInfo

问题复盘

  • 这个问题的核心是:你如何才能并发处理异步请求,特别是大当量数据的情况。
  • 并发考虑做个消息队列。

特别感谢

特别感谢Go项目实战群里的三位大佬提供的思路:@star,@J,@钢之镇魂曲

------ 本文结束------
如果本篇文章对你有帮助,可以给作者加个鸡腿~(*^__^*),感谢鼓励与支持!