当前位置: 首页 > news >正文

广州站在哪个区找人做网站价格

广州站在哪个区,找人做网站价格,沈阳男科医院去哪里,厦门建网站哪家好RPC#xff08;Remote Procedure Call#xff09;远程过程调用#xff0c;简单的理解是一个节点请求另一个节点提供的服务#xff0c;对应rpc的是本地过程调用#xff0c;函数调用是最常用的本地过程调用#xff0c;将本地过程调用变成远程调用会面临着各种问题。 以两数…RPCRemote Procedure Call远程过程调用简单的理解是一个节点请求另一个节点提供的服务对应rpc的是本地过程调用函数调用是最常用的本地过程调用将本地过程调用变成远程调用会面临着各种问题。 以两数相加为例 package mainimport fmtfunc add(a, b int) int {return a b } func main() {fmt.Println(add(1, 2)) } 函数调用过程 1将1和2压入函数的栈中 2进入add函数从栈中取出1和2分别赋值给a和b 3执行ab将结果压栈 4将栈中的结果取出打印 远程过程面临的问题 1.原本的本地函数放到另外一个服务器上去运行但是引入了很多新问题 2.Call的id映射 我们怎么告诉远程机器我们要调用add而不是sub或者Foo呢在本地调用中函数体是直接通过函数指针来指定的我们调用add编译器就自动帮我们调用它相应的函数指针。但是在远程调用中函数指针是不行的因为两个进程的地址空间是完全不一样的。所以在RPC中所有的函数都必须有自己的一个ID。这个ID在所有进程中都是唯一确定的。客户端在做远程过程调用时必须附上这个ID。然后我们还需要在客户端和服务端分别维护一个函数–Call ID的对应表。两者的表不一定需要完全相同但相同的函数对应的Call ID必须相同。当客户端需要进行远程调用时它就查一下这个表找出相应的Call ID然后把它传给服务端服务端也通过查表来确定客户端需要调用的函数然后执行相应函数的代码。 3.序列化和反序列化 客户端怎么把参数值传给远程的函数呢在本地调用中我们只需要把参数压到栈里然后让函数自己去栈里读就行。但是在远程过程调用时客户端跟服务端是不同的进程不能通过内存来传递参数。甚至有时候客户端和服务端使用的都不是同一种语言比如服务端用C客户端用Java或者Python。这时候就需要客户端把参数先转成一个字节流传给服务端后再把字节流转成自己能读取的格式。这个过程叫序列化和反序列化。同理从服务端返回的值也需要序列化反序列化的过程。 4.网络传输 远程调用往往用在网络上客户端和服务端是通过网络连接的。所有的数据都需要通过网络传输因此就需要有一个网络传输层。网络传输层需要把Call ID和序列化后的参数字节流传给服务端然后再把序列化后的调用结果传给客户端。只要能完成这两者的都可以作为传输层使用。因此他所使用的协议其实是不限的能完成传输就行尽管大部分RPC框架都使用TCP协议但其实UDP也可以而RPC干脆就用了HTTP2。Java的Netty也属于这层的东西。 RPC第一个要点数据编码协议 一般采用将数据传输到gingin传输到服务端服务端负责解析数据 客户端流程 1.建立连接tcp/http2.将employee对象序列化成json字符串-序列化3.发送json字符串-调用成功后实际上你接受到的是一个二进制的数据4.等待服务器发送结果5将服务返回的数据解析成PrintResult对象-反序列化服务端流程 1.监听网络接口802.读取数据-二进制的json数据3.对数据进行反序列化Employee对象4.开始处理业务逻辑5.将处理的结果PrintReuslt发序列化成json二进制数据-序列化6.将数据返回序列化和反序列化是可以选择的不一定要采用json、xml、protobuf、msgpack RPC第二个要点传输协议 http协议http1.x http2.0协议 http协议底层使用的也是tcphttp现在主流的是http1.x这种协议有性能问题一次性一旦结果返回连接就断开。我们可以直接基于tcp/udp协议去封装一层协议myhttp没有通用型http2.0既有http的特性也有长连接的特性grpc就是基于http2.0的 http协议是文本协议http底层的传输协议是tcp。grpc基于http2.0传输协议也是tcp http协议具有一次性的问题一旦对方返回了结果连接断开http2.0通过长连接解决了这个问题。 基于Http Server实现rpc请求 server端 package mainimport (encoding/jsonfmtnet/httpstrconv )func add(a, b int) int {return a b }func main() {//get方法http://127.0.0.1:8000/add?a1b2或http://127.0.0.1:8000?methodadda1b2//返回的格式化json{data:3}//1、callId的问题r.URL.Path2、数据的传输协议url的参数传输协议3、网络传输协议httphttp.HandleFunc(/add, func(w http.ResponseWriter, r *http.Request) {err : r.ParseForm() //解析参数if err ! nil {panic(error)}fmt.Println(path:, r.URL.Path)a, err : strconv.Atoi(r.Form[a][0])if err ! nil {panic(transform error)}b, err : strconv.Atoi(r.Form[b][0])if err ! nil {panic(transform error)}w.Header().Set(Content-Type, application/json)jData, err : json.Marshal(map[string]int{data: a b,})w.Write(jData)})_ http.ListenAndServe(:8000, nil) } 缺点http1.x麻烦性能不高 客户端 package mainimport (encoding/jsonfmttimegithub.com/kirinlabs/HttpRequest )type ResponseData struct {Data int json:data }func Add(a, b int) int {req : HttpRequest.NewRequest()res, _ : req.Get(fmt.Sprintf(http://127.0.0.1:8000/%s?a%db%d, add, a, b))body, _ : res.Body()rspData : ResponseData{}_ json.Unmarshal(body, rspData)return rspData.Data } func main() {fmt.Println(Add(2, 2)) }这里遇到了一个Get “http://127.0.0.1:8000/add?a1b2”: context deadline exceeded (Client.Timeout exceeded while awaiting headers)的问题主要是客户端默认网络请求时间太短 修改之后 package mainimport (encoding/jsonfmttimegithub.com/kirinlabs/HttpRequest )type ResponseData struct {Data int json:data }func Add(a, b int) int {req : HttpRequest.NewRequest()req.SetTimeout(10 * time.Second)res, _ : req.Get(fmt.Sprintf(http://127.0.0.1:8000/%s?a%db%d, add, a, b))body, _ : res.Body()rspData : ResponseData{}_ json.Unmarshal(body, rspData)return rspData.Data } func main() {fmt.Println(Add(2, 2)) }rpc开发的要素分析 RPC技术在架构设计上有四部分组成分别是客户端、客户端存根、服务端、服务端存根。 客户端(Client)服务调用发起方也称为服务消费者。 客户端存根(Client Stub)该程序运行在客户端所在的计算机机器上主要用来存储要调用的服务器的地址另外该程序还负责将客户端请求远端服务器程序的数据信息打包成数据包通过网络发送给服务端Stub程序其次还要接收服务端Stub程序发送的调用结果数据包并解析返回给客户端。 服务端(Server):远端的计算机机器上运行的程序其中有客户端要调用的方法。 服务端存根(Server Stub)接收客户Stub程序通过网络发送的请求消息数据包并调用服务端中真正的程序功能方法完成功能调用其次将服务端执行调用的结果进行数据处理打包发送给客户端Stub程序。 rpc需要使用到的术语 1、动态代理技术 上文中我们提到的Client Stub和Sever Stub程序在具体的编码和开发实践过程中都是使用动态代理技术自动生成的一段程序。 序列化和反序列化 在RPC调用的过程中我们可以看到数据需要在一台机器上传输到另外一台机器上。在互联网上所有的数据都是以字节的形式进行传输的。而我们在编程的过程中往往都是使用数据对象因此想要在网络上将数据对象和相关变量进行传输就需要对数据对象做序列化和反序列化的操作。 序列化把对象转换为字节序列的过程称为对象的序列化也就是编码的过程。 反序列化把字节序列恢复为对象的过程称为对象的反序列化也就是解码的过程。 我们常见的Json,XML等相关框架都可以对数据做序列化和反序列化编解码操作。后面我们要学习的Protobuf协议这也是一种数据编解码的协议在RPC框架中使用的更广泛。 简单的rpc实例 服务端 package mainimport (netnet/rpc )type HelloService struct { }func (s *HelloService) Hello(request string, reply *string) error {//返回值是通过修改reply的值*reply hello, requestreturn nil } func main() {//rpc快速开发体验//1.实例化一个serverlistener, _ : net.Listen(tcp, :1234)//2.注册处理逻辑_ rpc.RegisterName(HelloService, HelloService{})//3.启动服务conn, _ : listener.Accept() //当一个新的连接进来的时候rpc.ServeConn(conn) } 客户端 package mainimport (encoding/jsonfmtnet/rpctime )func main() {//1.建立连接client, err : rpc.Dial(tcp, localhost:1234)if err ! nil {panic(连接失败)}var reply *string new(string)err client.Call(HelloService.Hello, bobby, reply)if err ! nil {panic(调用失败)}fmt.Println(*reply) } 替换rpc的序列化协议为json 序列化协议为json各种语言都可以调用服务端的内容 服务端 package mainimport (netnet/rpcnet/rpc/jsonrpc )type HelloService struct { }func (s *HelloService) Hello(request string, reply *string) error {//返回值是通过修改reply的值*reply hello, requestreturn nil } func main() {//替换rpc的序列化协议为json//1.实例化一个serverlistener, _ : net.Listen(tcp, :1234)//2.注册处理逻辑_ rpc.RegisterName(HelloService, HelloService{})//3.启动服务conn, _ : listener.Accept() //当一个新的连接进来的时候rpc.ServeCodec(jsonrpc.NewServerCodec(conn))} 客户端 package mainimport (encoding/jsonfmtnetnet/rpcnet/rpc/jsonrpctimegithub.com/kirinlabs/HttpRequest )func main() {//替换rpc的序列化协议为json//1.建立连接conn, err : net.Dial(tcp, localhost:1234)if err ! nil {panic(连接失败)}var reply *string new(string)client : rpc.NewClientWithCodec(jsonrpc.NewClientCodec(conn))err client.Call(HelloService.Hello, bobby, reply)if err ! nil {panic(调用失败)}fmt.Println(*reply) } python连接rpc序列化协议为json 服务端 package mainimport (netnet/rpcnet/rpc/jsonrpc )type HelloService struct { }func (s *HelloService) Hello(request string, reply *string) error {//返回值是通过修改reply的值*reply hello, requestreturn nil } func main() {//替换rpc的序列化协议为json//1.实例化一个serverlistener, _ : net.Listen(tcp, :1234)//2.注册处理逻辑_ rpc.RegisterName(HelloService, HelloService{})//3.启动服务conn, _ : listener.Accept() //当一个新的连接进来的时候rpc.ServeCodec(jsonrpc.NewServerCodec(conn))} 客户端 import json import socket request{id:0,params:[bobby],method:HelloService.Hello } clientsocket.create_connection((localhost,1234)) client.sendall(json.dumps(request).encode()) #获取服务器返回的数据 rspclient.recv(4096) rspjson.loads(rsp.decode()) print(rsp)替换rpc的传输协议为http 服务端 package mainimport (ionet/httpnet/rpcnet/rpc/jsonrpc ) type HelloService struct { }func (s *HelloService) Hello(request string, reply *string) error {//返回值是通过修改reply的值*reply hello, requestreturn nil } func main() {//替换rpc的序列化协议为http//2.注册处理逻辑_ rpc.RegisterName(HelloService, HelloService{})http.HandleFunc(/jsonrpc, func(w http.ResponseWriter, r *http.Request) {var conn io.ReadWriteCloser struct {io.Writerio.ReadCloser}{ReadCloser: r.Body,Writer: w,}rpc.ServeRequest(jsonrpc.NewServerCodec(conn))})http.ListenAndServe(:1234, nil) } 客户端 import requests request{id:0,params:[bobby],method:HelloService.Hello } rsprequests.post(http://localhost:1234/jsonrpc,jsonrequest) print(rsp.text)客户端 package mainimport (encoding/jsonfmtnet/rpctimegithub.com/kirinlabs/HttpRequest )func main() {//1.实例化一个client, err : rpc.Dial(tcp, 127.0.0.1:1234)if err ! nil {panic(连接失败)}var reply stringerr client.Call(HelloService.Hello, bobby, reply)if err ! nil {// panic(调用失败)fmt.Println(err)}fmt.Println(reply) } 代理封装 代理类 package handlerimport net/rpcconst HelloServiceName HelloServiceNametype HelloServiceStub struct {*rpc.Client }func NewHelloServiceClient(protcol, address string) HelloServiceStub {conn, err : rpc.Dial(protcol, address)if err ! nil {panic(connect error!)}return HelloServiceStub{conn} } func (c *HelloServiceStub) Hello(request string, reply *string) error {err : c.Call(HelloServiceName.Hello, request, reply)if err ! nil {return err}return nil }type HelloService struct { }func (s *HelloService) Hello(request string, reply *string) error {//返回值是通过修改reply的值*reply hello, requestreturn nil }func RegisterHelloService() error {return rpc.RegisterName(HelloServiceName, HelloService{}) } 服务端 package mainimport (TEMP/handlernetnet/rpc )func main() {//进一步改造rpc调用的代码//1.实例化一个serverlistener, _ : net.Listen(tcp, :1234)//2.注册处理逻辑handler_ handler.RegisterHelloService()//3.启动服务conn, _ : listener.Accept() //当一个新的连接进来的时候rpc.ServeConn(conn)} 客户端 package mainimport (TEMP/handlerfmt )func main() {//进一步改造rpc调用的代码//1.实例化一个client : handler.NewHelloServiceClient(tcp, 127.0.0.1:1234)var reply stringerr : client.Hello(bobby, reply)if err ! nil {// panic(调用失败)fmt.Println(err)}fmt.Println(reply) } 解耦合 将服务端的Hello函数传递变换成接口类型 代理类 package handlerimport net/rpcconst HelloServiceName HelloServiceNametype HelloServiceStub struct {*rpc.Client }func NewHelloServiceClient(protcol, address string) HelloServiceStub {conn, err : rpc.Dial(protcol, address)if err ! nil {panic(connect error!)}return HelloServiceStub{conn} } func (c *HelloServiceStub) Hello(request string, reply *string) error {err : c.Call(HelloServiceName.Hello, request, reply)if err ! nil {return err}return nil }type NewHelloService struct { } type HelloServicer interface {Hello(request string, reply *string) error }func (s *NewHelloService) Hello(request string, reply *string) error {//返回值是通过修改reply的值*reply hello, requestreturn nil }func RegisterHelloService() error {return rpc.RegisterName(HelloServiceName, NewHelloService{}) }服务端 package mainimport (TEMP/handlernetnet/rpc )func main() {//进一步改造rpc调用的代码//1.实例化一个serverlistener, _ : net.Listen(tcp, :1234)//2.注册处理逻辑handler_ handler.RegisterHelloService()//3.启动服务conn, _ : listener.Accept() //当一个新的连接进来的时候rpc.ServeConn(conn)} 客户端 package mainimport (TEMP/handlerfmt )func main() {//进一步改造rpc调用的代码//1.实例化一个client : handler.NewHelloServiceClient(tcp, 127.0.0.1:1234)var reply stringerr : client.Hello(bobby, reply)if err ! nil {// panic(调用失败)fmt.Println(err)}fmt.Println(reply) }
http://www.hkea.cn/news/14371843/

相关文章:

  • 建设银行广西分行网站电子商务毕业设计设计电商网站建设
  • 广州有专做网站logo图片素材大全
  • 济南 网站设计公司网站推广公司经理职责
  • 打车网站开发会做网站开发 但是不会二次开发
  • iis7建网站权重查询入口
  • 赣州城乡建设局网站招商网站建设全包
  • 如何防止网站挂马网站能不能一边用 一边备案
  • 电子商务网站建设主管的策划书网站建设 军报
  • 做网站买虚拟服务器yellow在线观看完整版视频
  • 网页制作门户网站案例net域名网站
  • 学做网站看书会了吗永久域名注册
  • 网站建设 我们的优势系统管理软件下载
  • 正规手表回收网站wordpress 数据备份
  • 网站建设跟pc官网一样吗专注苏州网站优化
  • 主要的网站开发技术路线旅游公共信息服务网站建设及服务质量标准
  • 网站建设互联网营销营销推广南阳网站制作价格
  • 网站SEO建设摘要泉州刚刚发生的重大新闻
  • 一站式装修平台好的网站页面
  • 阿里巴巴网站建设与维护计算机女生就业方向
  • 合作公司做网站需要定位的网站
  • 济南网站优化公司排名wordpress用户设置
  • 南宁百度网站公司the7 wordpress 主题
  • 网站做外链推广的常用方法施工企业安全形势分析会
  • 正规绍兴网站建设公司er图关于网站建设
  • 黄石网站制作黑龙江网站备案查询
  • 如何查一个网站的备案信息sydney wordpress主题
  • 网站流量指数企业网站鉴赏
  • 陕西省交通建设集团公司招聘网站衡阳建设网站公司
  • 成都网站建设与推广网站建设1001网站建设
  • 做网站的一般要多钱中国知名广告公司有哪些