上文《kratos微服务实战(八)kratos项目之服务注册到nacos》我们实现了把go-kratos编写的微服务注册到nacos中,那么既然是微服务,肯定是需要进行服务之间的调用的。所以本文我们演示下把两个kratos服务都注册到nacos中,然后分别通过http和grpc的方式来进行调用。直接开始。
一、创建项目
上文我们创建了user-center项目,这里我们再创建一个orders-center的服务,直接使用模板进行创建即可
kratos new orders-center -r https://gitee.com/go-kratos/kratos-layout.git
创建完成之后,修改下internal/service/greeter.go文件,修改SayHello方法,把它的返回添加一个orders-center,这样子咱们演示调用Sayello方法,然后通过调用可以区分出来是调用的哪一个服务。如下图:
然后我们再把这个orders-center服务的nacos相关的代码添加上,然后启动看是否成功的注册到nacos了。我这里是已经注册到nacos的,如下图:
二、修改user-center的nacos信息
这里我们要演示的效果是调用user-center的login接口,然后在login的service里面远程调用orders-center的hello word接口。所以这里的话我们需要的主要操作是:
1、通过user-center的nacos client获取到nacos上注册的其他服务。
所以这里我们需要整改下user-center服务的nacos registar。
1、修改internal/data/data.go文件,把nacos相关的registry.Registrar修改为nacos.Registry,修改的地方如下:
2、同样在main下我们也需要修改下这里的register
三、编写服务之间互相调用的代码
1、要通过服务之间互相调用服务的话,可以通过http的方式调用,也可以使用grpc的方式进行调用,所以这里首先需要安装依赖:
go get github.com/go-kratos/kratos/v2/transport/grpc go get github.com/go-kratos/kratos/v2/transport/http
2、实例化nacos的client
这里我们在internal/data/data.go的Data struct里面添加nacos的变量
type Data struct {
db *gorm.DB
rdb *redis.Client
nrg *nacos.Registry
}然后在NewData的时候实例化这里的变量
func NewData(c *conf.Data, logger log.Logger, db *gorm.DB, rdb *redis.Client, nrg *nacos.Registry) (*Data, func(), error) { cleanup := func() { log.NewHelper(logger).Info("closing the data resources") } return &Data{ db: db, rdb: rdb, nrg: nrg, }, cleanup, nil }
3、在biz的repository层添加调用方法
修改internal/biz/account.go文件中添加调用方法,直接在文末添加即可。
func (uc *AccountUseCase) GetUserOrders(ctx context.Context, key string) (res string, err error) { orders, err := uc.acc.GetUserOrders(ctx) fmt.Println("获取到的orders时:", orders) res, err = uc.acc.RedisGetAccount(ctx, key) if err != nil { return "", err } return res, nil }
然后还需要添加Repository的调用接口
type AccountRepo interface {
FindByUsernameAndPassword(ctx context.Context, loginReq *pb.LoginRequest) (acc *Account, err error)
RedisSetAccount(ctx context.Context, key string, value interface{}, expiration time.Duration) (err error)
RedisGetAccount(ctx context.Context, key string) (res string, err error)
GetUserOrders(ctx context.Context) (res string, err error)
}4、repository接口的方法实现实在internal/data/account.go里面实现的,所以修改internal/data/account.go文件,实现这个方法
func (acc accountRepo) GetUserOrders(ctx context.Context) (res string, err error) {
callGrpcRequest(&acc)
callHttpRequest(&acc)
return "测试", nil
}
/*
*
演示使用http调用
*/
func callHttpRequest(acc *accountRepo) {
httpConn, err := http.NewClient(
context.Background(),
http.WithEndpoint("discovery:///orders-center.http"),
http.WithDiscovery(acc.data.nrg),
http.WithTimeout(time.Second*2),
http.WithMiddleware(
recovery.Recovery()),
)
client := helloword.NewGreeterHTTPClient(httpConn)
rsp, err := client.SayHello(context.Background(), &helloword.HelloRequest{
Name: "张三",
})
if err != nil {
panic(err)
}
fmt.Println("通过http调用获取到的信息是结果是:", rsp)
}
/*
*
演示使用grpc调用
*/
func callGrpcRequest(acc *accountRepo) {
grpcConn, err := grpc.DialInsecure(
context.Background(),
grpc.WithEndpoint("discovery:///orders-center.grpc"),
grpc.WithDiscovery(acc.data.nrg),
grpc.WithTimeout(time.Second*2),
grpc.WithMiddleware(
recovery.Recovery()),
)
client := helloword.NewGreeterClient(grpcConn)
rsp, err := client.SayHello(context.Background(), &helloword.HelloRequest{
Name: "张三",
})
if err != nil {
panic(err)
}
fmt.Println("通过GRPC调用获取到的信息是结果是:", rsp)
}上面我们演示使用两种方式来实现服务之间的调用,一个是grpc,一个是http。两者的调用逻辑是:
1、编写通过registry获取nacos对应服务的配置。 2、通过配置分别创建初始化gprc或者http的客户端连接 3、调用proto对应的service。
备注:编写这里代码的时候需要注意以下几点:
1、grpc包的话,需要引入github.com/go-kratos/kratos/v2/transport/grpc,不然的话找不到对应的.DialInsecure方法。 2、需要把上面api的包(就是编译一大堆*.proto,*.pb.go的文件夹)引入进来,因为是通过上面的方法去进行调用的。 3、如果是其他语言的第三方服务,如果第三方的语言编写的服务也是使用grpc,则需要把第三方的proto导入进来放在api层,并且进行编译。 4、如果其他语言编写的第三方服务不是grpc框架,那么可以使用acc.data.nrg.GetService(ctx,"service-name")的方式获取列表,然后使用http的方式进行调用
5、改造login进行调用
接下来在internal/service/account.go文件中修改login方法,增加调用刚才在internal/biz/account.go文件中编写的GetUserOrders方法,示例代码如下:
func (s *AccountService) Login(ctx context.Context, req *pb.LoginRequest) (*pb.LoginResponse, error) {
s.uc.GetUserOrders(ctx, "")
acc, err := s.uc.GetAccountInfoByUsernameAndPassword(ctx, req)
if err != nil || len(acc.Username) == 0 {
return &pb.LoginResponse{Code: 401,
Msg: "用户不存在",
}, nil
}
marshal, err := json.Marshal(acc)
if err != nil {
return &pb.LoginResponse{Code: 401,
Msg: "用户不存在",
}, nil
}
fmt.Println("查询用户是:", string(marshal))
hash := md5.Sum([]byte(uuid.New().String()))
token := hex.EncodeToString(hash[:])
err = s.uc.RedisSetAccountInfo(ctx, "user_"+token, string(marshal), time.Second*300)
if err != nil {
return &pb.LoginResponse{Code: 401,
Msg: "用户不存在",
}, nil
}
return &pb.LoginResponse{Code: 200,
Msg: "请求成功",
Token: token}, nil
}四、自动注入
接下来把user-center的代码重新自动注入下即可
#进入自动注入的文件夹 cd cmd/user-center #自动注入 wire
五、启动user-center项目并且测试
最后就是启动项目并且测试了,启动user-center之后,可以看到user和orders都注册到nacos上了
然后我们使用api post请求user-center的login接口
然后回到user-center的控制台,可以看到http和grpc都已经分别调用到了orders-center服务了。
以上就是kratos微服务注册到nacos之后,服务之间进行互相调用的案例。
备注:
1、这里由于是演示user-center调用orders-center服务,所以在nacos注册这块只是把user-center修改成了nacos.Registry,orders-center没改,实际情况下建议都改,保持统一。
最后按照惯例,附上本案例的源码登录后即可下载。












还没有评论,来说两句吧...