文章目录

  • 一、微服务简介
  • 单体式服务架构和微服务架构
  • 二、RPC协议
  • 三、GRPC协议
  • 1. 简介
  • 2. GRPC安装
  • 3. GRPC使用
  • 4. 一个小Demo



一、微服务简介

服务是一个或者一组相对较小且独立的功能单元,是用户可以感知最小功能集。服务拆分原则:高内聚低耦合
微服务架构风格是将单个应用程序作为一组小型服务开发的方法,每个服务程序都在自己的进程中运行,并与轻量级机制(通常是HTTP资源API)进行通信。这些服务是围绕业务功能构建的。可以通过全自动部署机器独立部署。这些服务器可以用不同的编程语言编写,使用不同的数据存储技术,并尽量不用集中式方式进行管理。微服务架构精髓:分而治之,合而用之

易混淆概念: 微服务架构:将复杂的系统使用组件化的方式进行拆分,并使用轻量级通讯方式进行整合的一种设计方法
微服务:通过这种架构设计方法拆分出来的一个独立的组件化的小应用

单体式服务架构和微服务架构

单体式服务架构 特性:

  • 复杂性随着开发越来越高, 遇到问题解决困难。
  • 技术债务逐渐上升。
  • 耦合度高,维护成本大!
  1. 出现bug, 不容易排查
  2. 解决旧bug, 会出新bug
  • 持续交付时间较长。
  • 技术选型成本高,风险大。
  • 扩展性较差
  1. 垂直扩展:通过增加单个系统程的负荷来实现扩展。
  2. 水平扩展:通过增加更多的系统成员来实现扩展。

微服务架构

  • 优点:
  1. 职责单一
  2. 轻量级通信
  3. 独立性
  4. 迭代开发。
  • 缺点:
  1. 运维成本高
  2. 分部式复杂度
  3. 接口成本高
  4. 重复性劳动
  5. 业务分离困难。

单体式服务和微服务对比

传统单体架构

分布式微服务化架构

新功能开发

需要时间

容易开发和实现

部署

不经常而且容易部署

经常发布,部署复杂

隔离性

故障影响范围大

故障影响范围小

架构设计

初期技术选型难度大

设计逻辑难度大

系统性能

相对时间快,吞吐量小

相对时间慢,吞吐量大

系统运维

运维难度简单

运维难度复杂

新人上手

学习曲线大(应用逻辑)

学习曲线大(架构逻辑)

技术

技术单一而且封闭

技术多样而且容易开发

测试和差错

简单

复杂(每个服务都要进行单独测试,还需要集群测试)

系统扩展性

扩展性差

扩展性好

系统管理

重点在于开发成本

重点在于服务治理和调度


二、RPC协议

RPC(Remote Procedure Call Protocol) :远程过程调用协议。可以像调用本地函数一样,去调用远程函数。

  • 通过rpc协议,传递:函数名、函数参数。达到在本地,调用远端函数,得返回值到本地的目标。
  • 统一RPC框架可以统一 一套序列化、反序列化、网络框架、连接池、收发线程、超时处理、状态机等“业务之外”的技术劳动。

为什么微服务使用 RPC:

  1. 每个服务都被封装成 进程。彼此“独立”。
  2. 进程和进程之间,可以使用不同的语言实现。

三、GRPC协议

1. 简介

与许多RPC系统类似gRPC也基于以下理念:定义一个服务,指定其能够被远程调用的方法
在使用protobu编译服务f时,只能使用gRPC将其编译。

参考资料:
gRPC 官方文档中文版:
gRPC官网:https://grpc.io


2. GRPC安装

方法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文件夹改名grpcgo-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

3. GRPC使用

对proto文件进行编译

protoc --go_out=. --go-grpc_out=. ./*.proto

4. 一个小Demo

新建一个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可以保证两种语言之间的正常的数据交换