当前位置: 首页 > 科技观察

教你用Golang玩转Rpc

时间:2023-03-21 20:45:18 科技观察

简介“微服务”的概念想必大家都知道,即??使你没有接触过。简单来说,在以前的系统中,用户、搜索、内容等模块都放在一起,会导致代码“越来越冗余,越来越难维护”。因此,往往需要对这些服务进行拆分,微服务在拆分时,会将单个应用按照业务功能模块拆分成多个独立的项目,每个项目完成一部分业务功能,然后独立开发部署.这些独立的项目成为微服务。进而形成“服务集群”。看下面两张图可能对微服务的概念更直观。单体服务单体服务微服务微服务RPC简介微服务中很重要的一个部分就是“RPC”远程过程调用(RemoteProcedureCall,简称RPC)是一种计算机通信协议。一个运行在一台计算机上的程序调用另一台计算机上的一个子程序,不需要程序员为这种交互额外编程。”那么RPC是如何实现的呢?今天我们就以golang为工具,为大家实现一个简单的rpc输出helloWorld。RPC实现步骤其实RPC的实现有点像网络编程,A服务需要远程调用B服务的一个方法,此时我们称B服务为“server”,A称为“client”。。具体实现步骤如下:RPC实现步骤server1.注册服务对象,绑定类方法rpc.ResisterName("servicename","callbackobject")ResisterName函数解释funcRegisterName(namestring,rcvrinterface{})error//参数说明//name服务名(自己选),字符串类型//rcvr对应的RPC对象,绑定到这个对象的方法需要满足以下条件1)方法必须是exported(在packag外可见e)、在golang中,方法名首字母大写2)方法必须有两个参数,都是导出类型和内置类型3)方法的第二个参数(即传出参数在调用远程函数的客户端中),必须是一个指针(传出参数)4)该方法只有一个返回值,为错误接口类型的返回值。让我们举一个参数2的例子。例如,下面的方法TestMethod是符合条件的。typeTeststruct{}//这是匹配RegisterName的参数2的方法名func(this*Test)TestMethod(namestring,resp*string)error{returnnil}rpc.RegisterName("test",new(Test))//注册rpc服务对象2.创建监听listener,err:=net.Listen()3.开始监听并建立链接conn,err:=listener.Accept()4.将链接绑定到rpc服务rpc.ServerConn(conn)ServerConn函数解释func(server*Server)ServeConn(connio.ReadWriteCloser)//参数conn为成功建立连接的socket,也就是之前的connclient1.使用RPC连接服务器(server)conn,err:=rpc.Dail()2.调用远程函数conn.Call("服务名.方法名","传入参数","传出参数")func(client*Client)Call(serviceMethodstring,argsinterface{},replyinterface{})error//参数含义//serviceMethod"服务名"."方法名"//args"传入参数"调用方法所需的参数//reply"OutgoingParameters"定义一个变量,变量名取地址&变量,完成传参代码示例服务器代码server.go:packagemainimport("fmt""net""net/rpc")typeHellostruct{}func(this*Hello)HelloWorld(namestring,resp*string)(errerror){*resp=name+"Hello!"}returnerr}funcmain(){//注册rpc服务,指定对象和方法err:=rpc.RegisterName("hello",new(Hello))iferr!=nil{fmt.Println("registererr:",err)return}//设置监听器,err:=net.Listen("tcp","127.0.0.1:8088")iferr!=nil{fmt.Println("listenerr:",err)return}deferlistener.Close()//建立连接conn,err:=listener.Accept()iferr!=nil{fmt.Println("accepterr:",err)return}deferconn.Close()//绑定服务rpc.ServeConn(conn)}客户端代码client.go:packagemainimport("fmt""net/rpc")funcmain(){//使用rpc连接serverconn,err:=rpc.Dial("tcp","127.0.0.1:8088")iferr!=nil{fmt.Println("Dialerr:",err)return}deferconn.Close()varresp*stringconn.Call("hello.HelloWorld","小凡",&resp)fmt.Println(*resp)}