1、微服务

服务拆分原则:高内聚低耦合

微(micro):狭义来讲是就是体积小

服务(service):

广义来讲,微服务是一种分布式系统解决

1. 微服务概念

2. 由来

3. 微服务和单体式架构区别

—-过往服务器

—-微服务

优点:

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

缺点:

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

对比:

微服务-一(micro services) - 图1

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端:

  1. net.Dial() -- conn

conn.Write()

conn.Read()

conn.Close()

RPC使用的一般步骤:

—- 服务端:

  1. 注册RPC服务对象,给对象绑定方法(1.定义类;2.绑定类方法)
  1. rpc.RegisterName("服务名",回调对象)
  1. 创建监听器
  1. listener,err := net.Listen()
  1. 建立连接
  1. conn, err := listener.Accept()
  1. 将连接绑定RPC服务
  1. rpc.ServerConn(conn)

—- 客户端:

  1. 用RPC连接服务器 rpc.Dial()
  1. conn, err := rpc.Dial()
  1. 调用远程函数
  1. conn.Call("服务名.方法名",传入参数, 传出参数)

RPC相关函数

  1. 注册RPC服务
  1. func (server *Server) RegisterName(name String,rcvr interface{}) err
  2. 例如:
  3. type World struct {}
  4. func (world *World) HelloWorld(name string, resp *string) error {}
  5. rpc.RegisterName("ServerName", new(World))
  • 参数1:服务名
  • 参数2:对应的rpc对象,该对象满足如下条件
    • 方法必须是导出的 — 包外可见(首字母大写)
    • 方法必须有两个参数,都是导出类型、内建类型
    • 方法的第二个参数必须是“指针”(传出参数)
    • 方法只有一个 error 接口类型的返回值
  1. 绑定rpc服务
  1. func (server *Server) ServerConn(conn io.ReadWriteCloser)
  • conn:成功建立好连接的socket —- conn
  1. 调用远程函数
  1. func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) error
  • serviceMethod:”服务名.方法名”
  • args:传入参数。方法需要的数据
  • reply:传出参数,定义var变量,&变量名, 完成传参

编码实现

server

  1. package main
  2. import (
  3. "fmt"
  4. "net"
  5. "net/rpc"
  6. )
  7. //定义类对象
  8. type World struct{}
  9. //绑定World类方法
  10. func (world *World) HelloWorld(name string, resp *string) error {
  11. *resp = name + "你好!"
  12. //return nil
  13. return errors.New("未知错误...")
  14. }
  15. func main() {
  16. //1. 注册rpc服务,绑定服务对象方法
  17. err := rpc.RegisterName("hello", new(World))
  18. if err != nil {
  19. fmt.Println("注册rpc服务失败:", err)
  20. return
  21. }
  22. //2. 设置监听
  23. listener, err := net.Listen("tcp", "127.0.0.1:8088")
  24. if err != nil {
  25. fmt.Println("net.Listen err:", err)
  26. return
  27. }
  28. defer listener.Close()
  29. fmt.Println("开始监听...")
  30. //3. 建立连接
  31. conn, err := listener.Accept()
  32. if err != nil {
  33. fmt.Println("listener.Accept err:", err)
  34. return
  35. }
  36. defer conn.Close()
  37. fmt.Println("连接建立成功...")
  38. //4. 绑定服务
  39. rpc.ServeConn(conn)
  40. }

client

  1. package main
  2. import (
  3. "fmt"
  4. "net/rpc"
  5. )
  6. func main() {
  7. // 1. 用RPC连接服务器
  8. conn, err := rpc.Dial("tcp", "127.0.0.1:8088")
  9. if err != nil {
  10. fmt.Println("rpc.Dial err:", err)
  11. return
  12. }
  13. defer conn.Close()
  14. // 2. 调用远程函数
  15. var reply string //接收函数传出参数
  16. err = conn.Call("hello.HelloWorld", "李白", &reply)
  17. if err != nil {
  18. fmt.Println("conn.Call err:", err)
  19. return
  20. }
  21. fmt.Println("reply:", reply)
  22. }

json版rpc

  • 使用nc -l 127.0.0.1 8088充当服务器(ubuntu)
  • client.go充当客户端,发起通信。 —- 乱码
    • 原因:RPC使用了Go语言特有的数据序列化gob,其他编程语言不能解析
  • 使用通用的序列化、反序列化

修改客户端:(使用jsonrpc)

微服务-一(micro services) - 图2

也可以修改服务端:()

微服务-一(micro services) - 图3

rpc封装

3、ProtoBuf

— Google开发的一种数据描述语言

适合数据存储、数据交换

编译ProtoBuf

protoc --go_out=./ *proto ==> 名字.报名.go

4、GRPC