1、微服务
服务拆分原则:高内聚低耦合
微(micro):狭义来讲是就是体积小
服务(service):
广义来讲,微服务是一种分布式系统解决
1. 微服务概念
2. 由来
3. 微服务和单体式架构区别
—-过往服务器
—-微服务
优点:
- 职责单一
- 通信轻量级
- 独立性
- 迭代开发
缺点:
- 运维成本高
- 分布式复杂度
- 接口成本高
- 重复性劳动
- 业务分离困难
对比:
2、RPC协议
RPC(Remote Procedure Call Protocol)— 远端过程调用协议
IPC:进程间通信
RPC:远程进程通信 — 应用层协议(http协议同层)。底层使用TCP实现
OSI:7层模型架构(物、数、网、传、会、表、应)
TCP/IP:4层架构(链路层、网络层、传输层、应用层)
- 理解RPC:
- 像调用本地函数一样,去调用远程函数
- 通过RPC协议,传递:函数名、函数参数。达到在本地,调用远端函数,得返回值到本地的目的。
- 像调用本地函数一样,去调用远程函数
- 为什么微服务要使用RPC:
- 每个服务都被封装成进程。彼此“独立”
- 进程和进程之间,可以使用不同的语言实现
1. RPC入门
远程 — 网络
Go语言 一般性 网络socket通信
Server端:
net.Listen() —- listener 创建监听器
listener.Accpry() —- conn 启动监听,建立连接
conn.Read()
conn.Write()
defer conn.Close()/listener.Close()
Client端:
net.Dial() -- conn
conn.Write()
conn.Read()
conn.Close()
RPC使用的一般步骤:
—- 服务端:
- 注册RPC服务对象,给对象绑定方法(1.定义类;2.绑定类方法)
rpc.RegisterName("服务名",回调对象)
- 创建监听器
listener,err := net.Listen()
- 建立连接
conn, err := listener.Accept()
- 将连接绑定RPC服务
rpc.ServerConn(conn)
—- 客户端:
- 用RPC连接服务器 rpc.Dial()
conn, err := rpc.Dial()
- 调用远程函数
conn.Call("服务名.方法名",传入参数, 传出参数)
RPC相关函数
- 注册RPC服务
func (server *Server) RegisterName(name String,rcvr interface{}) err
例如:
type World struct {}
func (world *World) HelloWorld(name string, resp *string) error {}
rpc.RegisterName("ServerName", new(World))
- 参数1:服务名
- 参数2:对应的rpc对象,该对象满足如下条件
- 方法必须是导出的 — 包外可见(首字母大写)
- 方法必须有两个参数,都是导出类型、内建类型
- 方法的第二个参数必须是“指针”(传出参数)
- 方法只有一个
error
接口类型的返回值
- 绑定rpc服务
func (server *Server) ServerConn(conn io.ReadWriteCloser)
- conn:成功建立好连接的socket —- conn
- 调用远程函数
func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) error
- serviceMethod:”服务名.方法名”
- args:传入参数。方法需要的数据
- reply:传出参数,定义var变量,&变量名, 完成传参
编码实现
server
package main
import (
"fmt"
"net"
"net/rpc"
)
//定义类对象
type World struct{}
//绑定World类方法
func (world *World) HelloWorld(name string, resp *string) error {
*resp = name + "你好!"
//return nil
return errors.New("未知错误...")
}
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:8088")
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("listener.Accept err:", err)
return
}
defer conn.Close()
fmt.Println("连接建立成功...")
//4. 绑定服务
rpc.ServeConn(conn)
}
client
package main
import (
"fmt"
"net/rpc"
)
func main() {
// 1. 用RPC连接服务器
conn, err := rpc.Dial("tcp", "127.0.0.1:8088")
if err != nil {
fmt.Println("rpc.Dial err:", err)
return
}
defer conn.Close()
// 2. 调用远程函数
var reply string //接收函数传出参数
err = conn.Call("hello.HelloWorld", "李白", &reply)
if err != nil {
fmt.Println("conn.Call err:", err)
return
}
fmt.Println("reply:", reply)
}
json版rpc
- 使用
nc -l 127.0.0.1 8088
充当服务器(ubuntu) - client.go充当客户端,发起通信。 —- 乱码
- 原因:RPC使用了Go语言特有的数据序列化gob,其他编程语言不能解析
- 使用通用的序列化、反序列化
修改客户端:(使用jsonrpc)
也可以修改服务端:()
rpc封装
3、ProtoBuf
— Google开发的一种数据描述语言
适合数据存储、数据交换
编译ProtoBuf
protoc --go_out=./ *proto
==> 名字.报名.go