Golang微服务基础技术

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

单体式和微服务

单体式架构服务

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

微服务

· 优点
1.职责单一
2.轻量级通信
3.独立性
4.迭代开发

· 缺点

  1. 运维成本高
  2. 分布式复杂度
  3. 接口成本高
  4. 重复性劳动
  5. 业务分离困难

单体式和微服务对比

在这里插入图片描述

RPC协议

什么是RPC

Remote Procedure Call Protocol – 远程过程调用协议
IPC进程间通信
RPC远程进程通信 — 应用层协议http协议同层底层使用TCP实现。

回顾
OSI7层模型架构物理层数据链路层网络层传输层会话层表示层应用层
TCP/IP4层架构链路层网络层传输层应用层

理解RPC
像调用本地函数一样去调用远程函数。
通过rpc协议传递函数名函数参数达到在本地调用远端函数得返回值到本地的目标

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

RPC入门使用

远程 — 网络

回顾Go语言 一般性 网络socket通信
server端
net.Listen() – listener 创建监听器
listener.Accpet() – conn 启动监听建立连接
conn.read()
conn.write()
defer conn.Close() / listener.Close()
client端
net.Dial() – conn
conn.Write()
conn.Read()
defer conn.Close()

RPC使用的步骤

-------服务端

1.注册RPC服务对象。给对象绑定方法1.定义类2.绑定类方法

rpc.RegisterName("服务名",回调对象)
  1. 创建监听器
listener,err := net.Listen()
  1. 建立连接
conn,err := listener.Accept()
  1. 将连接 绑定rpc服务
rpc.ServeConn(conn)

------ 客户端
1.用rpc连接服务器。

conn,err := rpc.Dial()

2.调用远程函数。

conn.Call("服务名.方法名",传入参数传出参数)

RPC相关函数

1.注册rpc服务

func (server *Server) RegisterName(name string,rcvr interface{}) error1服务名。字符串类型。
参2对应rpc对象。该对象绑定方法要满足如下条件
     1.方法必须是导出的----包外可见首字母大写。
     2.方法必须有两个参数都是导出类型内建类型。
     3.方法的第二个参数必须是“指针” 传出参数
     4.方法只有一个 error接口类型的返回值。
举例
type World stuct{

}
functhis *World HelloWorld(name string,resp *string) error{

}
rpc.RegisterName("服务名",new(World))

2.绑定rpc服务

func (server *Server) ServerConn(conn io.ReadWriteCloser)
	conn:成功建立好连接的 socket -- conn

3.调用远程函数

func client *Client CallserviceMethod stringargs interface{}reply interface{} error

	serviceMethod“服务器.方法名”
	args传入参数方法需要的数据。
	reply传出参数。定义var变量&变量名  完成传参。

编码实现

server端

package main
 
import (
	"net/rpc"
	"fmt"
	"net"
)

// 定义类对象
type World struct {
	
}
// 绑定类方法
func (this *World) HelloWorld (name string,resp *string) error {
	*resp = name + "你好"
	return nil
}
func main(){
	
	// 1.注册RPC服务绑定对象方法
	err := rpc.RegisterName("hello",new(World))
	if err != nil{
		fmt.Println("注册 rpc 服务失败",err)
		return
	}
	// 2.设置监听
	listener,err := net.Listen("tcp","127.0.0.1:8802")
	if err != nil{
		fmt.Println("net.Listen err:",err)
		return
	}
	defer listener.Close()
	
	fmt.Println("开始监听...")
	// 3.建立连接
	conn,err := listener.Accept()
	if err != nil{
		fmt.Println("Accpet() err:",err)
		return 
	}
	defer conn.Close()
	fmt.Println("连接成功....")
	// 4. 绑定服务
	rpc.ServeConn(conn)
}

client端

package main 

import (
	"net/rpc"
	"fmt"
)

func main(){
	// 1.用rpc连接服务器  --Dial
	conn,err := rpc.Dial("tcp","127.0.0.1:8802")
	if err != nil {
		fmt.Println("Dial err:",err)
		return 
	}
	defer conn.Close()

	// 2.调用远程函数
	var reply string   // 接收返回值   --- 传出参数
	err = conn.Call("hello.HelloWorld","李白",&reply)
	if err != nil {
		fmt.Println("Call err:",err)
		return 
	}
	fmt.Println(reply)
}

json版rpc

使用 nc -l 127.0.0.1 8800 充当服务器
2_client.go充当客户端发起通信。 --乱码
因为rpc使用了go语言特有的序列化gob其他编程语言不能解析
使用通用的序列化反序列化。 --jsonprotobuf

修改客户端

修改客户端使用jsonrpc
conn,err := jsonrpc.Dial("tcp","127.0.0.1:8800")

修改服务器端

修改服务器端使用jsonrpc

jsonrpc.ServerConn(conn)

如果绑定方法返回值的error不为空无论传出参数是否有值服务端都不会返回数据。

rpc封装

3_design.go

package main 

import (
   "net/rpc/jsonrpc"
   "net/rpc"
)
// 要求服务端在注册rpc对象时能让编译期检查出  注册对象是否合法

// 创建接口在接口中定义方法原型
type MyInterface interface{
	HelloWorld(string,*string) error
}

// 调用该方法需要给 i 传参参数应该是实现了  HelloWorld 方法的类对象
func RegisterService(i MyInterface) {
	rpc.RegisterName("hello",i)
}

//-------------------客户端调用

// 定义类
type Myclient struct {
	c *rpc.Client
}

// 由于使用了c调用Call因此需要初始化c
func InitClient(addr string) Myclient {
	conn,_ := jsonrpc.Dial("tcp",addr)
	

	return Myclient{c:conn}
}

// 实现函数原型参照上面的Interface来实现
func (this *Myclient) HelloWorld (a string,b *string) error {
	// 参数1参照上面的 InterfaceRegisterName  而来a传入参数  b:传出参数
	return this.c.Call("hello.HelloWorld",a,b)
}

1_server.go

package main
 
import (
	// "net/rpc"
	"net/rpc/jsonrpc"
	"fmt"
	"net"
)

// 定义类对象
type World struct {
	
}
// 绑定类方法

func (this *World) HelloWorld (name string,resp *string) error {
	*resp = name + "你好"
	return nil
}

func main(){
	// 1.注册RPC服务绑定对象方法
	RegisterService(new(World))
	// err := rpc.RegisterName("hello",new(World))
	// if err != nil{
	// 	fmt.Println("注册 rpc 服务失败",err)
	// 	return
	// }
	// 2.设置监听
	listener,err := net.Listen("tcp","127.0.0.1:8803")
	// listener,err := InitClient("127.0.0.1:8803")
	if err != nil{
		fmt.Println("net.Listen err:",err)
		return
	}
	defer listener.Close()
	
	fmt.Println("开始监听...")
	// 3.建立连接
	conn,err := listener.Accept()
	if err != nil{
		fmt.Println("Accpet() err:",err)
		return 
	}
	defer conn.Close()
	fmt.Println("连接成功....")
	// 4. 绑定服务
	// rpc.ServeConn(conn)
	jsonrpc.ServeConn(conn)
}

2_client.go

package main 

import (
	"net/rpc"
	"fmt"
)

func main01(){
	// 1.用rpc连接服务器  --Dial
	conn,err := rpc.Dial("tcp","127.0.0.1:8802")
	if err != nil {
		fmt.Println("Dial err:",err)
		return 
	}
	defer conn.Close()

	// 2.调用远程函数
	var reply string   // 接收返回值   --- 传出参数
	err = conn.Call("hello.HelloWorld","李白",&reply)
	if err != nil {
		fmt.Println("Call err:",err)
		return 
	}
	fmt.Println(reply)
}

// 结合 3_design.go 测试
func main(){
	myClient := InitClient("127.0.0.1:8803")

	var resp string 

	err := myClient.HelloWorld("杜甫",&resp)
	if err != nil{
		fmt.Println("HelloWorld err:",err)
		return
	}

	fmt.Println(resp,err)
}

ProtoBuf认识与使用

protobuf简介
Protobuf是Protocol Buffers的简称它是Google公司开发的一种描述语言是一种轻便高效的结构化数据存储格式可以用于结构化数据串行化或者说序列化。他很适合做数据存储或者RPC数据交换格式
可以用于通信协议数据存储等领域的语言无关平台无关可扩展的序列化结构数据格式。目前提供了C++JavaPython三种语言的API。

Protobuf刚开源是的定位类似于xmljson等数据描述语言通过附带工具生成代码并实现将结构化数据序列化的功能这里我们更关注的是Protobuf作为接口规范的描述语言可以作为设计安全的跨语言RPC接口的基础工具。

需要了解两点

  1. protobuf是类似于json一样的数据描述语言数据格式
  2. protobuf非常适合于RPC数据交换格式

接着我们来看一下protobuf的优势和劣势

优势
1.序列化后面积比Json和Xml很小适合网络传输
2.支持跨平台多语言
3.消息格式升级和兼容性还不错
4.序列化反序列化速度很快快于json的处理速度

劣势

  1. 应用不够广相比xml和json
  2. 二进制格式导致可读性差
  3. 缺乏自描述

protobuf的安装
1.下载protobuf

方法一===》git clone https://github.com/protocolbuffers/protobuf.git

方法二===》 或者将准备好的压缩包进行拖入
      解压到 $GOPATH/src/github.com/protocolbuffers/下面
      Unizip protobuf.zip
  1. 安装Ubuntu

在这里插入图片描述
在这里插入图片描述
3.测试protobuf编译工具

protoc -h

如果正常输出 相关指令 没有报任何error为安装成功

4.安装protobuf的go语言插件
在这里插入图片描述

感谢大家观看我们下次见

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: go