动手实现一个简单的 rpc 框架到入门 grpc (上)
rpc 全称 Remote Procedure Call
远程过程调用,即调用远程方法。我们调用当前进程中的方法时很简单,但是想要调用不同进程,甚至不同主机、不同语言中的方法时就需要借助 rpc 来实现,下面我一步步实现一个简单的 rpc 调用。
server 端注册函数,运行并接收客户端请求
func main() {
srv := NewServer()
srv.Register("fn", fn)
srv.Run()
}
//为了简单,这里只需要接收到消息打印出就代表执行成功
func fn(args ...interface{}) {
fmt.println(args)
}
定义请求格式
type rpcData struct {
Name string //函数名
Args []interface{} //参数
}
server 运行起来后,接收 socket 请求,解析消息调用已注册的函数
//server结构体
type server struct {
conn net.Conn //socket连接
maps map[string]reflect.Value //函数字典
}
//构造函数
func NewServer() *server {
return &server{
maps: make(map[string]reflect.Value),
}
}
//注册函数
func (s *server) Register(fname string, fun interface{}) {
if _, ok := s.maps[fname]; !ok {
s.maps[fname] = reflect.ValueOf(fun)
}
}
//运行一个socket接收请求
func (s *server) Run() {
listen, err := net.Listen("tcp4", ":3001")
if err != nil {
panic(err)
}
for {
s.conn, err = listen.Accept()
if err != nil {
continue
}
go s.handleConnect()
}
}
处理请求时,这里为了简单我使用 json 解析,同时需要定义一个简单的协议:客户端发送时,前4个字节放置消息长度,这样服务端接收到时就能知道消息的长度,从而正常解码消息
func (s *server) handleConnect() {
for {
header := make([]byte, 4)
if _, err := s.conn.Read(header); err != nil {
continue
}
bodyLen := binary.BigEndian.Uint32(header)
body := make([]byte, int(bodyLen))
if _, err := s.conn.Read(body); err != nil {
continue
}
var req rpcData
if err := json.Unmarshal(body, &req); err != nil {
continue
}
inArgs := make([]reflect.Value, len(req.Args))
for i := range req.Args {
inArgs[i] = reflect.ValueOf(req.Args[i])
}
fn := s.maps[req.Name]
fn.Call(inArgs)
}
}
client 端只需调用函数,通过网络发送请求
func main() {
var req = rpcData{"fn", []interface{}{1, "aaa"}}
rpcCall(req)
}
func rpcCall(data rpcData) {
conn, err := net.Dial("tcp4", "127.0.0.1:3001")
if err != nil {
panic(err)
}
req, err := json.Marshal(data)
if err != nil {
panic(err)
}
buf := make([]byte, 4+len(req))
binary.BigEndian.PutUint32(buf[:4], uint32(len(req)))
copy(buf[4:], req)
_, err = conn.Write(buf)
if err != nil {
panic(err)
}
}
测试时,首先运行 server,然后运行 client,只要看到正确的打印就代表调用成功,这就是一个最简单(简陋)的 rpc 了。
当我们使用 grpc 这些 rpc 框架时,就可以不用自己实现消息编码解码、socket连接这些细节,专注于业务逻辑,而且更为可靠。
动手实现一个简单的 rpc 框架到入门 grpc (上)的更多相关文章
- 动手实现一个简单的 rpc 框架到入门 grpc (下)
之前手动实现了一次简陋的 rpc 调用,为了简单使用了 json 编码信息,其实这是非常不可靠的,go 中 json 解析会有一些问题,比如整数会变成浮点数,而且 json 字符串比较占空间. gRP ...
- 徒手撸一个简单的RPC框架
来源:https://juejin.im/post/5c4481a4f265da613438aec3 之前在牛逼哄哄的 RPC 框架,底层到底什么原理得知了RPC(远程过程调用)简单来说就是调用远程的 ...
- 动手写一个简单的Web框架(模板渲染)
动手写一个简单的Web框架(模板渲染) 在百度上搜索jinja2,显示的大部分内容都是jinja2的渲染语法,这个不是Web框架需要做的事,最终,居然在Werkzeug的官方文档里找到模板渲染的代码. ...
- 动手写一个简单的Web框架(Werkzeug路由问题)
动手写一个简单的Web框架(Werkzeug路由问题) 继承上一篇博客,实现了HelloWorld,但是这并不是一个Web框架,只是自己手写的一个程序,别人是无法通过自己定义路由和返回文本,来使用的, ...
- 动手写一个简单的Web框架(HelloWorld的实现)
动手写一个简单的Web框架(HelloWorld的实现) 关于python的wsgi问题可以看这篇博客 我就不具体阐述了,简单来说,wsgi标准需要我们提供一个可以被调用的python程序,可以实函数 ...
- 自己动手写一个简单的MVC框架(第一版)
一.MVC概念回顾 路由(Route).控制器(Controller).行为(Action).模型(Model).视图(View) 用一句简单地话来描述以上关键点: 路由(Route)就相当于一个公司 ...
- 一个简单的"RPC框架"代码分析
0,服务接口定义---Echo.java /* * 定义了服务器提供的服务类型 */ public interface Echo { public String echo(String string) ...
- 自己动手写一个简单的MVC框架(第二版)
一.ASP.NET MVC核心机制回顾 在ASP.NET MVC中,最核心的当属“路由系统”,而路由系统的核心则源于一个强大的System.Web.Routing.dll组件. 在这个System.W ...
- 一个简单的RPC框架
一个 系统模型 二.数据库代码实现 1. mkdir database cd database vim dbInit.c /* * * Database Init tool * */ #include ...
随机推荐
- CentOS 6.X 双网卡绑定配置
相关环境 主机:Dell PowerEdge R720服务器(背板有4个GE网口) 操作系统:CentOS(RHEL)6.X 网线连接 使用6类网线 将Dell R720 GE网口 0,与交换机A相连 ...
- Tomcat/ WebSphere/WebLogic的作用和特点
作用: Tomcat:目前应用非常广泛的免费web服务器,支持部分j2ee. WebSphere:是IBM集成软件平台.可做web服务器,WebSphere提供了可靠.灵活和健壮的集成软件. Webl ...
- SSM-maven 简单整合
记一次简单的整合了一次SSM框架过程,因为好久不用了在过程中发生了一些问题. 后续我会在继续在此基础上整合其他框架进来. 本次整合用到的框架有: spring & springmvc myba ...
- @RequestMAPPPING映射请求占位符@PathVariable注解
@PathVariable:通过@PathVariable 可以将URL 中占位符参数绑定到控制器处理方法的入参中 URL中的{xxx} 占位符可以通过 @PathVariable{"xxx ...
- Python流程控制语句详解
1.程序结构 计算机在解决问题时,分别是顺序执行所有语句.选择执行部分语句.循环执行部分语句,分别是:顺序结构.选择结构.循环结构.如下图: 2.选择语句 2.1最简单的if语句 Python使用保留 ...
- Java 异常处理的十个建议
前言 Java异常处理的十个建议,希望对大家有帮助~ 本文已上传github: https://github.com/whx123/JavaHome 公众号:捡田螺的小男孩 一.尽量不要使用e.pri ...
- 2019-02-13 思考:1000瓶药水,1瓶有毒,老鼠毒发24h,如何用最少的老鼠在24h内找出毒药?
题目: 现在有1000瓶药水,其中一瓶有毒,一只老鼠喝了在24h后会准时死亡,药水无色无味,如何用最少的老鼠在24h内找出毒药? 分析: 时间限制为24h,说明我们只有一次喂老鼠的机会,需要一波找出来 ...
- jmeter组件中 测试计划,线程组,sampler等等
[测试计划] 这边用户定义的变量,定义整个测试中使用的重复值(全局变量),一般定义服务器的ip,端口号 [线程组] 关于,线程组,我简单聊聊,有不对的地方欢迎大家拨乱反正 线程数:你需要运行的线程 比 ...
- 2020 最新 Kubernetes实战指南
1.Kubernetes带来的变革 对于开发人员 由于公司业务多,开发环境.测试环境.预生产环境和生产环境都是隔离的,而且除了生产环境,为了节省成本,其他环境可能是没有日志收集的,在没有用k8s的 ...
- Windows7/10实现ICMP(ping命令)
如果觉得本文如果帮到你或者你想转载都可以,只需要标注出处即可.谢谢 利用ICMP数据包.C语言实现Ping命令程序,能实现基本的Ping操作,发送ICMP回显请求报文,用于测试—个主机到只一个主机之间 ...