仿`gRPC`功能实现像调用本地方法一样调用其他服务器方法

文章目录

  • 仿`gRPC`功能实现像调用本地方法一样调用其他服务器方法
    • 简介
        • 单体架构
        • 微服务架构
        • `RPC`
        • `gPRC`
    • `gRPC`交互逻辑
        • 服务端逻辑
        • 客户端逻辑
        • 示例图
    • 原生实现仿`gRPC`框架
        • 编写客户端方法
        • 编写服务端方法
        • 综合演示

仿 gRPC功能实现像调用本地方法一样调用其他服务器方法

简介

在介绍gRPC简介之前我们先了解一写概念:

单体架构

单体架构简单理解就是所有的业务代码都在一台服务器上,一旦某个服务宕机,会引起整个应用不可用,隔离性差。只能整体应用进行伸缩,例如整体打包部署一台或多台服务器,浪费资源,可伸缩性差。代码耦合在一起,可维护性差。

微服务架构

解决了单体架构的弊端。可按需拆成多个服务,例如针对用户的请求非常多,针对支付的请求少,可以将用户业务功能拆为多个服务器,支付业务功能拆为单个服务器。

也有一些弊端,例如代码冗余,同样的代码在多个服务器上都要写,例如接口等。服务与服务之间存在调用关系,服务拆分之后,就是服务和服务之间发生是进程与进程之间的调用,服务器与服务器之间的调用。

这时候就需要发起网络调用, 网络调用一般使用HTTP,但是在微服务架构中,HTTP虽然方便,但性能较低,这时候就需要引入RPC(远程过程调用),通过自定义协议发起TCP调用,来加快传输效率。

RPC

RPC的全称是Remote Procedure Call,远程过程调用。这是一种协议,是用来屏蔽分布式计算中的各种调用细节使得你可以像是本地调用一样直接调用一个远程的函数。

gPRC

gRPC 是一个高性能、开源和通用的RPC 框架,面向移动和 HTTP/2 设计。目前提供 CJavaGo 语言版本,分别是:grpc, grpc-java, grpc-go. 其中 C 版本支持 C, C++, Node.js, Python, Ruby, Objective-C, PHPC# 支持。

中文文档:http://doc.oschina.net/grpc

gRPC中,我们称调用方为client,被调用方为server。跟其他的RPC框架一样,gRPC也是基于服务定义的思想。简单的来讲,就是我们通过某种方式来描述一个服务,这种描述方式是语言无关的。在这个服务定义的过程中,我们描述了我们提供的服务服务名是什么,有哪些方法可以被调用,这些方法有什么样的入参,有什么样的回参。

也就是说,在定义好了这些服务、这些方法之后,gRPC会屏蔽底层的细节,client只需要直接调用定义好的方法,就能拿到预期的返回结果。对于server端来说,还需要实现我们定义的方法。同样的,gRPC也会帮我们屏蔽底层的细节,我们只需要实现所定义的方法的具体逻辑即可。

可以发现,在上面的描述过程中,所谓的服务定义,就跟定义接口的语义是很接近的。我更愿意理解为这是一种"约定”,双方约定好接口,然后server实现这个接口,client调用这个接口的代理对象。到于其他的细节,交给gRPC

gRPC交互逻辑

服务端逻辑

  • 创建gRPC Server对象,可以理解为它是Server端的抽象对象。
  • server(其包含需要被调用的服务端接口)注册到gRPC Server的内部注册中心。
    • 这样可以在接受到请求时,通过内部的服务发现。发现该服务端接口并转接进行逻辑处理。
  • 创建Listen,监听TCP端口。
  • gRPC Server开始lis.Accept,直到Stop

客户端逻辑

  • 创建与给定目标服务端的连接交互。
  • 创建server的客户端对象。
  • 发送RPC请求,等待同步响应,得到回调后返回响应结果。
  • 输出响应结里。

示例图

如下图:业务服务器调用登录业务服务器,支付服务器,库存服务器。

在这里插入图片描述

原生实现仿gRPC框架

因为gRPC框架目前不支持IRIS/Caché,所以这里我们了解gRPC原理后,仿造gRPC框架实现类似的功能。通过正常编写代码无感知的情况下调用其他服务器上的代码方法。

注:为了显示这里使用Caché作为客户端,IRIS作为服务端。

编写客户端方法

  1. 首先在客户端也就是调用端创建客户端类Util.RPC.Client,代码如下:
    • %DispatchClassMethod - 动态派发方法是实现无感知的关键。
    • SERVERIP - 目标服务端的IP地址。
    • PORT - 目标服务端的端口号。
Class Util.RPC.Client Extends %RegisteredObject
{Parameter SERVERIP = "127.0.0.1";Parameter PORT = 7788;ClassMethod %DispatchClassMethod(class As %String, method As %String, args...) [ ServerOnly = 1 ]
{#; 客户端通信、客户端需要设置服务器IP与端口号#dim clientSocket As %IO.Socket = ##class(%IO.Socket).%New()s host = ..#SERVERIPs port = ..#PORTs clientSocket.TranslationTable = "UTF8"d clientSocket.Open(host, port, .sc)s obj = {}	//注释1s obj.class = classs obj.method = methods params = []s i = ""for {s i = $o(args(i))q:(i = "")d params.%Push(args(i))}s obj.params = paramsd clientSocket.WriteLine(obj.%ToJSON())	//注释2while (1) {s data = clientSocket.ReadLine() if (data '= "" ){	//注释3ret data}}q $$$OK
}}
  1. 创建空类M.LoginM.PayM.Stock分别继承Util.RPC.Client
    • 目的是模拟交互接口,因为要调用其他服务器方法,首先要确定要调用的服务器接口名称。

在这里插入图片描述

  1. 按照常规调用方法的模式,来编写方法。

    • 这里实际上是没有LoginPayStock方法的,因为上一步创建的类为空类。

    • 如果按照常规直接调用方法肯定会提示方法不存在的错误,这里实际上我们调用的是服务端的方法。

    • 可以观察到,这里是按照正常调用类方法的方式编写的代码,并没有其他额外的操作。

Class M.RPC Extends %RegisteredObject
{/// d ##class(M.RPC).Biz()
ClassMethod Biz()
{w ##class(M.Login).Login("yx","123456"),!w ##class(M.Pay).Pay(100),!w ##class(M.Stock).Stock(3),!
}}

编写服务端方法

  1. 创建服务端监听Util.RPC.Server类,这里模拟的是gRPC 创建Server对象,创建Listen,监听TCP端口。代码如下:
    • 参数PORT为服务端监听和开启的接口。
Class Util.RPC.Server Extends %RegisteredObject
{Parameter PORT = 7788;/// d ##class(Util.RPC.Server).ServerRPC()
ClassMethod ServerRPC()
{#; 服务端通信、服务端需要打开端口,等待客户端通信#dim severSocket As %IO.ServerSocket = ##class(%IO.ServerSocket).%New()s port = ..#PORTs severSocket.TranslationTable="UTF8"s severSocket.ConnectionQueueSize = 2d severSocket.Open(port, 10, .sc)q:($$$ISERR(sc)) "Open:" _ $System.Status.GetOneErrorText(sc)d severSocket.Listen(10, .sc)q:($$$ISERR(sc)) "Listen:" _ $System.Status.GetOneErrorText(sc)while (1) {s data =  severSocket.ReadLine()if (data '= "") {s obj = {}.%FromJSON(data)	//注释1s arg = obj.params.%Size()for i = 1 : 1 : arg{s arg(i) = obj.params.%Get(i - 1)}s ret = $classmethod(obj.class, obj.method, arg...)	//注释2d severSocket.WriteLine(ret)	//注释3}}q $$$OK
}}
  1. 编写服务端M.LoginLogin方法,M.PayPay方法,M.StockStock方法。

    • 这里使用IRIS当服务端,实现的方法都在服务端,客户端是没有该方法的。

    • 客户端调用的方法实际上是服务端的上的方法。

在这里插入图片描述

综合演示

  1. IRIS服务端开启监听方法。

  2. 客户端Caché调用无感知业务逻辑业务员Biz()方法。

    • 可观察到客户端直接调用到了服务端的方法,并且编码方式跟正常编写代码并无差别。

    • 客户端不需要了解底层的细节,client只需要直接调用定义好的方法。

在这里插入图片描述

通过这种方式我们就实现了类似gRPC的功能,像正常编写代码一样调用服务端的程序。

创造价值,分享学习,一起成长,相伴前行,欢迎大家提出意见,共同交流。

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

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

相关文章

【OpenCV入门】第五部分——图像运算

文章结构 掩模图像的加法运算图像的位运算按位与运算按位或运算按位取反运算按位异或运算图像位运算的运用 合并图像加权和覆盖 掩模 当计算机处理图像时,有些内容需要处理,有些内容不需要处理。能够覆盖原始图像,仅暴露原始图像“感兴趣区域…

Myvatis关联关系映射与表对象之间的关系

目录 一、关联关系映射 1.1 一对一 1.2 一对多 1.3 多对多 二、处理关联关系的方式 2.1 嵌套查询 2.2 嵌套结果 三、一对一关联映射 3.1 建表 ​编辑 3.2 配置文件 3.3 代码生成 3.4 编写测试 四、一对多关联映射 五、多对多关联映射 六、小结 一、关联关系映射 …

一文学会K8s集群搭建

环境准备 节点数量:2台虚拟机 centos7硬件配置:master节点内存至少3G(2G后面在master节点初始化集群时会报错,内存不够),node节点可以2G,CPU至少2个,硬盘至少30G网络要求&#xff1…

Ant-Design-Pro-V5: ProTable前端导出excel表格。

Prtable表格中根据搜索条件实现excel表格导出。 代码展示: index.jsx import React, { useRef, useState, Fragment, useEffect } from react; import { getLecturerList, lecturerExportExcel } from /services/train/personnel; import { getOrgList, getSelec…

Navicat Premium 16.2.7 for Mac

Navicat Premium 16是一款功能强大的跨平台数据库管理工具,支持多种数据库类型,如MySQL、MariaDB、Oracle、SQLite、PostgreSQL等等。它提供了丰富的数据库管理功能和工具,可以帮助开发人员和数据库管理员快速地创建、管理和维护数据库。 Nav…

stable diffusion实践操作-大模型介绍

本文专门开一节写大模型相关的内容,在看之前,可以同步关注: stable diffusion实践操作 模型下载网站 国内的是:https://www.liblibai.com 国外的是:https://civitai.com(科学上网) 一、发展历…

自动化驱动程序管理

在部署操作系统时,每次都从下载和分发所需的驱动程序中实现真正的独立性可能是一场艰苦的战斗。特别是具有硬件多样化的环境,并且需要支持新的硬件类型时。借助 OS Deployer,可以对所有端点使用一个映像,无论品牌和型号如何&#…

【用unity实现100个游戏之7】从零开始制作一个仿杀戮尖塔卡牌回合制游戏

文章目录 前言素材资源开始一、UI框架二、挂载脚本三、事件监听,用于绑定按钮事件四、声音管理器五、excel转txt文本六、游戏配置七、用户信息表八、战斗管理器九、 敌人管理器十、玩家血量、能量、防御值、卡牌数十一、敌人血量 行动显示逻辑十二、UI提示效果实现十…

Jetsonnano B01 笔记1:基础理解—网络配置—远程连接

今日开始学习 Jetsonnano B01,这是一台小电脑,可以用来: 运行现代 AI 负载,并行运行多个神经网络,以及同时处理来自多个高清传感器的数据,可广泛应用与图像分类、对象检测、图像分割、语音处 理等领域。它…

【python爬虫】15.Scrapy框架实战(热门职位爬取)

文章目录 前言明确目标分析过程企业排行榜的公司信息公司详情页面的招聘信息 代码实现创建项目定义item 创建和编写爬虫文件存储文件修改设置 代码实操总结 前言 上一关,我们学习了Scrapy框架,知道了Scrapy爬虫公司的结构和工作原理。 在Scrapy爬虫公司…

配置本地maven

安装maven安装包 修改环境变量 vim ~/.bash_profile export JMETER_HOME/Users/yyyyjinying/apache-jmeter-5.4.1 export GOROOT/usr/local/go export GOPATH/Users/yyyyjinying/demo-file/git/backend/go export GROOVY_HOME/Users/yyyyjinying/sortware/groovy-4.0.14 exp…

手写Mybatis:第10章-使用策略模式,调用参数处理器

文章目录 一、目标:参数处理器二、设计:参数处理器三、实现:参数处理器3.1 工程结构3.2 参数处理器关系图3.3 入参数校准3.4 参数策略处理器3.4.1 JDBC枚举类型修改3.4.2 类型处理器接口3.4.3 模板模式:类型处理器抽象基类3.4.4 类…

linux 进程隔离Namespace 学习

一、linux namespace 介绍 1.1、概念 Linux Namespace是Linux内核提供的一种机制,它用于隔离不同进程的资源视图,使得每个进程都拥有独立的资源空间,从而实现进程之间的隔离和资源管理。 Linux Namespace的设计目标是为了解决多个进程之间…

微服务设计和高并发实践

文章目录 1、微服务的设计原则1.1、服务拆分方法1.2、微服务的设计原则1.3、微服务架构 2、高并发系统的一些优化经验2.1、提高性能2.1.1、数据库优化2.1.2、使用缓存2.1.3、服务调用优化2.1.4、动静分离2.1.5、数据库读写分离 2.2、服务高可用2.2.1、限流和服务降级2.2.2、隔离…

C语言插入排序

前言: 本文主要讲解插入排序中的直接插入排序和希尔排序。 1、直接插入排序: 1.1基本思想 直接插入排序是一种简单的插入排序法,其基本思想是把待排序的数值按照大小顺序逐个插入到一个已经排好序的有序序列中,直到将所有记录…

Spring Cloud--从零开始搭建微服务基础环境【四】

😀前言 本篇博文是关于Spring Cloud–从零开始搭建微服务基础环境【四】,希望你能够喜欢 🏠个人主页:晨犀主页 🧑个人简介:大家好,我是晨犀,希望我的文章可以帮助到大家,…

QT day5

服务器: #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//给服务器指针实例化对象server new QTcpServer(this); }Widget::~Widget() {delete ui…

Java“牵手”京东商品评论数据接口方法,京东商品评论接口,京东商品评价接口,行业数据监测,京东API实现批量商品评论内容数据抓取示例

京东平台商品评论数据接口是开放平台提供的一种API接口,通过调用API接口,开发者可以获取京东商品的标题、价格、库存、月销量、总销量、库存、详情描述、图片、评论内容、评论日期、评论图片、追评内容等详细信息 。 获取商品评论接口API是一种用于获取…

el-select 加多选框使用

解决方法&#xff1a; el-select 添加属性 multiple&#xff0c; <el-form-item label"订单来源&#xff1a;"><el-selectv-model"tableFrom.userType"clearablemultipleplaceholder"请选择"class"selWidth"><el-opt…

LeetCode-53-最大子数组和-贪心算法

贪心算法理论基础&#xff1a; 局部最优推全局最优 贪心无套路~ 没有什么规律~ 重点&#xff1a;每个阶段的局部最优是什么&#xff1f; 题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#…