Pigeon的一次调用服务端发生了什么

上一篇 :Pigeon的一次调用客户端发生了什么

接着上一篇,来看一下在这一次请求中服务端发生了什么

首先来看下服务端的启动

public static void init() {
        if (!isInitialized) {
            synchronized (ProviderBootStrap.class) {
                if (!isInitialized) {
                	//调用链初始化
                    ProviderProcessHandlerFactory.init();
                    //序列化工厂,负责编解码
                    SerializerFactory.init();
                    ClassUtils.loadClasses("com.dianping.pigeon");
                    //关闭钩子,主要内容:服务下线,客户端和服务端关闭
                    Thread shutdownHook = new Thread(new ShutdownHookListener());
                   	......
                   	//初始化服务配置,并默认传输协议为HTTP
                    ServerConfig config = new ServerConfig();
                    config.setProtocol(Constants.PROTOCOL_HTTP);
                    //注册服务管理
                    RegistryManager.getInstance();
                    //ServiceLoader加载服务类:nettyServer
                    List<Server> servers = ExtensionLoader.getExtensionList(Server.class);
                    for (Server server : servers) {
                        if (!server.isStarted()) {
                            if (server.support(config)) {
                            	//netty服务端启动,共享线程池的初始化都在这里完成
                                server.start(config);
                                ....
                                ....
                            }
                        }
                    }
                    isInitialized = true;
                }
            }
        }
    }

我们可以看到整个服务端的初始化流程以及启动流程(通过server.start(config)完成netty的启动),其中nettyServer是通过ServiceLoader加载初始化的(Java中的SPI机制是基于接口的编程+策略模式+配置文件的组合方式实现的动态加载机制),其初始化配置如图
在这里插入图片描述
接着看下其Pipeline配置
在这里插入图片描述

可以看到同客户端是基本一致的,接着我们看下pigeon的自定义handler对请求的处理是什么样的

在这里插入图片描述

可以看到其中是通过server.processRequest方法对请求进行了处理,我们进去看它的调用,最终负责处理逻辑的是doProcessRequest(request, providerContext)方法,看一下实现

 public Future<InvocationResponse> doProcessRequest(final InvocationRequest request,
                                                       final ProviderContext providerContext) {
        requestContextMap.put(request, providerContext);
        startMonitorData(request, providerContext);
        Callable<InvocationResponse> requestExecutor = new Callable<InvocationResponse>() {

            @Override
            public InvocationResponse call() throws Exception {
                providerContext.getTimeline().add(new TimePoint(TimePhase.T));
                try {
                	//调用了ProviderProcessHandlerFactory中构建的filter链
                    ServiceInvocationHandler invocationHandler = ProviderProcessHandlerFactory
                            .selectInvocationHandler(providerContext.getRequest().getMessageType());
                    if (invocationHandler != null) {
                        providerContext.setThread(Thread.currentThread());
                        return invocationHandler.handle(providerContext);
                    }
                } catch (Throwable t) {
                    logger.error("Process request failed with invocation handler, you should never be here.", t);
                } finally {
                    requestContextMap.remove(request);
                }
                return null;
            }
        };
        final ThreadPool pool = selectThreadPool(request);

        try {
            checkRequest(pool, request);
            providerContext.getTimeline().add(new TimePoint(TimePhase.T));
            return pool.submit(requestExecutor);
        } catch (RejectedExecutionException e) {
            requestContextMap.remove(request);
            endMonitorData(request, providerContext);
            throw new RejectedException(getProcessorStatistics(pool), e);
        }
    }

这里调用了ProviderProcessHandlerFactory中构建的filter链,这里根据消息的类型调用不同的链路,然后交给了请求绑定的线程池(共享线程池、慢线程池、自定义线程池中的一种)去执行,可以看到其核心调用逻辑是在ProviderProcessHandlerFactory中构建的filter链,一起来看一下服务端的filter链是怎样的

public static void init() {
		//请求初始的一些定义
        registerBizProcessFilter(new ProviderContextFilter());
        //监控相关
        registerBizProcessFilter(new TracerFilter());
        if (Constants.MONITOR_ENABLE) {
            registerBizProcessFilter(new MonitorProcessFilter());
        }
        registerBizProcessFilter(new InnerTracerFilter());
        registerBizProcessFilter(new TrafficRecordFilter());
        //负责传数据给客户端的filter
        registerBizProcessFilter(new WriteResponseProcessFilter());
        //上下文处理
        registerBizProcessFilter(new ContextTransferProcessFilter());
        registerBizProcessFilter(new ExceptionProcessFilter());
        //通用调用处理
        registerBizProcessFilter(new GenericProcessFilter());
        //安全相关
        registerBizProcessFilter(new SecurityFilter());
        //统计信息
        registerBizProcessFilter(new GatewayProcessFilter());
        //服务方法调用
        registerBizProcessFilter(new BusinessProcessFilter());
        //基础调用链
        bizInvocationHandler = createInvocationHandler(bizProcessFilters);

		//心跳相关责任链
        registerHeartBeatProcessFilter(new WriteResponseProcessFilter());
        registerHeartBeatProcessFilter(new HeartbeatProcessFilter());
        heartBeatInvocationHandler = createInvocationHandler(heartBeatProcessFilters);

        registerHealthCheckProcessFilter(new WriteResponseProcessFilter());
        registerHealthCheckProcessFilter(new HealthCheckProcessFilter());
        healthCheckInvocationHandler = createInvocationHandler(healthCheckProcessFilters);

        registerScannerHeartBeatProcessFilter(new WriteResponseProcessFilter());
        registerScannerHeartBeatProcessFilter(new ScannerHeartBeatProcessFilter());
        scannerHeartBeatInvocationHandler = createInvocationHandler(scannerHeartBeatProcessFilters);
    }

可以看到ProviderProcessHandlerFactory中一共构建了四种filter链,我们这里要看的主要是bizProcessFilters调用链,这是负责数据处理和传输的链路,其中WriteResponseProcessFilter负责数据的返回,BusinessProcessFilter负责服务本地方法的调用,来看下它的实现

public InvocationResponse invoke(ServiceInvocationHandler handler, ProviderContext invocationContext)
            throws Throwable {
        invocationContext.getTimeline().add(new TimePoint(TimePhase.U));
        InvocationRequest request = invocationContext.getRequest();
        if (request.getMessageType() == Constants.MESSAGE_TYPE_SERVICE) {
            if (timeoutReseted && request.getTimeout() > 0) {
                ContextUtils.putLocalContext(Constants.REQUEST_TIMEOUT, request.getTimeout());
            }
            .....
			.....
            InvocationResponse response = null;
            ServiceMethod method = invocationContext.getServiceMethod();
            if (method == null) {
                method = ServiceMethodFactory.getMethod(request);
            }

            ProviderHelper.setContext(invocationContext);
            invocationContext.getTimeline().add(new TimePoint(TimePhase.M, System.currentTimeMillis()));
            Object returnObj = null;
            try {
            	//服务执行方法调用
                returnObj = method.invoke(request.getParameters());
            } finally {
                ProviderHelper.clearContext();
                if (Constants.REPLY_MANUAL || invocationContext.isAsync()) {
                    if (request.getCallType() == Constants.CALLTYPE_REPLY) {
                        request.setCallType(Constants.CALLTYPE_MANUAL);
                    }
                }
            }
            invocationContext.getTimeline().add(new TimePoint(TimePhase.M, System.currentTimeMillis()));
            if (request.getCallType() == Constants.CALLTYPE_REPLY) {
                response = ProviderUtils.createSuccessResponse(request, returnObj);
            }
            return response;
        }
        throw new BadRequestException("message type[" + request.getMessageType() + "] is not supported!");
    }

我们知道服务端暴露给客户端的api是接口,客户端通过接口api调用相关方法(通过动态代理调用服务),那么服务端是怎么根据接口找到请求匹配的方法实现的呢?
从上面可以看到是通过调用 ServiceMethodFactory.getMethod(request);获取的方法,看一下它的实现
在这里插入图片描述
通过
getServiceMethodCache(newUrl)获得服务方法缓存,然后从serviceMethodCache(存了对应服务所有的方法信息,其中有一个根据方法名和参数个数保存的Map方法集合)中去获取方法,接着进去看下
在这里插入图片描述
这里的核心方法是
getBestMatchMethod(methodName, paramNames)方法,该方法作用:找到匹配度最高的方法(根据参数匹配),然后将结果方法缓存bestMacthMethod
里,以待下次直接获取,无需再行匹配,最后将匹配到的方法返回。
在这里插入图片描述
得到匹配的method会通过反射去执行对应服务方法的实现,然后返回结果给外层Filter ,并由WriteResponseProcessFilter完成数据的发送。

这里要注意的是pigeon不管是客户端还是服务端,都是使用类Filter的责任链执行流程,调用过程其实是从上到下执行,再从下到上的返回调用(上层Filter嵌套下层Filter),从链路处理逻辑中我们可以看到,异常并不在下层filter中处理,而是直接抛给上层,交给MonitorProcessFilter去记录异常,或者直接抛出给调用方。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值