目录导航:
1. 测试user微服务
2. api层的实现
3. github仓库地址
1.测试user微服务
接上一篇实现了user微服务,并将服务注册到了etcd上。测试为服务业编写一个客户端发现服务并进行rpc调用,新建douyin/test/userRpc.go如下:
package mainimport ("context""douyin/kitex_gen/user""douyin/kitex_gen/user/userservice""douyin/pkg/constants""douyin/pkg/middleware""github.com/cloudwego/kitex/client""github.com/cloudwego/kitex/pkg/retry"etcd "github.com/kitex-contrib/registry-etcd"trace "github.com/kitex-contrib/tracer-opentracing""log""time"
)func main() {r, err := etcd.NewEtcdResolver([]string{constants.EtcdAddress})if err != nil {panic(err)}c, err := userservice.NewClient(constants.UserServiceName,client.WithMiddleware(middleware.CommonMiddleware),client.WithInstanceMW(middleware.ClientMiddleware),client.WithMuxConnection(1), // muxclient.WithRPCTimeout(3*time.Second), // rpc timeoutclient.WithConnectTimeout(50*time.Millisecond), // conn timeoutclient.WithFailureRetry(retry.NewFailurePolicy()), // retryclient.WithSuite(trace.NewDefaultClientSuite()), // tracerclient.WithResolver(r), // resolver)if err != nil {panic(err)}req := &user.DouyinUserRegisterRequest{Username: "111111", Password: "124"}resp, err := c.CreateUser(context.Background(), req)req1 := &user.DouyinUserLoginRequest{Username: "111111", Password: "124"}resp1, err := c.CheckUser(context.Background(), req1)req2 := &user.DouyinUserRequest{UserId: 1, Token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjIyOTg3NjkyMjMsImlhdCI6MTY3NjY4OTIyMywiaXNzIjoiZG91eWluIn0.Yot75U-ZZlXwUfaXEEag6A2Vf-U4LL-wO3RKb07KQlA"} //token是复制的注册后返回的tokenresp2, err := c.QueryCurUser(context.Background(), req2)if err != nil {log.Fatal(err)}log.Println(resp)log.Println(resp1)log.Println(resp2)time.Sleep(time.Second)
}
开启user微服务:终端进入/douyin/cmd/user输入以下指令:
bash ./build.shbash ./output/bootstrap.sh
提示如下即成功开启微服务:
编译运行userRpc.go,输出以下结果就是成功进行了服务发现并且完成user rpc调用:
2.api层的实现
服务发现&rpc调用
新建douyin/cmd/api/rpc文件夹,文件存放初始化rpc调用的init.go文件以及对外提供rpc调用接口的user.go文件代码如下:
package rpcimport ("context""douyin/kitex_gen/user""douyin/kitex_gen/user/userservice""douyin/pkg/constants""douyin/pkg/errno""douyin/pkg/middleware"trace "github.com/kitex-contrib/tracer-opentracing""time""github.com/cloudwego/kitex/client""github.com/cloudwego/kitex/pkg/retry"etcd "github.com/kitex-contrib/registry-etcd"
)var userClient userservice.Clientfunc initUserRpc() {r, err := etcd.NewEtcdResolver([]string{constants.EtcdAddress})if err != nil {panic(err)}c, err := userservice.NewClient(constants.UserServiceName,client.WithMiddleware(middleware.CommonMiddleware),client.WithInstanceMW(middleware.ClientMiddleware),client.WithMuxConnection(1), // muxclient.WithRPCTimeout(3*time.Second), // rpc timeoutclient.WithConnectTimeout(50*time.Millisecond), // conn timeoutclient.WithFailureRetry(retry.NewFailurePolicy()), // retryclient.WithSuite(trace.NewDefaultClientSuite()), // tracerclient.WithResolver(r), // resolver)if err != nil {panic(err)}userClient = c
}// CreateUser create user info
func CreateUser(ctx context.Context, req *user.DouyinUserRegisterRequest) (int64, string, error) {resp, err := userClient.CreateUser(ctx, req)if err != nil {return -1, "", err}if resp.BaseResp.StatusCode != 0 {return -1, "", errno.NewErrNo(resp.BaseResp.StatusCode, resp.BaseResp.StatusMessage)}return resp.UserId, resp.Token, nil
}// CheckUser check user info
func CheckUser(ctx context.Context, req *user.DouyinUserLoginRequest) (int64, string, error) {resp, err := userClient.CheckUser(ctx, req)if err != nil {return -1, "", err}if resp.BaseResp.StatusCode != 0 {return -1, "", errno.NewErrNo(resp.BaseResp.StatusCode, resp.BaseResp.StatusMessage)}return resp.UserId, resp.Token, nil
}// UserInfo user info format
type UserInfo struct {ID int64 `json:"id"`Name string `json:"name"`
}// QuryUser check user info
func QueryUser(ctx context.Context, req *user.DouyinUserRequest) (*UserInfo, error) {resp, err := userClient.QueryCurUser(ctx, req)if err != nil {return nil, err}if resp.BaseResp.StatusCode != 0 {return nil, errno.NewErrNo(resp.BaseResp.StatusCode, resp.BaseResp.StatusMessage)}var userInfo UserInfouserInfo.ID = resp.User.IduserInfo.Name = resp.User.Namereturn &userInfo, nil
}
gin接收参数返回结果
新建douyin/cmd/api/handles文件夹,文件存放接收参数完成rpc调用返回结果的对应功能文件,user服务包括登录login.go,注册register.go,查询用户信息get_cur_user.go,这里举例register.go,其余代码详见文章末尾github仓库。
package handlersimport ("context""douyin/cmd/api/rpc""douyin/kitex_gen/user""douyin/pkg/errno""github.com/gin-gonic/gin""log"
)func Register(c *gin.Context) {var registerVar UserParamif err := c.BindQuery(®isterVar); err != nil {SendUserResponse(c, errno.ConvertErr(err), -1, "")return}log.Print(registerVar)if len(registerVar.Username) == 0 || len(registerVar.Password) == 0 {SendUserResponse(c, errno.ParamErr, -1, "")return}userID, token, err := rpc.CreateUser(context.Background(), &user.DouyinUserRegisterRequest{Username: registerVar.Username,Password: registerVar.Password,})if err != nil {SendUserResponse(c, errno.ConvertErr(err), -1, "")return}SendUserResponse(c, errno.Success, userID, token)
}
配置路由&开启api服务
douyin/cmd/api下编写main.go,在main.go中配置路由并且开启服务器如下:
package mainimport ("douyin/cmd/api/handles""douyin/cmd/api/middleware""douyin/cmd/api/rpc""douyin/pkg/tracer""net/http""github.com/cloudwego/kitex/pkg/klog""github.com/gin-gonic/gin"
)func Init() {// TODOtracer.InitJaeger("api")rpc.InitRPC()
}func main() {Init()r := gin.Default()r.Use(middleware.OpenTracing())r.Static("/static", "./public")douyin := r.Group("/douyin")userGroup := douyin.Group("/user")userGroup.POST("/login/", handlers.Login)userGroup.POST("/register/", handlers.Register)userGroup.GET("/", middleware.AuthMiddleware(), handlers.QueryCurUser)if err := http.ListenAndServe("0.0.0.0:8080", r); err != nil {klog.Fatal(err)}
}
app连接服务端测试
运行douyin/api下的脚本build.shbash ./build.sh
就能开启服务等待客户端抖声app的连接啦:
在app中进行注册用户,注册成功,终端返回如下消息:
这样就完成了用户登录、注册和返回用户信息,如果后续选择社交方向将继续增加用户信息中关注数量和列表等。
3.github仓库地址
https://github.com/LaiYuShuang/douyin/tree/main