go微服务系列之一

wiatingpub · · 3013 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

如何编写一个微服务?这里用的是go的微服务框架go micro,具体的情况可以查阅:http://btfak.com/%E5%BE%AE%E6%9C%8D%E5%8A%A1/2016/03/28/go-micro/ 这里给出的是开发一个微服务的步骤(如果想直接查阅源码或者通过demo学习的,可以访问[ricoder_demo](https://gitee.com/xi_fan/ricoder_demo)。): 1、书写proto文件,定义函数等 具体实现: ```protobuf syntax = "proto3"; package pb; service UserService { //增 rpc InsertUser (InsertUserReq) returns (InsertUserRep){} //删 rpc DeletetUser (DeletetUserReq) returns (DeletetUserRep){} //查 rpc SelectUser(SelectUserReq)returns (SelectUserRep){} //改 rpc ModifyUser(ModifyUserReq)returns (ModifyUserRep){} } message User{ int32 id = 1 ; string name = 2; string Address = 3; string Phone = 4; } message ModifyUserReq { int32 id = 1 ; string name = 2; string Address = 3; string Phone = 4; } message ModifyUserRep { } message SelectUserReq { int32 id = 1 ; } message SelectUserRep { User users = 1; } message DeletetUserReq { int32 id = 1 ; } message DeletetUserRep { } message InsertUserReq { int32 id = 1 ; string name = 2; string Address = 3; string Phone = 4; } message InsertUserRep { int32 id = 1 ; string name = 2; string Address = 3; string Phone = 4; } ``` 2、采用代码生成工具生成user.pb.go文件,生成协议 具体可以查看 https://github.com/micro/go-micro ,这里我自己写了个脚本文件 build_proto.sh ,自动将指定文件夹下的proto文件生成相应的协议,具体代码如下: ```bash #!/usr/bin/env bash protoc --proto_path=./proto --go_out=plugins=micro:./src/share/pb ./proto/*.proto ``` 可以对代码进行自定义修改 ... .... ... 运行 build_proto.sh 文件后可以看到在指定文件夹下生成了相应的 user.pb.go 文件,在我这里如: ![Screenshot from 2017-10-11 17-09-09.png](http://upload-images.jianshu.io/upload_images/3365849-a5ddf7ce5fd38070.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 3、书写一个handler实现user.pb.go定义的接口 具体实现: 1)先创建一个user.go文件 2)定义一个结构体,命名为UserHandler,实现user.proto文件所有定义的service,在这里要注意一点,即使是暂时没有实现好业务,也有给个空实现,代码如下: ```go package handler import( "mewe_job/GoMicroDemo/src/share/pb" "golang.org/x/net/context" ) type UserHandler struct { } // new一个UserHandler func NewUserHandler() *UserHandler{ return &UserHandler{} } // 增 func (c *UserHandler) InsertUser(ctx context.Context, req * pb.InsertUserReq,rsp *pb.InsertUserRep)error { return nil } // 删 func (c *UserHandler) DeletetUser(ctx context.Context, req * pb.DeletetUserReq,rsp *pb.DeletetUserRep)error { return nil } // 查 func (c *UserHandler) SelectUser(ctx context.Context, req * pb.SelectUserReq,rsp *pb.SelectUserRep)error { return nil } //改 func (c *UserHandler) ModifyUser(ctx context.Context, req * pb.ModifyUserReq,rsp *pb.ModifyUserRep)error { return nil } ``` 4、将handler注册进微服务,这一步在main中实现 具体实现: ```go package main import ( "github.com/micro/cli" "mewe_job/GoMicroDemo/src/share/pb" "github.com/micro/go-micro/server" "mewe_job/GoMicroDemo/src/user-srv/handler" "github.com/micro/go-micro" "log" "mewe_job/GoMicroDemo/src/user-srv/db" "mewe_job/GoMicroDemo/src/share/config" ) func main() { // 创建Service,并定义一些参数 service := micro.NewService( micro.Name("go.micro.srv.user"), micro.Version("latest"), ) // 定义Service动作操作 service.Init( micro.Action(func(c *cli.Context) { log.Println("micro.Action test ...") // 先注册db db.Init(config.MysqlDSN) pb.RegisterUserServiceHandler(service.Server(), handler.NewUserHandler(), server.InternalHandler(true)) }), micro.AfterStop(func() error { log.Println("micro.AfterStop test ...") return nil }), micro.AfterStart(func() error { log.Println("micro.AfterStart test ...") return nil }), ) log.Println("启动user-srv服务 ...") //启动service if err := service.Run(); err != nil { log.Panic("user-srv服务启动失败 ...") } } ``` 这段代码主要的点有: - 创建service,通过以下代码可以初始化一个名叫 go.micro.srv.user 的微服务 ```go // 创建Service,并定义一些参数 service := micro.NewService( micro.Name("go.micro.srv.user"), micro.Version("latest"), ) ``` - 注册db连接和给go.micro.srv.user这个微服务绑定handler,虽然目前我还没有在db中定义db层的操作 ```go db.Init(config.MysqlDSN) pb.RegisterUserServiceHandler(service.Server(), handler.NewUserHandler(), server.InternalHandler(true)) ``` - 启动service,通过Run开启 ```go if err := service.Run(); err != nil { log.Panic("user-srv服务启动失败 ...") } ``` 5、现在就可以通过 go run main.go --registry=mdns 启动该服务了,之所以携带 --registry=mdns 是因为我本地ubuntu系统没有安装consul实现服务发现,所以就采用了gomicro官方推荐的方法。 ![Screenshot from 2017-10-11 17-42-03.png](http://upload-images.jianshu.io/upload_images/3365849-33f56af2c4e93f67.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 6、到这一步客户端还无法访问到服务,需要做些处理,我这里是加了个web服务,再将客户端的请求进行转发,main函数实现如下: ```go func main() { /* 方案一: mux := http.NewServeMux() mux.HandleFunc("/", handleRPC) log.Println("Listen on :8082") http.ListenAndServe(":8082", mux)*/ /* 方案二 */ service := web.NewService( web.Name(config.ServicePrefix+".web"), ) service.HandleFunc("/", handleRPC) if err := service.Init(); err != nil { log.Fatal(err) } if err := service.Run(); err != nil { log.Fatal(err) } } ``` 这里主要的函数是handleRPC这个函数,由于代码量偏多,具体实现可以查看源码。这里如果使用consul实现了服务发现,也可以通过方案一进行实现,这样的话web服务的端口还是固定的。 7、开启web服务 ```go $ go run web.go --registry=mdns Listening on [::]:36859 ``` 8、到这一步客户端就可以通过web服务端口和接口以及参数访问user这个微服务了,访问链接:(这里安利postman,一个谷歌的插件,超级好用 ... ) ```go http://127.0.0.1:36859/user/selectUser ``` tip:该项目的源码(包含数据库的增删查改的demo)可以查看 [源代码](https://gitee.com/xi_fan/ricoder_demo)

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

3013 次点击  ∙  2 赞  
加入收藏 微博
被以下专栏收入,发现更多相似内容
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传