skywalking源码分析第十五篇一agent端服务注册与DictionaryManager字典管理

前言

原理图

  • 通过ServiceManager.boot[加载,准备,启动,完成]实现所有BootService的初始化和运行前准备工作
    在这里插入图片描述
    字典相关bootService如下:
类名作用
ServiceAndEndpointRegisterClient与服务端进行定时注册,基于服务端响应更新本地字典信息

源码分析一ServiceManager

  • 通过SPI加载所有bootService并完成加载service集合的生命周期调用
  • loadAllServices通过spi加载bootService同时处理DefaultImplementor和OverrideImplementor注解
  • DefaultImplementor注解: 目标类名为bootService自身
  • OverrideImplementor注解: 目标类名为bootService上OverrideImplementor注解指定的类名
public enum ServiceManager {
    单例模式
    INSTANCE;
    spi加载的bootservice集合
    private Map<Class, BootService> bootedServices = Collections.emptyMap();
    引导程序入口
    public void boot() {
        基于java原生SPI加载/resources/META-INF.services/org.skywalking.apm.agent.core.boot.BootService
        /*
            默认加载如下:
            TraceSegmentServiceClient
            ContextManager
            SamplingService
            GRPCChannelManager
            JVMService
            
            ContextManagerExtendService
            CommandService
            CommandExecutorService
            OperationNameFormatService
         */
        bootedServices = loadAllServices();
        遍历处理service的prepare
        prepare();
        遍历处理service的boot
        startup();
        遍历处理service的onComplete
        onComplete();
    }

正文一服务注册发现

源码分析一ServiceAndEndpointRegisterClient生命周期

  • prepare方法中注册grpc事件监听器(回调statusChanged)
  • boot启动ServiceAndEndpointRegisterClient核心任务调度,每3秒执行一次,负责服务注册,数据同步,字典维护
  • 如果服务端返回ServiceResetCommandExecutor则coolDownStartTime为当前时间
  • 则10分钟后执行服务注册等逻辑
  • SERVICE_ID还不存在则先向服务注册service
  • SERVICE_INSTANCE_ID还不存在 则先向服务端注册SERVICE_INSTANCE
  • 发送心跳
  • 处理心跳Commands回调,[实际只有ServiceResetCommandExecutor有处理逻辑]
  • 维护NetworkAddressDictionary和EndpointNameDictionary字典
public class ServiceAndEndpointRegisterClient implements BootService, Runnable, GRPCChannelListener {
    private static final ILog logger = LogManager.getLogger(ServiceAndEndpointRegisterClient.class);
    private static String INSTANCE_UUID;
    private static List<KeyStringValuePair> SERVICE_INSTANCE_PROPERTIES;

    private volatile GRPCChannelStatus status = GRPCChannelStatus.DISCONNECT;
    private volatile RegisterGrpc.RegisterBlockingStub registerBlockingStub;
    private volatile ServiceInstancePingGrpc.ServiceInstancePingBlockingStub serviceInstancePingStub;
    private volatile ScheduledFuture<?> applicationRegisterFuture;
    private volatile long coolDownStartTime = -1;

    @Override
    public void statusChanged(GRPCChannelStatus status) {
        grpc事件触发修改stub服务
        if (GRPCChannelStatus.CONNECTED.equals(status)) {
            Channel channel = ServiceManager.INSTANCE.findService(GRPCChannelManager.class).getChannel();
            registerBlockingStub = RegisterGrpc.newBlockingStub(channel);
            serviceInstancePingStub = ServiceInstancePingGrpc.newBlockingStub(channel);
        } else {
            registerBlockingStub = null;
            serviceInstancePingStub = null;
        }
        this.status = status;
    }

    @Override
    public void prepare() throws Throwable {
       向grpc通道注册grpc事件监听器
        ServiceManager.INSTANCE.findService(GRPCChannelManager.class).addChannelListener(this);

        INSTANCE_UUID = StringUtil.isEmpty(Config.Agent.INSTANCE_UUID) ? UUID.randomUUID().toString()
                .replaceAll("-", "") : Config.Agent.INSTANCE_UUID;

        SERVICE_INSTANCE_PROPERTIES = new ArrayList<KeyStringValuePair>();

        for (String key : Config.Agent.INSTANCE_PROPERTIES.keySet()) {
            SERVICE_INSTANCE_PROPERTIES.add(KeyStringValuePair.newBuilder()
                    .setKey(key).setValue(Config.Agent.INSTANCE_PROPERTIES.get(key)).build());
        }
    }

    @Override
    public void boot() throws Throwable {
        启动service执行任务
        applicationRegisterFuture = Executors
                .newSingleThreadScheduledExecutor(new DefaultNamedThreadFactory("ServiceAndEndpointRegisterClient"))
                .scheduleAtFixedRate(new RunnableWithExceptionProtection(this, new RunnableWithExceptionProtection.CallbackWhenException() {
                    @Override
                    public void handle(Throwable t) {
                        logger.error("unexpected exception.", t);
                       每三秒执行一次调度
                    }
                }), 0, Config.Collector.APP_AND_SERVICE_REGISTER_CHECK_INTERVAL, TimeUnit.SECONDS);
    }

    @Override
    public void onComplete() throws Throwable {
    }

    @Override
    public void shutdown() throws Throwable {
        applicationRegisterFuture.cancel(true);
    }

    @Override
    public void run() {
        logger.debug("ServiceAndEndpointRegisterClient running, status:{}.", status);
        if (coolDownStartTime > 0) {
            final long coolDownDurationInMillis = TimeUnit.MINUTES.toMillis(Config.Agent.COOL_DOWN_THRESHOLD);
            服务端返回ServiceResetCommandExecutor则执行10分钟hold
            if (System.currentTimeMillis() - coolDownStartTime < coolDownDurationInMillis) {
                logger.warn("The agent is cooling down, won't register itself");
                return;
            } else {
                超过10分钟后则允许重新注册
                logger.warn("The agent is re-registering itself to backend");
            }
        }
        coolDownStartTime = -1;

        boolean shouldTry = true;
        while (GRPCChannelStatus.CONNECTED.equals(status) && shouldTry) {
            shouldTry = false;
            try {
                SERVICE_ID还不存在则先向服务注册service 由于定时调度存在,如果SERVICE_ID不存在则轮询请求服务端
                if (RemoteDownstreamConfig.Agent.SERVICE_ID == DictionaryUtil.nullValue()) {
                    if (registerBlockingStub != null) {
                        ServiceRegisterMapping serviceRegisterMapping = registerBlockingStub.withDeadlineAfter(GRPC_UPSTREAM_TIMEOUT, TimeUnit.SECONDS).doServiceRegister(
                                Services.newBuilder().addServices(Service.newBuilder().setServiceName(Config.Agent.SERVICE_NAME)).build());
                        if (serviceRegisterMapping != null) {
                            for (KeyIntValuePair registered : serviceRegisterMapping.getServicesList()) {
                                if (Config.Agent.SERVICE_NAME.equals(registered.getKey())) {
                                    更新自己的serviceId
                                    RemoteDownstreamConfig.Agent.SERVICE_ID = registered.getValue();
                                    shouldTry = true;
                                }
                            }
                        }
                    }
                } else {
                    if (registerBlockingStub != null) {
                        SERVICE_INSTANCE_ID还不存在 则先向服务端注册SERVICE_INSTANCE
                        if (RemoteDownstreamConfig.Agent.SERVICE_INSTANCE_ID == DictionaryUtil.nullValue()) {
                            ServiceInstanceRegisterMapping instanceMapping = registerBlockingStub.withDeadlineAfter(GRPC_UPSTREAM_TIMEOUT, TimeUnit.SECONDS)
                                    .doServiceInstanceRegister(ServiceInstances.newBuilder()
                                            .addInstances(
                                                    ServiceInstance.newBuilder()
                                                            .setServiceId(RemoteDownstreamConfig.Agent.SERVICE_ID)
                                                            .setInstanceUUID(INSTANCE_UUID)
                                                            .setTime(System.currentTimeMillis())
                                                            .addAllProperties(OSUtil.buildOSInfo())
                                                            .addAllProperties(SERVICE_INSTANCE_PROPERTIES)
                                            ).build());
                            for (KeyIntValuePair serviceInstance : instanceMapping.getServiceInstancesList()) {
                                if (INSTANCE_UUID.equals(serviceInstance.getKey())) {
                                    int serviceInstanceId = serviceInstance.getValue();
                                    if (serviceInstanceId != DictionaryUtil.nullValue()) {
                                        // 更新自己的SERVICE_INSTANCE_ID
                                        RemoteDownstreamConfig.Agent.SERVICE_INSTANCE_ID = serviceInstanceId;
                                        RemoteDownstreamConfig.Agent.INSTANCE_REGISTERED_TIME = System.currentTimeMillis();
                                    }
                                }
                            }
                        } else {
                            3秒一次发送心跳
                            final Commands commands = serviceInstancePingStub.withDeadlineAfter(GRPC_UPSTREAM_TIMEOUT, TimeUnit.SECONDS)
                                    .doPing(ServiceInstancePingPkg.newBuilder()
                                            .setServiceInstanceId(RemoteDownstreamConfig.Agent.SERVICE_INSTANCE_ID)
                                            .setTime(System.currentTimeMillis())
                                            .setServiceInstanceUUID(INSTANCE_UUID)
                                            .build());
                            同步NetworkAddress并更新本地字典
                            NetworkAddressDictionary.INSTANCE.syncRemoteDictionary(registerBlockingStub.withDeadlineAfter(GRPC_UPSTREAM_TIMEOUT, TimeUnit.SECONDS));
                            同步EndpointName并更新本地字典 [EndpointName来源于span创建时业务侧定义的operationName]
                            EndpointNameDictionary.INSTANCE.syncRemoteDictionary(registerBlockingStub.withDeadlineAfter(GRPC_UPSTREAM_TIMEOUT, TimeUnit.SECONDS));
                            /*

                                ServiceResetCommand   ->  ServiceResetCommandExecutor
                                // 无实际处理
                                EndpointResetCommand  ->  NoopCommandExecutor
                                InstanceResetCommand  ->  NoopCommandExecutor
                                NetworkResetCommand   ->  NoopCommandExecutor
                                TraceIgnoreCommand    ->  NoopCommandExecutor
                             */
                            ServiceManager.INSTANCE.findService(CommandService.class).receiveCommand(commands);
                        }
                    }
                }
            } catch (Throwable t) {
                logger.error(t, "ServiceAndEndpointRegisterClient execute fail.");
                ServiceManager.INSTANCE.findService(GRPCChannelManager.class).reportError(t);
            }
        }
    }

    public void coolDown() {
        this.coolDownStartTime = System.currentTimeMillis();
    }
}

总结

  • 通过serviceManager加载启动主动BootService
  • ServiceAndEndpointRegisterClient负责服务和服务实例注册,地址和端点同步,本地字典维护以及心跳请求的逻辑
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值