在我们的系列文章“在微服务上写博客”的第二部分中,我们描述
了API Gateway 。
在这里,我们描述了用户微服务的实现。
我们的微服务应该能够:
- 记录服务调用和指示TraceId的中间状态(由api-gw发出的相同状态,请参见第2部分“ API网关” )
- 实现登录(SignIN)和注册(SignUp)功能
- 实现CRUD功能(在数据库中创建,读取,编辑,删除记录)。 使用MongoDB作为数据库。
首先,我们在原始文件(./services/user/protobuf/user.proto)中描述我们的服务。
指定使用的语法-proto3。 我们指定了protobuf软件包的名称,在该软件包中,将实现服务器和客户端部件的自动生成的代码。
我们导入了注释库google / api / annotations.proto,将需要用它来描述用于生成REST API的指令。
syntax = "proto3"; package protobuf; import "google/api/annotations.proto";
用户服务的描述,直接是它应具有的接口(方法)。 例如,SignUp接口(注册):它接收包含Username,Password,FirstName和LastName属性的SignUpRequest消息,并用包含Slug(UserID),Username,Role属性的SignUpResponse消息作为响应。 同样,在接口说明的“选项”部分中,指定post指令:“ / api / v1 / user / signup。基于此,代码生成器将创建一个REST接口,该接口将在http:{{api_gw_host}} / api / v1 / user处接收POST请求。 /注册。
它将在请求正文中包含以下结构:
{ Username: 'username_value', Password: 'password_value', FirstName: 'firstname_value', LastName: 'lastname_value', }
因此,如果成功,它将给出以下结构:
{ Slug: 'user_id_value', Username: 'username_value', Role: 'role_value', }
还是一个错误。 在稍后描述实现原型文件中描述的接口的函数的部分中,我们将在稍后再告诉您更多有关错误的信息。
其他接口(登录,创建,更新,删除,获取,查找)的声明方式相同。
现在我们有了一个现成的原型文件。 我们转到项目的根目录,并执行sh ./bin/protogen.sh命令。 该脚本将生成主要代码。
接下来,转到./services/user目录,并在functions.go文件中编写声明的接口的实现。
首先,我们实现中间件。 在对服务的每个请求中,我们从请求上下文中提取TraceId,UserId,UserRole参数,并将它们写入日志文件。 您可以在此处实施请求授权。
在SignUp方法中,我们确定响应结构。
接下来,检查请求参数。
如果一切正常,请填写用户结构,写入数据库并返回答案。
user:=&User{ Username:in.Username, FirstName:in.FirstName, LastName:in.LastName, Password:getMD5(in.Password), } var slug string collection:= o.DbClient.Database("blog").Collection("users") insertResult, err := collection.InsertOne(context.TODO(), user) if err != nil { return out,err } if oid, ok := insertResult.InsertedID.(primitive.ObjectID); ok { slug=fmt.Sprintf("%s",oid.Hex()) }else { err:=app.ErrInsert return out,err } out.Slug=slug out.Username=in.Username out.Role=app.ROLE_USER return out,nil
另外,我们注意错误返回,例如:
err:=app.ErrInsert
由于最终该错误将返回到我们的api-wg(在其REST部分),因此将其转换为标准HTTP响应代码很酷。 为了不编写其他代码,您不应使用标准的go错误,而应使用google.golang.org/grpc/status包中的status.error。
文件/ Services / user / app / errors.go中描述了User微服务的所有典型错误以及如何将它们转换为HTTP响应代码。
package app import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" )
关于用户微服务,我想讲的最后一件事是它如何启动并连接到数据库。 这些操作在文件./services/user/main.go中执行。
服务启动:
lis,err:= net.Listen("tcp", fmt.Sprintf(":%s", Port)) if err != nil { log.Fatalf("failed to listen: %v", err) } grpcServer:= grpc.NewServer( grpc.UnaryInterceptor(protobuf.AccessLogInterceptor), ) s:=&protobuf.Server{} …
连接到数据库(main.go):
DbConnect功能的实现(./services/user/functions.go):