服务是一个或者一组相对较小且独立的功能单元,是用户可以感知最小功能集。服务拆分原则:高内聚低耦合
。
微服务架构风格是将单个应用程序作为一组小型服务开发的方法,每个服务程序都在自己的进程中运行,并与轻量级机制(通常是HTTP资源API)进行通信。这些服务是围绕业务功能构建的。可以通过全自动部署机器独立部署。这些服务器可以用不同的编程语言编写,使用不同的数据存储技术,并尽量不用集中式方式进行管理。微服务架构精髓:分而治之,合而用之
。
易混淆概念:
微服务架构:将复杂的系统使用组件化的方式进行拆分,并使用轻量级通讯方式进行整合的一种设计方法。
微服务:通过这种架构设计方法拆分出来的一个独立的组件化的小应用。
单体式服务架构
特性:
微服务架构
单体式服务和微服务对比
传统单体架构 | 分布式微服务化架构 | |
---|---|---|
新功能开发 | 需要时间 | 容易开发和实现 |
部署 | 不经常而且容易部署 | 经常发布,部署复杂 |
隔离性 | 故障影响范围大 | 故障影响范围小 |
架构设计 | 初期技术选型难度大 | 设计逻辑难度大 |
系统性能 | 相对时间快,吞吐量小 | 相对时间慢,吞吐量大 |
系统运维 | 运维难度简单 | 运维难度复杂 |
新人上手 | 学习曲线大(应用逻辑) | 学习曲线大(架构逻辑) |
技术 | 技术单一而且封闭 | 技术多样而且容易开发 |
测试和差错 | 简单 | 复杂(每个服务都要进行单独测试,还需要集群测试) |
系统扩展性 | 扩展性差 | 扩展性好 |
系统管理 | 重点在于开发成本 | 重点在于服务治理和调度 |
RPC(Remote Procedure Call Protocol) :远程过程调用协议。可以像调用本地函数一样,去调用远程函数。
为什么微服务使用 RPC:
- 每个服务都被封装成 进程。彼此“独立”。
- 进程和进程之间,可以使用不同的语言实现。
与许多RPC系统类似gRPC也基于以下理念:定义一个服务,指定其能够被远程调用的方法
。
在使用protobu编译服务f时,只能使用gRPC将其编译。
参考资料:
gRPC 官方文档中文版:http://doc.oschina.net/grpc?t=60133
gRPC官网:https://grpc.io
方法1:官方推荐安装方法(需要科学上网)
go get -u -v google.golang.org/grpc
方法2:在gopath
下的src\google.golang.org
中执行:
git clone https://github.com/grpc/grpc-go.git
git clone https://github.com/google/go-genproto.git
生成grpc-go
文件夹改名grpc
,go-genproto
文件夹改名genproto
验证:
服务端:
cd $gopath\src\google.golang.org\grpc\examples\helloworld\greeter_server
go run main.go
客户端:
cd $gopath\src\google.golang.org\grpc\examples\helloworld\greeter_client
go run main.go
如果报错:
dial tcp 34.64.4.113:443:
解决办法:go env -w GOPROXY=https://goproxy.cn,direct
对proto文件进行编译
protoc --go_out=. --go-grpc_out=. ./*.proto
新建一个person.proto
的proto文件
syntax = "proto3";
package pb;
//消息体——同一个包中不允许有同名的消息体,即使是在pb中别的proto文件中定义的
message Teacher {
int32 age = 1;
string name = 2;
}
//定义服务
service SayName {
rpc SayHello(Teacher) returns (Teacher);
}
使用命令protoc --go_out=plugins=grpc:. *.proto
编译,会自动生成peron.pb.go
文件,这个生成文件不要做任何修改。
写服务端,新建一个server.go
文件
//定义类
type Children struct {
}
//按接口绑定类方法,重写SayHello
func (c *Children)SayHello(ctx context.Context, t *pb.Teacher) (*pb.Teacher, error) {
t.Name += "is sleeping"
return t, nil
}
func main() {
//初始化一个grpc对象 服务端
grpcServer := grpc.NewServer()
//注册服务端
pb.RegisterSayNameServer(grpcServer, new(Children))
//设置监听
listener, err := net.Listen("tcp", "127.0.0.1:8800")
if err != nil {
fmt.Println("Listen err:", err)
return
}
defer listener.Close()
//启动服务
grpcServer.Serve(listener)
}
写服务端,新建一个client.go
文件
func main() {
//连接grpc服务
grpcConn, err := grpc.Dial("127.0.0.1:8800", grpc.WithInsecure())
if err != nil {
fmt.Println("grpc Dial err:", err)
return
}
defer grpcConn.Close()
//初始化grpc客户端
grpcCLient := pb.NewSayNameClient(grpcConn)
teacher := pb.Teacher{
Age: 18,
Name: "iscast",
}
//调用远程函数
t, err := grpcCLient.SayHello(context.TODO(), &teacher)
fmt.Println(t, err)
}
运行服务端和客户端
如果服务端是用两种不同的语言编写,grpc可以保证服务端和客户端的通信,protobuf可以保证两种语言之间的正常的数据交换