Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.pulsar.functions.worker; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.annotations.VisibleForTesting; import io.netty.util.concurrent.DefaultThreadFactory; import java.net.URI; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import static org.apache.commons.lang3.StringUtils.isNotBlank; import org.apache.bookkeeper.clients.StorageClientBuilder; import org.apache.bookkeeper.clients.admin.StorageAdminClient; import org.apache.bookkeeper.clients.config.StorageClientSettings; import org.apache.commons.lang3.StringUtils; import org.apache.distributedlog.DistributedLogConfiguration; import org.apache.distributedlog.api.namespace.Namespace; import org.apache.distributedlog.api.namespace.NamespaceBuilder; import org.apache.pulsar.broker.authentication.AuthenticationService; import org.apache.pulsar.client.admin.PulsarAdmin; import org.apache.pulsar.client.api.ClientBuilder; import org.apache.pulsar.client.api.PulsarClient; import org.apache.pulsar.client.api.PulsarClientException; import org.apache.pulsar.common.configuration.PulsarConfigurationLoader; /** * A service component contains everything to run a worker except rest server. */ @Slf4j @Getter public class WorkerService { private final WorkerConfig workerConfig; private PulsarClient client; private FunctionRuntimeManager functionRuntimeManager; private FunctionMetaDataManager functionMetaDataManager; private ClusterServiceCoordinator clusterServiceCoordinator; // dlog namespace for storing function jars in bookkeeper private Namespace dlogNamespace; // storage client for accessing state storage for functions private StorageAdminClient stateStoreAdminClient; private MembershipManager membershipManager; private SchedulerManager schedulerManager; private boolean isInitialized = false; private final ScheduledExecutorService statsUpdater; private AuthenticationService authenticationService; private ConnectorsManager connectorsManager; private PulsarAdmin brokerAdmin; private PulsarAdmin functionAdmin; private final MetricsGenerator metricsGenerator; private final ScheduledExecutorService executor; @VisibleForTesting private URI dlogUri; public WorkerService(WorkerConfig workerConfig) { this.workerConfig = workerConfig; this.statsUpdater = Executors .newSingleThreadScheduledExecutor(new DefaultThreadFactory("worker-stats-updater")); this.executor = Executors.newScheduledThreadPool(10, new DefaultThreadFactory("pulsar-worker")); this.metricsGenerator = new MetricsGenerator(this.statsUpdater, workerConfig); } public void start(URI dlogUri) throws InterruptedException { log.info("Starting worker {}...", workerConfig.getWorkerId()); this.brokerAdmin = Utils.getPulsarAdminClient(workerConfig.getPulsarWebServiceUrl(), workerConfig.getClientAuthenticationPlugin(), workerConfig.getClientAuthenticationParameters(), workerConfig.getTlsTrustCertsFilePath(), workerConfig.isTlsAllowInsecureConnection()); final String functionWebServiceUrl = StringUtils.isNotBlank(workerConfig.getFunctionWebServiceUrl()) ? workerConfig.getFunctionWebServiceUrl() : workerConfig.getWorkerWebAddress(); this.functionAdmin = Utils.getPulsarAdminClient(functionWebServiceUrl, workerConfig.getClientAuthenticationPlugin(), workerConfig.getClientAuthenticationParameters(), workerConfig.getTlsTrustCertsFilePath(), workerConfig.isTlsAllowInsecureConnection()); try { log.info("Worker Configs: {}", new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(workerConfig)); } catch (JsonProcessingException e) { log.warn("Failed to print worker configs with error {}", e.getMessage(), e); } // create the dlog namespace for storing function packages this.dlogUri = dlogUri; DistributedLogConfiguration dlogConf = Utils.getDlogConf(workerConfig); try { this.dlogNamespace = NamespaceBuilder.newBuilder().conf(dlogConf) .clientId("function-worker-" + workerConfig.getWorkerId()).uri(this.dlogUri).build(); } catch (Exception e) { log.error("Failed to initialize dlog namespace {} for storing function packages", dlogUri, e); throw new RuntimeException(e); } // create the state storage client for accessing function state if (workerConfig.getStateStorageServiceUrl() != null) { StorageClientSettings clientSettings = StorageClientSettings.newBuilder() .serviceUri(workerConfig.getStateStorageServiceUrl()).build(); this.stateStoreAdminClient = StorageClientBuilder.newBuilder().withSettings(clientSettings) .buildAdmin(); } // initialize the function metadata manager try { ClientBuilder clientBuilder = PulsarClient.builder() .serviceUrl(this.workerConfig.getPulsarServiceUrl()); if (isNotBlank(workerConfig.getClientAuthenticationPlugin()) && isNotBlank(workerConfig.getClientAuthenticationParameters())) { clientBuilder.authentication(workerConfig.getClientAuthenticationPlugin(), workerConfig.getClientAuthenticationParameters()); } clientBuilder.enableTls(workerConfig.isUseTls()); clientBuilder.allowTlsInsecureConnection(workerConfig.isTlsAllowInsecureConnection()); clientBuilder.tlsTrustCertsFilePath(workerConfig.getTlsTrustCertsFilePath()); clientBuilder.enableTlsHostnameVerification(workerConfig.isTlsHostnameVerificationEnable()); this.client = clientBuilder.build(); log.info("Created Pulsar client"); //create scheduler manager this.schedulerManager = new SchedulerManager(this.workerConfig, this.client, this.brokerAdmin, this.executor); //create function meta data manager this.functionMetaDataManager = new FunctionMetaDataManager(this.workerConfig, this.schedulerManager, this.client); this.connectorsManager = new ConnectorsManager(workerConfig); //create membership manager this.membershipManager = new MembershipManager(this, this.client); // create function runtime manager this.functionRuntimeManager = new FunctionRuntimeManager(this.workerConfig, this, this.dlogNamespace, this.membershipManager, connectorsManager, functionMetaDataManager); // Setting references to managers in scheduler this.schedulerManager.setFunctionMetaDataManager(this.functionMetaDataManager); this.schedulerManager.setFunctionRuntimeManager(this.functionRuntimeManager); this.schedulerManager.setMembershipManager(this.membershipManager); // initialize function metadata manager this.functionMetaDataManager.initialize(); // initialize function runtime manager this.functionRuntimeManager.initialize(); authenticationService = new AuthenticationService(PulsarConfigurationLoader.convertFrom(workerConfig)); // Starting cluster services log.info("Start cluster services..."); this.clusterServiceCoordinator = new ClusterServiceCoordinator(this.workerConfig.getWorkerId(), membershipManager); this.clusterServiceCoordinator.addTask("membership-monitor", this.workerConfig.getFailureCheckFreqMs(), () -> membershipManager.checkFailures(functionMetaDataManager, functionRuntimeManager, schedulerManager)); this.clusterServiceCoordinator.start(); // Start function runtime manager this.functionRuntimeManager.start(); // indicate function worker service is done intializing this.isInitialized = true; this.connectorsManager = new ConnectorsManager(workerConfig); } catch (Throwable t) { log.error("Error Starting up in worker", t); throw new RuntimeException(t); } } public void stop() { if (null != functionMetaDataManager) { try { functionMetaDataManager.close(); } catch (Exception e) { log.warn("Failed to close function metadata manager", e); } } if (null != functionRuntimeManager) { try { functionRuntimeManager.close(); } catch (Exception e) { log.warn("Failed to close function runtime manager", e); } } if (null != client) { try { client.close(); } catch (PulsarClientException e) { log.warn("Failed to close pulsar client", e); } } if (null != clusterServiceCoordinator) { clusterServiceCoordinator.close(); } if (null != membershipManager) { try { membershipManager.close(); } catch (PulsarClientException e) { log.warn("Failed to close membership manager", e); } } if (null != schedulerManager) { schedulerManager.close(); } if (null != this.brokerAdmin) { this.brokerAdmin.close(); } if (null != this.functionAdmin) { this.functionAdmin.close(); } if (null != this.stateStoreAdminClient) { this.stateStoreAdminClient.close(); } if (null != this.dlogNamespace) { this.dlogNamespace.close(); } if (this.executor != null) { this.executor.shutdown(); } } }