Golang微服务基础技术

news2024/11/19 22:51:30

单体式和微服务

单体式架构服务

------过往大家熟悉的服务器
特性:
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{

}
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语言插件
在这里插入图片描述

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/191477.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

“深度学习”学习日记。卷积神经网络--整体结构

2023.2.1 一、全连接层神经网络: 之前学习的神经网络称为 全连接神经网络 ( Fully-Connected),它的特点就是相邻层所有的神经元都有联接,通过Affine层实现全连接层。 在全连接层神经网络中,Affine层后面…

【ROS-Navigation】—— DWA路径规划算法解析

文章目录前言1. 涉及的核心配置文件与启动文件1.1 demo01_gazebo.launch1.2 nav06_path.launch1.3 nav04_amcl.launch1.4 nav05_path.launch1.5 move_base_params.yaml1.6 dwa_local_planner_params.yaml2. 调参时的一些经验与心得2.1 DWA算法流程2.2 对costmap的参数进行调整2…

1. Mybatis基础

文章目录1. Mybatis 简介2. Mybatis 快速入门3. 使用 idea 写 SQL4. Mapper 代理开发5. MyBatis 核心配置文件1. Mybatis 简介 MyBatis 是一款优秀的持久层框架,用于简化 JDBC 开发。 官方文档:https://mybatis.org/mybatis-3/zh/index.html 持久层&am…

GoogLeNet——网络实战

文章目录摘要🐇1 项目结构🐇2 划分训练集和测试集🐇3 计算mean和Standard🐇3.1 标准化的作用🐇3.2 归一化的作用🐇4 训练🐇4.1 导入项目使用的库🐇4.2 设置随机因子🐇4.3…

Java单例模式演示与理解

目录单例模式1、饿汉式2、懒汉式3、DSL懒汉式(双重锁懒汉模式)静态内部类懒汉式单例模式的如何破坏4、使用枚举类单例模式 为什么使用单例模式? 单例模式确保一个类在内存中只会有同一个实例对象存在。不管声明获取实例对象多少次都是内存中…

2023年网络安全八大预测!

随着创新技术的不断兴起,以及网络犯罪的日益专业化,网络安全攻击风险仍在持续增长。可以预见,2023年的网络安全形势依然严峻,需要国家不断完善网络安全政策和法规,网络安全企业积极创新网络安全防护技术。瑞数信息作为…

Allegro如何导出和导入器件模型Signal_Model操作指导

Allegro如何导出和导入器件模型Signal_Model操作指导 在用Allegro做PCB设计的时候,通常需要给器件加上Signal_Model,在做等长的时候用到的非常频繁。 Allegro除了可以给器件添加模型,还支持从一块加好模型的BRD导入到另外一块BRD中, 如下图,需要把R7002的Signal_Model导入…

剪报浏览器:可以自己设计网页的浏览器

总的功能就是一句话“不同网站的精华内容裁剪下来,合并到一处浏览”把自己关注的网页版块从不同网站上裁剪下来放在一个页面里,一次刷新就可以看到不同网站的最新内容,而不用逐个打开网站去看,提高了上网的效率。关键特征汇聚浏览…

排序算法(带动图)

0、算法概述0.1 算法分类十种常见排序算法可以分为两大类:比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。非比较类排序:不通过比较来决定元素间的相对…

【数据结构初阶】第七篇——二叉树的顺序结构及实现(堆的向下,向上调整算法)

二叉树的顺序结构 堆的概念及结构 堆的向下调整算法 堆的向上调整算法 堆的实现 初始化堆 销毁堆 打印堆 堆的插入 堆的删除 获取堆顶的数据 获取堆的数据个数 堆的判空 建堆的时间复杂度 二叉树的顺序结构 普通二叉树是不适合用数组来存储的,因为可能会导致大量…

为nginx配置好看的错误提示页面

前言 nginx默认错误页面确实有些丑哈,leeader让我换一个样式 ,我就来喽! 为nginx配置好看的错误提示页面前言1 找异常页原始页2 win上替换3 再linux服务器上替换4 不生效解决办法样式显示不正确6 错误页源码1 找异常页 原始页 nginx默认错误…

2个月快速通过PMP证书的经验

01 PMP证书是什么? 指的是项目管理专业人士资格认证。它是由美国项目管理协会(Project Management Institute(简称PMI))发起的,严格评估项目管理人员知识技能是否具有高品质的资格认证考试。其目的是为了给项目管理人员提供统一的…

初学者的Metasploit教程 - 从基础到高级

Metasploit是使用最广泛的渗透测试工具之一,是一个非常强大的多合一工具,用于执行渗透测试的不同步骤。 文章目录前言安装Metasploit在 Linux 上安装 Metasploit了解 Metasploit 的版本并更新渗透测试的基础知识1. 信息收集/侦察2. 漏洞分析3.渗透4. 渗透…

OSCP_VULHUB_Hack the Kioptrix Level-1.2

文章目录前言渗透方法论(方法一)渗透方法论(方法二)第一种sqlmap扫描&提取数据库和用户凭证ssh登录使用 SUID 位和 SUDO 二进制文件利用目标第二种方法searchsploit LotusCMS前言 Kioptrix 的 CTF 挑战:Level1.2 …

Linux搭建Hyperledger Fabric区块链框架 - Hyperledger Fabric 概念

企业选型的区块链底层技术 Hyperledger Fabric 概念 2015年,Linux基金会启动了Hyperledger项目,目标是发展跨行业的区块链技术。 Hyperledger Fabric是Hyperledger中的一个区块链项目,包含一个账本,使用智能合约并且是一个通过所…

上海亚商投顾:三大指数均涨约1% 两市近4300股飘红

上海亚商投顾前言:无惧大盘涨跌,解密龙虎榜资金,跟踪一线游资和机构资金动向,识别短期热点和强势个股。市场情绪三大指数早盘冲高回落,午后又震荡走强,深成指、创业板指均涨超1.2%。人工智能概念掀涨停潮&a…

Pytorch实战笔记(3)——BERT实现情感分析

本文展示的是使用 Pytorch 构建一个 BERT 来实现情感分析。本文的架构是第一章详细介绍 BERT,其中包括 Self-attention,Transformer 的 Encoder,BERT 的输入与输出,以及 BERT 的预训练和微调方式;第二章是核心代码部分…

机器视觉_HALCON_HDevelop用户指南_4.HDevelop开发程序

文章目录四、HDevelop编程4.1. 新建一个新程序4.2. 输入一个算子4.3. 指定参数4.4. 获取帮助4.5. 添加其他程序4.6. 理解图像显示4.7. 检查变量4.8. 利用灰度直方图改进阈值4.9. 编辑代码行4.10. 重新执行程序4.11. 保存程序4.12. 选择特征区域4.13. 打开图形窗口4.14. 循环遍历…

Swig工具在win10上使用

SWIG 是一种软件开发工具,它将 C 和 C 编写的程序与各种高级编程语言连接起来。这里我们用它来将 C/C 转换成 Java。 一、Swig安装 1、下载 官网:SWIG官网下载 源码链接 GitHub:https://github.com/swig/swig.git 这两个地址可能会出现无…

STM32单片机智能蓝牙APP加油站火灾预警安防防控报警监控系统MQ2DHT11

实践制作DIY- GC0122-智能蓝牙APP加油站火灾预警 一、功能说明: 基于STM32单片机设计-智能蓝牙APP加油站火灾预警 功能介绍: 基于STM32F103C系列最小系统,MQ-2烟雾传感器,火焰传感器(不能直视阳光会受到阳光干扰&…