gRPC学习记录(五)--拦截器分析

go语言 grpc 拦截器 在gRPC中,拦截器函数通常通过实现grpc.UnaryServerInterceptor和grpc.StreamServerInterceptor接口来定义。gRPC拦截器(interceptor)是一种函数,它可以在gRPC调用之前和之后执行一些逻辑,例如认证、授权、日志记录、监控和统计等。如果真的需要多个拦截器,可以使用 go-grpc-middleware 提供的 grpc.UnaryInterceptor 和 grpc.StreamInterceptor 链式方法。也可以直接下载绑定的资源。 阅读详情

对于此类调用拦截器是必不可少的,本篇就分析下拦截器的实现.(博主本来想分析源码的,但是水平不足,并发知识欠缺,看的不是很懂,哎,仍需努力),另外貌似不同版本有些差异,这里使用的是1.0.3版本.

1.一个拦截器的小例子

在分析之前先看一种设计.

有一个接口如下:

/**
 * 主调用接口
 */
public abstract class Client {
    public abstract void start(String say);
}
/**
 * 上述接口实现类
 */
public class ClientImp extends Client {
    @Override
    public void start(String say) {
        System.out.println(say);
    }
}

对此接口相关的转换器:

/**
 * 用于包装Client到另一个Client
 */
public abstract class ForwardingClient extends Client{
    //要包装的对象
    protected abstract Client delegate();

    @Override
    public void start(String say) {
        delegate().start(say);
    }
}
/**
 * 一个简单的包装实现类,必须要传入要包装的对象
 */
public class ForwardingClientImpl extends ForwardingClient{

    //被委托对象
    private final Client client;

    public ForwardingClientImpl(Client client) {
        this.client = client;
    }

    @Override
    protected Client delegate() {
        return client;
    }
}

然后在下列方法中调用:

public class InterceptTest {
    public static void main(String[] args) {
        Client client = new ClientImp();//主要想执行的方法
        //构造第一个拦截器
        Client intercept1 = new ForwardingClientImpl(client){
            @Override
            public void start(String say) {
                System.out.println("拦截器1");
                super.start(say);
            }
        };
        //构造第二个拦截器
        Client intercept2 = new ForwardingClientImpl(intercept1){
            @Override
            public void start(String say) {
                System.out.println("拦截器2");
                super.start(say);
            }
        };
        //执行主方法
        intercept2.start("这是要执行的方法");
    }
}

毫无疑问会输出

拦截器2
拦截器1
这是要执行的方法

分析一下针对Client接口,通过ForwardingClient可以实现自身的嵌套调用,从而达到了类似拦截器的效果.在gRPC中有很多类似的嵌套类,其本质和上面差不多,上面例子有助于对gRPC拦截器的掌握.

2.gRPC的ClientCall

该抽象类就是用来调用远程方法的,实现了发送消息和接收消息的功能,该接口由两个泛型ReqT和ReqT,分别对应着请求发送的信息,和请求收到的回复.
ClientCall抽象类主要有两个部分组成,一是public abstract static class Listener<T>用于监听服务端回复的消息,另一部分是针对客户端请求调用的一系列过程,如下代码流程所示:
该类中方法都是抽象方法,规定了整个调用顺序,如下:

call = channel.newCall(unaryMethod, callOptions);
call.start(listener, headers);
call.sendMessage(message);
call.halfClose();
call.request(1);
// wait for listener.onMessage()

在ClientCall的子类中有ForwardingClientCall<ReqT, RespT>,该类的作用和之前的Demo一样,用于包装ClientCall,然后实现委托嵌套调用,里面方法都如下代码所示:

@Override
  public void start(Listener<RespT> responseListener, Metadata headers) {
    delegate().start(responseListener, headers);
  }

  @Override
  public void request(int numMessages) {
    delegate().request(numMessages);
  }

那和之前的Demo一对比,拦截器怎么使用就变得很容易了.
创建一个客户端拦截器,其中为header添加了token参数.之所以要实现ClientInterceptor接口,因为Channel本身也是可以嵌套的类,所以创建ClientCall也是被一层一层的调用.

/**
 * 客户端拦截器
 * @author Niu Li
 * @date 2017/2/4
 */
//ClientInterceptor接口是针对ClientCall的创建进行拦截
public class ClientInterruptImpl implements ClientInterceptor {
    @Override
    public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method,
                                                               CallOptions callOptions, Channel next) {
        //创建client
        System.out.println("创建client1");
        ClientCall<ReqT,RespT> clientCall = next.newCall(method,callOptions);
        return new ForwardingClientCall<ReqT, RespT>() {
            @Override
            protected ClientCall<ReqT, RespT> delegate() {
                return clientCall;
            }
            @Override
            public void start(Listener<RespT> responseListener, Metadata headers) {
                System.out.println("拦截器1,在此可以对header参数进行修改");
                Metadata.Key<String> token = Metadata.Key.of("token",Metadata.ASCII_STRING_MARSHALLER);
                headers.put(token,"123456");
                super.start(responseListener, headers);
            }
        };
    }
}

调用输出如下:

创建client1
拦截器1,在此可以对header参数进行修改

这是针对客户端调用前的拦截,对于客户端收到的回复拦截则通过ClientCall的静态内部类Listener来实现,该Listener也是可以嵌套的,其内有如下方法:

public void onHeaders(Metadata headers) {}
public void onMessage(T message) {}
public void onClose(Status status, Metadata trailers) {}
public void onReady() {}

对之前start方法改造下,让其判断返回的header中有没有传送过去的token,没有则该请求视为失败.

            @Override
            public void start(Listener<RespT> responseListener, Metadata headers) {
                System.out.println("拦截器1,在此可以对header参数进行修改");
                Metadata.Key<String> token = Metadata.Key.of("token",Metadata.ASCII_STRING_MARSHALLER);
                headers.put(token,"123456");
                Listener<RespT> forwardListener = new ForwardingClientCallListener.
                        SimpleForwardingClientCallListener<RespT>(responseListener) {
                    @Override
                    public void onHeaders(Metadata headers) {
                        Metadata.Key<String> token = Metadata.Key.of("token",Metadata.ASCII_STRING_MARSHALLER);
                        if (!"123456".equals(headers.get(token))){
                            System.out.println("返回参数无token,关闭该链接");
                            super.onClose(Status.DATA_LOSS,headers);
                        }
                        super.onHeaders(headers);
                    }
                };
                super.start(forwardListener, headers);
            }

最后再Channel创建的时候使用intercept(new ClientInterruptImpl())加入拦截器这样就简单实现了客户端的拦截了.


3.gRPC的ServerCall

有一点要搞明白,ClientCall是针对客户端要调用的方法的,而ServerCall是针对ClientCall的.看如下例子:

public class ServerInterruptImpl  implements ServerInterceptor{
    @Override
    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call,
                                                                 Metadata headers, ServerCallHandler<ReqT, RespT> next) {
        System.out.println("执行server拦截器1,获取token");
        //获取客户端参数
        Metadata.Key<String> token = Metadata.Key.of("token", Metadata.ASCII_STRING_MARSHALLER);
        String tokenStr = headers.get(token);
        if (StringUtil.isNullOrEmpty(tokenStr)){
            System.out.println("未收到客户端token,关闭此连接");
            call.close(Status.DATA_LOSS,headers);
        }
        //服务端写回参数
        ServerCall<ReqT, RespT> serverCall = new ForwardingServerCall.SimpleForwardingServerCall<ReqT, RespT>(call) {
            @Override
            public void sendHeaders(Metadata headers) {
                System.out.println("执行server拦截器2,写入token");
                headers.put(token,tokenStr);
                super.sendHeaders(headers);
            }
        };
        return next.startCall(serverCall,headers);
    }
}

当服务端接收到请求的时候就会打印出来如下的日志.这样就实现了服务端接手前的拦截和写回时的拦截.

执行server拦截器1,获取token
收到的信息:world:0
执行server拦截器2,写入token

关于更多使用还在琢磨中,目前欠缺并发知识,所以下一步打算看看并发相关的资料.

附录:

相关代码: https://github.com/nl101531/JavaWEB



作者:此博废弃_更新在个人博客
链接:https://www.jianshu.com/p/6a2f6db0a967
來源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


gRPC日志与恢复拦截器的实现与应用 本文探讨了在gRPC服务中实现日志记录和恢复拦截器的方法。通过具体的函数和代码示例,阐述了如何利用Zap日志库生成结构化日志,并在服务启动和请求处理过程中捕获关键信息,以便于调试和监控。同时,文章介绍了如何构建恢复拦截器,以应对服务器运行时可能出现的panic,确保服务的可用性和稳定性。 阅读详情

相关推荐

Android 桌面小组件 AppWidgetProvider

桌面小组件,绝对是小程序中的小程序,说白了就是任何复杂一丁点的操作都适合做成桌面小组件。所以这里采用的演示的例子,就只有一个白色圆角背景,外加一个文本框,显示文字。小组件的教程网上一搜一大堆,所以我这里主要就是介绍一些坑的地方,跟大致处理流程,具体细节还得看其他大神的骚操作。

qq_33601179的博客 6583

Grpc远程调用-客户端服务端传参问题-已解决

采用Grpc调用远程服务(博主的服务是注册在eureka上的),一般是通过grpc的stub对象去调用,如果需要向服务端传递参数,比如日志追踪用到的traceId,这个时候可以使用grpc的拦截器去实现。实现步骤如下 1.客户端 1.1 客户端先新建拦截器,实现ClientInterceptor接口,代码如下 package cn.swiftpass.upay.payment.ags.interceptor.grpc; import io.grpc.*; import lombok.extern

qq_30434271的博客 1347

告别环境配置噩梦:用Docker Desktop + WSL2在Windows上5分钟搞定vLLM运行环境

本文详细介绍了如何在Windows系统上使用Docker Desktop和WSL2快速搭建vLLM开发环境,5分钟内完成配置。通过容器化技术解决传统环境配置中的依赖冲突、环境污染等问题,提供一键复用的高效方案,特别适合AI开发者快速部署和测试vLLM框架。

weixin_28728495的博客 502

gRPC 实战之——客户端为 Request,服务端为 Response

二 编写接口实现类 三 编写服务端代码 四 编写客户端代码 五 测试 1 启动服务端和客户端 2 服务端打印如下 3 客户端打印如下 六 冲突解决 GRPC-Server报错服务端启动com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;CLjava异常解决方案_时间是一种解药的博客-优快云博客https://blog.youkuaiyun.com/cucgyfjklx/article/de

实践求真知 849

多模态融合相关概念

多模态图像融合

weixin_43921949的博客 7353

CUDA&PCL 点云体素下采样

CUDA&PCL 点云体素下采样

dayuhaitang1的博客 1268

GRPC server启动流程简单梳理

GRPC server启动流程简单梳理 一、rpc和grpc 1、rpc (remote procedure call) : 使得应用程序之间可以进行通信,而且也遵从server/client模型。使用的时候客户端调用server端提供的接口就像是调用本地的函数一样. 2、grpc : google提供的rpc框架 grpc 通信结构图如下: grpc 和 restful API 比较 ①:grpc可以通过protobuf定义接口,可以有更加严格的接口约束 ②:protobuf 通过二进制传输,提高传输效

why154285的博客 5196

STM32F103(二十三)通用同步异步收发器(USART)

学习板:STM32F103ZET6 往期博客: STM32F103五分钟入门系列(一)跑马灯(库函数+寄存器)+加编程模板+GPIO总结 STM32F103五分钟入门系列(二)GPIO的七大寄存器+GPIOx_LCKR作用和配置 STM32F103五分钟入门系列(三)GPIO的常用库函数使用方法总结+一个网络上的误区 STM32F103五分钟入门系列(四)蜂鸣器实验(库函数+寄存器) STM32F103五分钟入门系列(五)按键实验(库函数+寄存器) STM32F103五分钟入门系列(六)时钟框图+相关寄存器

Curnane0_0的博客 1017

gRPC 拦截器和监听器

gRPC 拦截器和监听器 gRPC 拦截器用于在请求执行之前执行,以实现校验授权,记录调用行为,插入其他逻辑等;拦截器有 ClientInterceptor 和 ServerInterceptor,分别用于客户端和服务端 客户端 拦截器接口定义 ClientInterceptor @ThreadSafe public interface ClientInterceptor { <ReqT, RespT> ClientCall<ReqT, RespT> interceptC

啦啦啦啦 la 3246

会计引擎:交易与核算分离的前世今生

一、为什么需要会计引擎 金融产品的设计,一如一块硬币需要兼顾两面:一面是为客户提供好的金融服务,满足客户支付结算、借贷、资产保值增值等方面的需求,并在这个过程中,以数字化的方式做好客户资产的登记,登记的载体,则是“分户”或“台账”,如客户存款户,是一种典型的分户--资金的增减变化都在一个账户中进行体现,而客户购买的银行理财,因为收益率、期限、投资标的不同,每一笔持有就形成一行记录,即为“台账”--这当然是不严谨但相对形象的表述。但是,“分户”和“台账”并没有必然的区别,以贷款为例,一些银行仍然存在所谓“

银行信息系统应用架构详解 982

手把手教你YOLOv8/YOLOv11分割训练自己数据集和推理,并教你使用Labelme工具标注数据(附分割网络结构图)

YOLOv8-seg 和 YOLOv11-seg 都是一种高效实例分割算法,实例分割模型的输出是一组勾勒出图像中每个物体的遮罩或轮廓,以及每个物体的类标签和置信度分数。当你不仅需要知道物体在图像中的位置,还需要知道它们的具体形状时,实例分割就非常有用了,功能非常强大,可以应对各种视觉任务。 YOLOv11-seg 则在 YOLOv8-seg 基础上进一步魔改了模型架构,相对分割速度可能更快,其他指标性能有待测试。实例分割可以用于自动驾驶、医疗图像处理、智能农业监控等领域。

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 4470

06-gRPC收发请求过程解析

实现了这两个过程,我们就可以完成一个点对点的 RPC 功能,但在实际使用的时候,我们的服务提供方通常都是以一个集群的方式对外提供服务的,所以在 gRPC 里面你还可以看到负载均衡、服务发现等功能。而且 gRPC 采用的是 HTTP/2 协议,我们还可以通过 Stream 方式来调用服务,以提升调用性能。总的来说,其实我们可以简单地认为gRPC 就是采用 HTTP/2 协议,并且默认采用 PB 序列化方式的一种 RPC。

JavaEdge全是干货的技术号 2763

备战数学建模38-粒子群算法pso番外篇1(攻坚战2)

粒子群算法最初是根据鸟类群体行为得到的启发,对鸟群行为进行仿真的算法,是一种启发式算法,也就是智能优化算法,利用信息共享,通过中间信息进行改进搜索,从而获得问题的可行解。我们简单从下图去体会一下粒子群算法,就是有多个鸟,每个鸟相当于一个粒子,每只鸟的位置受自己认知的历史最佳位置和当前距离食物最近的鸟的位置的影响。我们进一步分析这个图,可以得到两个公式,第一个是速度公式,即每只鸟的当前速度受上一步的速度惯性,自我认知和社会认知三部分影响,第二个是位置公式,即每只鸟的位置受上一位置和上一位置的速度的影响。

nuist_NJUPT的博客 1664

grpc java 泛型_gRPC学习记录(五)-拦截器分析 - Java 技术驿站-Java 技术驿站

对于此类调用拦截器是必不可少的,本篇就分析下拦截器的实现.(博主本来想分析源码的,但是水平不足,并发知识欠缺,看的不是很懂,哎,仍需努力),另外貌似不同版本有些差异,这里使用的是1.0.3版本.1.一个拦截器的小例子在分析之前先看一种设计.有一个接口如下:/*** 主调用接口*/public abstract class Client {public abstract void start(Str...

weixin_42355013的博客 1075

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Go语言的gRPC教程-拦截器

gRPC的拦截器和其他框架的拦截器(也称middleware)作用是一样的。利用拦截器我们可以在不侵入业务逻辑的前提下修改或者记录服务端或客户端的请求与响应,利用拦截器我们可以实现诸如日志记录权限认证限流等诸多功能上一篇提到gRPC的通信模式分为unary和streaming和,两种拦截器可以分别应用在服务端和客户端,所以gRPC总共为我们提供了四种拦截器。它们已经被定义成了go中的接口,我们创建的拦截器只要实现这些接口即可。

qq_44376306的博客 1247

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Android中GRPC的使用-拦截器

在构建GRPC应用程序时,无论是客户端应用程序,还是服务端应用程序,在远程方法执行之前后之后,都可能需要执行一些通用逻辑。在GRPC中可以拦截RPC的执行,来满足特定的需求,如日志、认证、性能度量指标等,这会使用一种名为拦截器的扩展机制。GRPC提供了简单的API,用来在客户端和服务器端的GRPC应用程序中实现拦截器。根据所拦截的RPC调用的类型,GRPC拦截器可风味两类:客户端拦截器和服务端拦截。

qtiao的博客 7518

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

gRPC(六)进阶:拦截器 interceptor

在常规的 HTTP 服务器中,我们可以设置有一个中间件将我们的处理程序包装在服务器上。此中间件可用于在实际提供正确内容之前执行服务器想要执行的任何操作,它可以是身份验证或日志记录或任​​何东西。中间件:中间件供系统软件和应用软件之间连接、便于软件各部件之间的沟通的计算机软件,相当于不同技术、工具和数据库之间的桥梁,例如他可以记录响应时长、记录请求和响应数据日志,身份验证等。中间件可以在拦截到发送给 handler 的请求,且可以拦截 handler 返回给客户端的响应。

林钟一的博客 4947

(精华)2020年10月28日 Grpc Grpc拦截器的使用

一. 前言 前面两篇文章给大家介绍了使用gRPC的入门以及双向流的使用,今天介绍的是gRPC中的拦截器。拦截器就像MVC的过滤器或者是ASP.NET Core middleware 一样,具有面向切面的思想,可以在调用服务的时候进行一些统一处理, 很适合在这里处理验证、日志等流程。本片文章就以记录日志为例来进行讲解。 二. Interceptor 类介绍 Interceptor类是gRPC服务拦截器的基类,是一个抽象类,它定了几个虚方法,分别如下: public virtual TResponse Bloc

愚公智库 30万+

gRPC 的拦截器

关于 gRPC 的拦截器使用介绍!

qq_46457076的博客 1244

gRPC实践--拦截器

前提阅读: gRPC实践–加密通信升级版 gRPC实践–加密通信 gRPC实践–Server&Client 本文的代码,可能在以上代码的基础上进行了更改。 前言 什么是拦截器? 拦截器(Interceptor),主要完成请求参数的解析、将页面表单参数赋给值栈中相应属性、执行功能检验、程序异常调试等工作。 说人话,就是,我需要在调用 gRPC 方法之前(或之后),对某些参数(如,日子、异常,甚至是token)做一些处理。 实现这类功能的活,就叫“拦截器”。 gRPC中的拦截器 gRPC中

Gassuih的博客 1207

gRPC中interceptor拦截器的总结和实践

拦截器是调用在还没有到达目的地之前进行处理的逻辑,类似于Spring框架中存在的Interceptor。gRPC 拦截器主要分为两种:客户端拦截器(ClientInterceptor),服务端拦截器(ServerInterceptor),顾名思义,分别于请求的两端执行相应的前拦截处理。

yangnk的技术记录 2417

gRPC 进阶——Interceptor 拦截器

gRPC拦截器是一种用于在RPC方法调用的生命周期中拦截和处理请求和响应的机制。拦截器允许开发者在请求到达实际服务方法之前或在响应返回客户端之前执行自定义逻辑。它们类似于中间件,广泛应用于日志记录、身份验证、请求修改等场景。

MPY_3的博客 1288

grpc 开发进阶 - 使用拦截器 interceptor

现在网上大部分都是 grpc 相关的介绍,真正涉及到 grpc 的配置使用的文章还是比较少的 所以本系列着重介绍 grpc 开发时可以能会用到的一些配置 拦截器在作用于每一个 RPC 调用,通常用来做日志,认证,metric 等等 interfactor 分为两种 unary interceptor 拦截 unary(一元) RPC 调用 stream interceptor 处理 stre...

IceberGu的博客 1万+

Interceptor拦截器 -- gRPC生态里的中间件

什么是拦截器gRPC的拦截器(interceptor)类似各种Web框架里的请求中间件,请求中间件大家都知道是利用装饰器模式对最终处理请求的handler程序进行装饰,这样中间件就可以在处...

kevin_tech的博客,微信搜「网管叨bi叨」 2429

Go gRPC 拦截器链:日志、Trace、重试和限流不要搅在一起

gRPC 拦截器链不应该是一个巨大的垃圾桶,而应该是一组职责单一、按序排列的独立组件。按语义分层:Trace(最外)→ 限流 → 日志 → 业务特定校验 → 重试(最内)。顺序不可随意调换。每个拦截器只做一件事。如果一个拦截器在"顺便"做另一件事——拆出来。使用显式声明顺序。不要使用多个参数(它们以注册的逆序执行,容易出错)。服务端重试仅限幂等方法。非幂等操作的重试逻辑放在客户端拦截器。编排良好的拦截器链在排查线上问题时,每一步都有清晰的轨迹。

m0_50889382的博客 9920

ETCD数据库源码分析——gRPC 拦截器

RPC响应要流经后置处理阶段。在前置处理阶段之后,则可以调用StreamHandler来完成远程方法的RPC执行,而且通过已实现grpc.ServerStream接口的包装器流接口,可以拦截流RPC的消息。server 收到 client 的 Range RPC 请求后,根据 ServiceName 和 RPC Method 将请求转发到对应的 handler 实现,handler 首先会将上面描述的一系列拦截器串联成一个执行,在拦截器逻辑中,通过调用 KVServer 模块的 Range 接口获取数据。.

肥叔菌的博客 856
上一篇: gRPC学习记录(四)--官方Demo
下一篇: 一个更优的零知识证明:Bulletproofs
Omni-Space
博客等级 码龄11年 2158粉丝 23原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值