1 前言
在上一篇文章——《Go 微服务实战之如何应用 go-micro 写微服务利用》中,咱们介绍了微服务的相干概念和 go-micro 框架的特点。
接下来,咱们将以循序渐进的形式建设一个繁难的提供加解密服务的 Go 微服务项目。首先为了创立微服务,须要后期设计几个实体:
- 定义服务的 RPC 办法的 protocol buffer 文件
- 具体方法实现的 handler 文件
- 一个公开 RPC 办法的服务器 server
- 一个能够收回 RPC 申请并取得响应后果的客户端 client
2 创立 encryption.proto 文件
首先,为了将 protocol buffer 文件编译为 Go 包,须要先装置 protoc
,下载点此处,抉择你对应的零碎。
本文是以 Win 进行的示例开发,下载的是 protoc-21.9-win32.zip
,解压完后增加到零碎环境变量,如图所示:
而后装置 proto-gen-micro
,应用如下命令:
go install github.com/go-micro/generator/cmd/[email protected]
接下来,创立咱们的我的项目目录 encryptService
文件夹,而后在其中创立一个 proto
目录,新建一个 encryption.proto
文件,写入如下内容:
syntax = "proto3";package main;option go_package="./proto";service Encrypter { rpc Encrypt(Request) returns (Response) {} rpc Decrypt(Request) returns (Response) {}}message Request { string message = 1; string key = 2;}message Response { string result = 2;}
下面的文件命名了一个 Encrypter
的服务,有着 Request
和 Response
两条音讯。这两条信息是用来申请加密和解密的。
- 首行前置的文件语法是
proto3
- 申请音讯
Request
有两个字段,别离为:message
(须要加密的信息)和key
(密钥)。客户端应用这些字段来发送一个plaintext/ciphertext
音讯 - 响应音讯
Response
只有一个字段result
:它是加密/解密过程的后果。加密Encypter
服务有两个 RPC 办法:Encrypt
和Decypt
,两者都是接管一个申请,而后返回一个响应。
接着咱们能够通过编译 .proto
文件来生成 Go 文件,执行如下命令:
protoc --proto_path=. --micro_out=. --go_out=. proto/encryption.proto
执行胜利后会在咱们的我的项目 encryptService/proto
目录下主动生成两个文件:
- encryption.pb.go
- encryption.pb.micro.go
文件胜利生成后如图:
这些主动生成的文件不须要咱们手动进行批改。
3 编写 encryptService
微服务端
3.1 新建 utils.go
文件
接下来,咱们新建一个 utils.go
文件,定义字符串 AES 加解密的办法,如下:
package mainimport ( "crypto/aes" "crypto/cipher" "encoding/base64")var initVector = []byte{35, 46, 57, 24, 85, 35, 24, 74, 87, 35, 88, 98, 66, 32, 14, 05}// 字符串加密函数func EncryptString(key, text string) string { block, err := aes.NewCipher([]byte(key)) if err != nil { panic(err) } plaintext := []byte(text) cfb := cipher.NewCFBEncrypter(block, initVector) cipertext := make([]byte, len(plaintext)) cfb.XORKeyStream(cipertext, plaintext) return base64.StdEncoding.EncodeToString(cipertext)}// 解密函数func DecryptString(key, text string) string { block, err := aes.NewCipher([]byte(key)) if err != nil { panic(err) } cipertext, _ := base64.StdEncoding.DecodeString(text) cfb := cipher.NewCFBEncrypter(block, initVector) plaintext := make([]byte, len(cipertext)) cfb.XORKeyStream(plaintext, cipertext) return string(plaintext)}
3.2 新建 handler.go
文件
接着新建一个 handler.go
文件,在这个文件内为咱们的服务定义业务逻辑:
- 首先定义一个
Encrypt
构造体 - 减少两个办法
Encrypt
和Decrypt
解决 RPC 申请
package mainimport ( "context" "encryptService/proto")type Encrypter struct{}// 将音讯加密后发送申请func (g *Encrypter) Encrypt(ctx context.Context, req *proto.Request, rsp *proto.Response) error { rsp.Result = EncryptString(req.Key, req.Message) return nil}// 将密文解密后返回相应func (g *Encrypter) Decrypt(ctx context.Context, req *proto.Request, rsp *proto.Response) error { rsp.Result = DecryptString(req.Key, req.Message) return nil}
如上的代码,在 Encrypter
构造体中的两个办法 Encrypt
和 Decrypt
,
func (g *Encrypter) Encrypt(ctx context.Context, req *proto.Request, rsp *proto.Response)func (g *Encrypter) Decrypt(ctx context.Context, req *proto.Request, rsp *proto.Response)
两个办法都是接管一个 context
对象、一个 RPC 申请对象、和一个 RPC 响应对象。每个办法所做的工作是调用各自的实用函数,并将响应对象返回为一个后果 rsp.Result
。
值得一提的是,Encrypt
加密和 Decrypt
解密会被映射到 protocol buffer 文件中的 RPC 办法中,如下办法:
rpc Encrypt(Request) returns (Response) {}rpc Decrypt(Request) returns (Response) {}
3.3 新建 main.go
文件
紧接着,咱们在 encryptService
根目录下,新建一个 main.go
文件,依据上一篇文章中对 go-micro 框架中创立微服务实例的办法,咱们写入如下内容:
package mainimport ( "encryptService/proto" "fmt" "go-micro.dev/v4")func main() { // 创立一个新服务 service := micro.NewService( micro.Name("encrypter"), ) // 初始化 service.Init() proto.RegisterEncrypterHandler(service.Server(), new(Encrypter)) // 启动服务 if err := service.Run(); err != nil { fmt.Println(err) }}
micro.NewService
用于新建一个微服务,而后一个service
对象- 运行
service.Init()
收集命令行参数 - 通过
proto.RegisterEncrypterHandler
办法注册服务,这个办法是由 protocol buffer 编译器动静生成的。 - 最初,
service.Run
启动服务
3.4 运行 encryptService
服务
咱们来看一下如何失常启动整个微服务实例:
- 执行
go mod init encrypService
在执行这一步呈现问题,比方遇到如下谬误:
go: encryptClient/proto imports go-micro.dev/v4/api: go-micro.dev/v4/[email protected]: parsing go.mod: module declares its path as: github.com/micro/go-micro but was required as: go-micro.dev/v4/api
应用如下命令进行解决,失去 v4 版:
go get go-micro.dev/v4
胜利截图如下:
再来执行 go mod tidy
,执行胜利如下图,最初会主动生成 go.mod
和 go.sum
文件。:
应用 go build .
编译整个我的项目,编译胜利后在 Win 下会生成一个 .exe
的可执行文件。
编译残缺个我的项目后的目录构造如下:
最初,运行咱们的 encrypService 服务,通过应用 ./encryptService.exe
命令进行启动,胜利如下:
正如你从服务器终端看到的那样,go-micro 利用一个 info Transport
和一个音讯代理 info Broker
胜利启动了一个微服务。此时,咱们能够通过在浏览器中拜访 http://127.0.0.1:58184/
查看相干信息:
当初,客户端能够向这些端口发送申请,但目前这些服务并不那么有用,因为咱们还没有编写客户端来生产这些 API,接下来尝试建设一个 encryptClient
客户端,学习如何连贯到这个服务器。
4 编写 encryptClient
客户端
同理,通过 Go Micro 框架构建客户端,通过 RPC 调用下面的服务端,接下来就是按步骤编写客户端的办法。新建一个 encryptClient
目录,而后在这个目录下建设一个 proto
文件夹。客户端我的项目结构图如下:
4.1 编写 proto 文件
首先,咱们须要晓得服务器和客户端应该批准应用雷同的 protocol buffers (协定缓冲区)。同样地,Go Micro 心愿服务器和客户端应用雷同的 .proto
文件,在下面的的例子是 encryption.proto
文件。
在 encryptClient/proto
下创立一个和服务端雷同的 encryption.proto
文件:
syntax = "proto3";package main;option go_package="./proto";service Encrypter { rpc Encrypt(Request) returns (Response) {} rpc Decrypt(Request) returns (Response) {}}message Request { string message = 1; string key = 2;}message Response { string result = 2;}
相似地,应用 protoc -I=. --micro_out=. --go_out=. proto/encryption.proto
命令执行生成 Go 文件,如图:
4.2 编写 main.go
文件
package mainimport ( "context" "encryptClient/proto" "fmt" "go-micro.dev/v4")func main() { // 创立新服务 service := micro.NewService(micro.Name("encrypter.client")) // 初始化客户端,解析命令行参数 service.Init() // 创立新的加密服务实例 encrypter := proto.NewEncrypterService("encrypter", service.Client()) // 调用 encrypter 加密服务 rsp, err := encrypter.Encrypt(context.TODO(), &proto.Request{ Message: "Hello world", Key: "111023043350789514532147", }) if err != nil { fmt.Println(err) } // 打印响应 fmt.Println(rsp.Result) // 调用解密 decrypter 服务 rsp, err = encrypter.Decrypt(context.TODO(), &proto.Request{ Message: rsp.Result, Key: "111023043350789514532147", }) if err != nil { fmt.Println(err) } // 打印解密后果 fmt.Println(rsp.Result)}
service := micro.NewService(micro.Name("encrypter.client")
新建服务实例- 调用加密服务时,传入
"Hello world"
文本和一个密钥"111023043350789514532147"
fmt.Println(rsp.Result)
,最初在终端打印rsp.Result
- 调用解密服务时,传入加密的后果
rsp.Result
和同一个密钥"111023043350789514532147"
- 而后打印解密后果
fmt.Println(rsp.Result)
编写实现后,执行 go mod init encryptClient
,如图:
接着,应用 go mod tidy
,主动生成 go.sum
文件。
而后执行编译 go build .
,生成 encryptClient.exe
文件。
最初执行客户端打印,终端输入 Hello world 的 AES 加密文本 8rqECLu6rQTfkCM=
和解密后的明文 Hello world
:
$ ./encryptClient.exe 8rqECLu6rQTfkCM=Hello world
执行过程,如图所示:
这个过程证实了咱们的加解密微服务的 RPC 调用时胜利的,不过也能看到通过应用 Go Micro 框架,咱们能通过几行代码,就创立了微服务和客户端。
5 总结
本文通过实现加解密操作展现了一个微服务利用的开发过程。通过编写服务端,胜利运行了一个微服务实例,该服务可能通过加密申请失去一个加密后的密文,通过解密申请将音讯进行解密,并返回明文后果。而后通过编写客户端向服务端进行 RPC 调用,胜利将 Hello world 字符串进行加密并打印出密文和明文的后果。
这个过程充沛展现了 Go Micro 框架的便利性,至于 Go Mirco 框架还有更多的常识等着大家学习。心愿本文能起到抛砖引玉的成果,让更多看到文章的人退出学习和微服务的开发当中。
心愿本文能对你有所帮忙,如果喜爱本文,能够点个赞或关注。
这里是宇宙之一粟,下一篇文章见!
宇宙古今无有穷期,毕生不过顷刻,当思奋争。
参考链接:
- Go Micro入门 - Go语言中文文档
- go-micro 微服务开发中文手册
- Writing microservices with Go Micro
- Introduction to gRPC
- Hands-On-Restful-Web-services-with-Go
- https://github.com/go-micro/g...
- https://github.com/go-micro/g...
本文参加了思否技术征文,欢送正在浏览的你也退出。