一、目標
在2021-10-17 dubbogo 基礎使用中,介紹了如何用go
寫一個部署到zookeeper
的dubbo
服務,這次編寫一個go
語言的dubbo
調用端。并且支持同時連接到多個zookeeper
,根據需要調用不同zk
上的同一個服務
開動
1、部署zk
docker run --name zk1 --restart always -d -p 2181:2181 zookeeper
docker run --name zk2 --restart always -d -p 2182:2181 zookeeper
這里我們部署兩個zookeeper
,端口號分別是2181
和2182
2、運行服務
- 進入
cmd/server
目錄,修改dubbo.yml
中的zk
端口為2181
,然后go run main.go
啟動服務1
- 進入
cmd/server
目錄,修改dubbo.yml
中的zk
端口為2182
,然后go run main.go
啟動服務2
3、客戶端配置
-
dubbo.registries
配置兩個
registries:
zk1:
protocol: zookeeper
timeout: 3s
address: 192.168.96.129:2181
zk2:
protocol: zookeeper
timeout: 3s
address: 192.168.96.129:2182
-
dubbo.consumer
按照如下配置
consumer:
request-timeout: 10s
check: false
references:
UserServiceEnv1:
retries: 0
registry-ids:
- zk1
protocol: dubbo
interface: com.demo.exp.service.UserService
UserServiceEnv2:
retries: 0
registry-ids:
- zk2
protocol: dubbo
interface: com.demo.exp.service.UserService
這里我們配置了兩個UserService
的引用,并且設置了不同的別名。指定了每個引用連接各自的zk
.
4、客戶端初始化
- 這里我們分別為要連接的不同
zk
定義結構體和對象,與【3】小節中配置文件定義的引用別名一致
var(
UsZk1 = &UserServiceEnv1{}
UsZk2 = &UserServiceEnv2{}
)
func InitUserServiceClient(){
dto.RegisterDtos(func(pojos ...dto.POJO){
for _,p := range pojos{
hessian.RegisterPOJO(p)
}
})
config.SetConsumerService(UsZk1)
config.SetConsumerService(UsZk2)
}
type UserServiceEnv1 struct {
service.UserService
}
type UserServiceEnv2 struct {
service.UserService
}
func(a *UserServiceEnv1)Reference()string{
return "UserServiceEnv1"
}
func(a *UserServiceEnv2)Reference()string{
return "UserServiceEnv2"
}
注意,這里service.UserService
為服務提供方的接口,我們直接繼承他
- 服務提供方的
dto
定義
type POJO interface {
JavaClassName() string
}
type WithDto func(...POJO)
func RegisterDtos(registerFunc WithDto){
registerFunc(
&UserRequest{},
&UserResponse{},
)
}
const JavaDtoPgkName = "com.demo.exp.dto."
type UserRequest struct {
UserName string // 用戶名
UserId string // 用戶id
}
func(req UserRequest) JavaClassName() string{
return JavaDtoPgkName + "QueryUserParam"
}
type UserResponse struct {
UserName string // 用戶名
UserId string // 用戶id
BirthDate string // 出生日期
Age int64 // 年齡
IsDead bool // 是否已去世
}
func(req UserResponse) JavaClassName() string{
return JavaDtoPgkName + "QueryUserResponse"
}
- 服務提供方的
service
定義
//
// UserService
// @Description: 服務接口定義
//
type UserService struct {
QueryUser func(ctx context.Context, in *dto.UserRequest)(*dto.UserResponse, error)
}
func(a *UserService) Reference()string{
return "com.demo.exp.service.UserService"
}
5、調用代碼
main.go
func main(){
clients.InitUserServiceClient()
err := config.Load(config.WithPath("./conf/dubbo.yml"))
if err != nil{
panic(err)
}
req := &dto.UserRequest{
UserName: "你好",
UserId: "123",
}
ctx, traceId := util.GetDubboContextWithAppName("dubbo-consumer")
//time.Sleep(10 * time.Second)
rsp, err := clients.UsZk1.QueryUser(ctx, req)
if err != nil{
logrus.WithFields(logrus.Fields{
"traceId": traceId,
"rsp": rsp,
"err": err,
}).Error("query zk1 userservice response")
}else{
logrus.WithFields(logrus.Fields{
"traceId": traceId,
"rsp": rsp,
}).Info("query zk1 userservice response")
}
req.UserId = "123456789"
ctx, traceId = util.GetDubboContextWithAppName("dubbo-consumer")
rsp, err = clients.UsZk2.QueryUser(ctx, req)
if err != nil{
logrus.WithFields(logrus.Fields{
"traceId": traceId,
"rsp": rsp,
"err": err,
}).Error("query zk2 userservice response")
}else{
logrus.WithFields(logrus.Fields{
"traceId": traceId,
"rsp": rsp,
}).Info("query zk2 userservice response")
}
select {
}
}
- 運行客戶端
日志如下:
time="2022-04-03T17:20:01+08:00" level=error msg="query zk1 userservice response" err="no user found with id[123]" rsp="&{ 0 false}" traceId=e166fc1a
time="2022-04-03T17:20:01+08:00" level=info msg="query zk2 userservice response" rsp="&{dubbo-user1 123456789 1967-01-22 17:20:01 56 true}" traceId=998b5c6b
服務1
的日志如下:
time="2022-04-03T17:20:01+08:00" level=info msg="user_service:queryuser received call" appName=dubbo-consumer req="&{你好 123}" traceId=e166fc1a
服務2
的日志如下:
time="2022-04-03T17:20:01+08:00" level=info msg="user_service:queryuser received call" appName=dubbo-consumer req="&{你好 123456789}" traceId=998b5c6b