上文《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没改,实际情况下建议都改,保持统一。
最后按照惯例,附上本案例的源码登录后即可下载。
还没有评论,来说两句吧...