热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Golang微服务基础技术

单体式和微服务单体式架构服务------过往大家熟悉的服务器特性:1.复杂性随着开发越来越高,遇到问题解决困难。2.技术债务逐渐上升3.耦合度高&#


单体式和微服务

单体式架构服务

------过往大家熟悉的服务器
特性:
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{}) error
1:服务名。字符串类型。
2:对应rpc对象。该对象绑定方法要满足如下条件:
1.方法必须是导出的----包外可见,首字母大写。
2.方法必须有两个参数,都是导出类型,内建类型。
3.方法的第二个参数必须是“指针” (传出参数)
4.方法只有一个 error接口类型的返回值。
举例:
type World stuct{
}
func(this *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) Call(serviceMethod string,args 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,其他编程语言不能解析
使用通用的序列化反序列化。 --json,protobuf


修改客户端

修改客户端,使用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,参照上面的 Interface,RegisterName 而来,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++,Java,Python三种语言的API。

Protobuf刚开源是的定位类似于xml,json等数据描述语言,通过附带工具生成代码并实现将结构化数据序列化的功能,这里我们更关注的是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语言插件
在这里插入图片描述

感谢大家观看,我们下次见







推荐阅读
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • ejava,刘聪dejava
    本文目录一览:1、什么是Java?2、java ... [详细]
  • 云原生的十大开源项目是什么
    这篇“云原生的十大开源项目是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • SpringBoot整合SpringSecurity+JWT实现单点登录
    SpringBoot整合SpringSecurity+JWT实现单点登录,Go语言社区,Golang程序员人脉社 ... [详细]
  • 解决Sharepoint 2013运行状况分析出现的“一个或多个服务器未响应”问题的方法
    本文介绍了解决Sharepoint 2013运行状况分析中出现的“一个或多个服务器未响应”问题的方法。对于有高要求的客户来说,系统检测问题的存在是不可接受的。文章详细描述了解决该问题的步骤,包括删除服务器、处理分布式缓存留下的记录以及使用代码等方法。同时还提供了相关关键词和错误提示信息,以帮助读者更好地理解和解决该问题。 ... [详细]
  • Sleuth+zipkin链路追踪SpringCloud微服务的解决方案
    在庞大的微服务群中,随着业务扩展,微服务个数增多,系统调用链路复杂化。Sleuth+zipkin是解决SpringCloud微服务定位和追踪的方案。通过TraceId将不同服务调用的日志串联起来,实现请求链路跟踪。通过Feign调用和Request传递TraceId,将整个调用链路的服务日志归组合并,提供定位和追踪的功能。 ... [详细]
  • 基于分布式锁的防止重复请求解决方案
    一、前言关于重复请求,指的是我们服务端接收到很短的时间内的多个相同内容的重复请求。而这样的重复请求如果是幂等的(每次请求的结果都相同,如查 ... [详细]
  • 知识图谱表示概念:知识图谱是由一些相互连接的实体和他们的属性构成的。换句话说,知识图谱是由一条条知识组成,每条知识表示为一个SPO三元组(Subject-Predicate-Obj ... [详细]
author-avatar
与爱情无关于寂寞有染_973
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有