go自带rpc框架生产环境使用demo

基础使用

序列化使用自带gob协议

server

package mainimport ("net""net/rpc"
)// 定义一个handler结构体
type HelloService struct {
}// 定义handler方法,大小写,参数,返回值都是固定的,否则无法注册
func (receiver *HelloService) Hello(req string, rep *string) error {*rep = "hello " + reqreturn nil
}func main() {
//1. 实例化一个serverlisten, _ := net.Listen("tcp", ":8001")//2. 注册handler_ = rpc.RegisterName("HelloService", &HelloService{})// 3. 启动服务for {conn, _ := listen.Accept()go rpc.ServeConn(conn) //避免阻塞}}}

client

package mainimport ("fmt""net/rpc"
)func main() {//1. 建立连接client, _ := rpc.Dial("tcp", "localhost:8001")var data *string = new(string)err := client.Call("HelloService.Hello", "matthew", data)if err != nil {fmt.Println("调用失败")}fmt.Println("success: ", *data)
}

注:两个文件需要在不同包下面

使用json序列化

server

package mainimport ("net""net/rpc""net/rpc/jsonrpc"
)// 定义一个handler结构体
type HelloService struct {
}// 定义handler方法,大小写,参数,返回值都是固定的,否则无法注册
func (receiver *HelloService) Hello(req string, rep *string) error {*rep = "hello " + reqreturn nil
}func main() {jsonserver()
}/*
*
go 默认的序列化反序列化协议是gob
*/
func gobserver() {//1. 实例化一个serverlisten, _ := net.Listen("tcp", ":8001")//2. 注册handler_ = rpc.RegisterName("HelloService", &HelloService{})// 3. 启动服务for {conn, _ := listen.Accept()go rpc.ServeConn(conn) //避免阻塞}
}/*
*
使用json来序列化和反序列化
*/
func jsonserver() {//1. 实例化一个serverlisten, _ := net.Listen("tcp", ":8001")//2. 注册handler_ = rpc.RegisterName("HelloService", &HelloService{})// 3. 启动服务for {conn, _ := listen.Accept()go rpc.ServeCodec(jsonrpc.NewServerCodec(conn)) //避免阻塞}}

client

package mainimport ("fmt""net""net/rpc""net/rpc/jsonrpc"
)func main() {jsonRpcClient()
}func jsonRpcClient() {//1. 建立连接client, _ := net.Dial("tcp", "localhost:8001")var data *string = new(string)codeclient := rpc.NewClientWithCodec(jsonrpc.NewClientCodec(client))err := codeclient.Call("HelloService.Hello", "matthew", data)if err != nil {fmt.Println("调用失败")}fmt.Println("success: ", *data)
}

构建一个规范的rpc项目框架

如果想构建生产环境使用的rpc服务,不但要能实现业务,还要有良好的架构设计

  • client 客户端
    • client_proxy/stub 客户端代理封装
    • handler 句柄封装
  • server 服务端
    • server_proxy/stub 服务端函数封装
    • handler 句柄封装

句柄相当于服务端和客户端互相通信的通道,告诉双方可以提供的方法

在这里插入图片描述

client.go

package mainimport ("fmt""learngo/chw01/nicerpc/client_stub_proxy"
)func main() {stub := client_stub_proxy.NewHelloServiceStub("tcp", "localhost:9001")res := new(string)stub.Hello("matthew", res)fmt.Println(*res)
}

client_stub_proxy

package client_stub_proxyimport ("fmt""learngo/chw01/nicerpc/handler""net/rpc"
)/**
存放客户端proxy或者stub,封装已经注册的服务和方法列表,用于客户端快速调用专注业务
*/type HelloServiceStub struct {*rpc.Client
}// 构造函数返回一个,服务代理并携带客户端
func NewHelloServiceStub(protcol, address string) HelloServiceStub {client, err := rpc.Dial(protcol, address)if err != nil {fmt.Println(err)panic("rpc client start panic")}return HelloServiceStub{client}
}/*
*
封装了HelloService服务的Hello方法
*/
func (cs *HelloServiceStub) Hello(req string, reply *string) error {err := cs.Call(handler.HelloServiceName+".Hello", req, reply)return err
}

hander.go

package handler/*
*
定义所有的handler名称,可以被client,server两端引入对齐
*/
const HelloServiceName = "hander/HelloService"// 定义一个handler结构体
type HelloService struct {
}// 定义handler方法,大小写,参数,返回值都是固定的,否则无法注册
func (receiver *HelloService) Hello(req string, rep *string) error {*rep = "hello " + reqreturn nil
}

server.go

package mainimport ("fmt""learngo/chw01/nicerpc/handler""learngo/chw01/nicerpc/server_proxy_stub""net""net/rpc"
)func main() {var address string = ":9001"//实例化一个serverlisten, err := net.Listen("tcp", address)if err != nil {panic("server start error " + address)}fmt.Println("server start success on address: ", address)//注册方法server_proxy_stub.RegisterHelloServicer(&handler.HelloService{})//启动服务for {conn, err := listen.Accept()if err != nil {fmt.Println("connect error", err)}rpc.ServeConn(conn)}
}

server_proxy_stub

package server_proxy_stubimport ("learngo/chw01/nicerpc/handler""net/rpc"
)/**
封装所有server的方法(业务逻辑)
*//*
*
多态:顶一个HelloServie的接口,凡是实现了该接口方法的struct都继承了接口
*/
type HelloServicer interface {Hello(req string, reply *string) error
}// 当前的方法只能用来HelloService一种结构体,我们关注的不是结构体而是结构体的方法
func RegisterHelloService(srv *handler.HelloService) error {return rpc.RegisterName(handler.HelloServiceName, srv)
}// 对比上面的注册,通过接口来注册更加灵活。所有实现了HelloServicer接口的struct都可以直接使用该方法
func RegisterHelloServicer(srv *handler.HelloService) error {return rpc.RegisterName(handler.HelloServiceName, srv)
}

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

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

相关文章

数据库事务:保障数据一致性的基石

目录 1. 什么是数据库事务? 1.1 ACID特性解析 2. 事务的实现与控制 2.1 事务的开始和结束 2.2 事务的隔离级别 3. 并发控制与事务管理 3.1 并发控制的挑战 3.2 锁和并发控制算法 4. 最佳实践与性能优化 4.1 事务的划分 4.2 批处理操作 5. 事务的未来发展…

SpringSecurity6 | 自定义登录页面

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: Java从入门到精通 ✨特色专栏&#xf…

高工氢电年会 | 未势能源解超朋博士受邀出席并做主题演讲

12月4日,以“战略重构 商业觉醒”为主题的2023高工氢电年会在深圳举办,未势能源副总裁解超朋博士受邀出席开幕式论坛,以《把握机遇、直面挑战,迎接氢车规模化推广时代》为主题发表演讲,并参与圆桌论坛研讨。 氢势已来&…

【Linux】resolv.conf 文件

resolv.conf resolv.conf 文件 是 DNS 的 client 端使用的文件,用于设置 DNS 服务器的 ip 地址以及 DNS 域名,还可以配置域名搜索顺序等等。主要包含如下关键字:nameserver、domain、search、sortlist、options。设置的格式都是 关键字空格 …

管理类联考——数学——真题篇——按知识分类——数据

文章目录 排列组合2023真题(2023-05)-数据分析-排列组合-组合-C运算-至少-需反面思考真题(2023-08)-数据分析-排列组合-相邻不相邻-捆绑法插空法-插空法注意空位比座位多1个,是用A;捆绑法内部排序用A&#…

2023中国(海南)国际高尔夫旅游文化博览会 暨国际商界峰层·全球华人高尔夫精英巡回赛 全国颍商自贸港行盛大启幕

2023中国(海南)国际高尔夫旅游文化博览会(以下简称“海高博”)暨全国颍商走进海南自贸港于12月7-9日在海口观澜湖盛大开幕。该活动由中国国际贸易促进委员会海南省委员会、海南省旅游和文化广电体育厅主办,中国国际商会…

最新版本11.17的YOLOv8加入注意力方法

本文基于11.17版本,以往版本略有不同,可查看改进YOLOv8,教你YOLOv8如何添加20多种注意力机制进行参考 放入注意力代码,以biformer注意力为例 import torch import torch.nn as nn import torch.nn.functional as Fdef position(H, W, is_cuda=

探索 Python 中链表的实现:从基础到高级

# 更多资料获取 📚 个人网站:ipengtao.com 链表是一种基础的数据结构,它由一系列节点组成,每个节点都包含数据和指向下一个节点的引用。在Python中,可以使用类来实现链表,本文将介绍如何实现链表&#xff…

【密码学引论】认证

认证是许多应用系统中安全保护的第一道设防认证和加密的区别:加密用来确保数据的保密性,而认证用来确保报文发送者和接受者的真实性和报文的完整性。认证和数字签名的区别: 认证总是基于某种收发双方共享的保密数据来认证被鉴别对象的真实性&…

关于linux开机自启动

1、系统启动流程 2、 init、 inittab、 init.d、 rcx.d /etc/inittab是Linux系统中的一个配置文件,用于定义系统的运行级别和相应的操作。其语法格式如下: 标签:运行级别:操作:进程 label:runlevel:action:process下面…

PHP基础 - 注释变量

一. 语言开始标识 在PHP中,文件的开头需要使用语言开始标识来指定该文件是PHP代码。标识通常为"<?php",也可以是"<?",但建议使用"<?php"以确保代码的兼容性和可读性。 <?php // PHP代码从这里开始写 二. PHP注释 注释是用…

【Python】Faker库详解:创建测试数据轻而易举

Python Faker库详解&#xff1a;创建测试数据轻而易举 在软件开发和测试过程中&#xff0c;通常需要大量的测试数据来模拟真实环境。Python的Faker库为开发者提供了一个方便、灵活且强大的工具&#xff0c;用于生成各种虚构数据。本文将深入介绍Faker库&#xff0c;演示其基本…

十一、了解分布式计算

1、什么是&#xff08;数据&#xff09;计算&#xff1f; 2、分布式(数据)计算 &#xff08;1&#xff09;概念 顾名思义&#xff0c;分布式计算&#xff0c;即以分布式的形式完成数据的统计&#xff0c;得到需要的结果。 分布式数据计算&#xff0c;顾名思义&#xff0c;就是…

c语言选择排序总结(详解)

选择排序cpp文件项目结构截图 项目cpp文件截图 项目具体代码截图 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <math.h> #include <iostream> #include <string.h> #include <time.h> #include &…

Java发展史

Java发展史 Java历史的几个重要节点&#xff1a; 1990&#xff0c;Sun公司启动了一个名为“绿色计划”的项目&#xff0c;由James Gosling等领导&#xff0c;目标是开发一种可以在机顶盒等消费性电子产品上运行的程序架构。这个计划产生了Java的前身&#xff1a;Oak&#xff…

看图学源码 之 ConcurrentHashMap put、get、remove、clear、扩容等相关方法的源码分析

ConcurrentHashMap 引入 HashMap 的弊端 多线程下是不安全的&#xff0c;是有死循环的 JDK1.7 的时候会使用头插法将新的节点增加到头部&#xff0c;那么就会造成链表翻转成为了闭环&#xff0c;就是所谓的死循环。 JDK1.8之后使用的是尾插法&#xff0c;因此不会造成环形链…

京东数据运营:京东API接口有哪些?京东数据如何采集调用?

市场分析对于电商品牌来说非常重要&#xff0c;它可以帮助电商品牌更好地理解市场&#xff0c;把握市场机会&#xff0c;以及制定有效的产品定价、产品营销策略等等。 结合市场中可以帮助品牌方做市场分析的电商数据分析工具——鲸参谋电商数据分析平台&#xff0c;我们一起具体…

在Mac上安装Windows应用程序的简便方法:CrossOver for Mac

对于许多Mac用户来说&#xff0c;有时候他们可能需要使用一些只有在Windows上才能找到的应用程序。以前&#xff0c;解决这个问题的方法是通过安装Windows虚拟机或使用双系统来在Mac上运行Windows应用程序。但这些方法需要额外的硬件资源和时间来配置&#xff0c;并且可能会导致…

有什么进销存软件能对接微信小程序?

有什么进销存软件能对接微信小程序&#xff1f; 据我所知&#xff0c;很多进销存软件都有配套的微信小程序吧。 以我们现在用的这个为例&#xff0c;这也是同行推荐过来的&#xff0c;很好用&#xff0c;而且性价比很高—— 在线平台&#xff0c;无需下载APP&#xff0c;搭载…

C语言实战演练之跳动的爱心C语言版

跳 动 的 爱 心 - LOVE - 完整程序 #include <stdio.h> #include <math.h> #include <windows.h> #include <tchar.h> float f(float x, float y, float z) {float a x * x 9.0f / 4.0f * y * y z * z - 1;return a * a * a - x * x * z * z …