Hello again!

I have found one work-around, it is not very sound but seems reliable.

Before first invocation of UriDeploymentSpi-deployed Compute Job with,
first run a locally-deployed job with same dependency. In this case,
ServiceTopologyCallable is called outside of UriDeploymentSpi context, is
deployed properly and doesn't cause problems later.

Work is underway for proper fix.

-- 
Ilya Kasnacheev

2017-10-29 14:46 GMT+03:00 Dmitriy Ivanov <daiva...@gridfore.com>:

> Hi!
> In our project we need to deploy custom compute tasks into cluster without
> cluster restart and p2p class loading.
> I try to use org.apache.ignite.spi.deployment.uri.UriDeploumentSpi for
> that purpose, but I have a problem.
>
> I have simple Ignite Service and Ignite Compute Task which use it throught
> @ServiceResource.
> This ComputeTask located into .gar file which was deployed via
> UriDeploumentSpi.
>
> If I have service implementation on each node(node singleton service) then
> it works great.
> But if I deploy service as a cluster singleton then task executes
> correctly only on node with this service.
>
> On other nodes @ServiceResource returns ServiceProxy that throws exception
> on service remote method invokation (lambda with service call cannot be
> deployed):
>
> SEVERE: Failed to execute job 
> [jobId=68a96d76f51-7919c34c-9a48-4068-bcd6-70dad5595e86,
> ses=GridJobSessionImpl [ses=GridTaskSessionImpl [taskName=task-one,
> dep=GridDeployment [ts=1509275650885, depMode=SHARED, 
> clsLdr=GridUriDeploymentClassLoader
> [urls=[file:/C:/IdeaProjects/dmp_code_deployment/test/out/
> deployment/gg.uri.deployment.tmp/428ec712-e6d0-4eab-97f9-
> ce58d7b3e0f5/dirzip_task-one6814855127293591501.gar/]],
> clsLdrId=7eb15d76f51-428ec712-e6d0-4eab-97f9-ce58d7b3e0f5, userVer=0,
> loc=true, sampleClsName=com.gridfore.tfedyanin.deploy.Task1,
> pendingUndeploy=false, undeployed=false, usage=1], 
> taskClsName=com.gridfore.tfedyanin.deploy.Task1,
> sesId=38a96d76f51-7919c34c-9a48-4068-bcd6-70dad5595e86,
> startTime=1509275650601, endTime=9223372036854775807,
> taskNodeId=7919c34c-9a48-4068-bcd6-70dad5595e86, 
> clsLdr=GridUriDeploymentClassLoader
> [urls=[file:/C:/IdeaProjects/dmp_code_deployment/test/out/
> deployment/gg.uri.deployment.tmp/428ec712-e6d0-4eab-97f9-
> ce58d7b3e0f5/dirzip_task-one6814855127293591501.gar/]], closed=false,
> cpSpi=null, failSpi=null, loadSpi=null, usage=1, fullSup=false,
> internal=false, subjId=7919c34c-9a48-4068-bcd6-70dad5595e86,
> mapFut=IgniteFuture [orig=GridFutureAdapter [ignoreInterrupts=false,
> state=INIT, res=null, hash=1254296516]], execName=null],
> jobId=68a96d76f51-7919c34c-9a48-4068-bcd6-70dad5595e86]]
> class org.apache.ignite.IgniteDeploymentException: Failed to auto-deploy
> task (was task (re|un)deployed?): class org.apache.ignite.internal.
> processors.service.GridServiceProcessor$ServiceTopologyCallable
> at org.apache.ignite.internal.util.IgniteUtils$8.apply(
> IgniteUtils.java:833)
> at org.apache.ignite.internal.util.IgniteUtils$8.apply(
> IgniteUtils.java:831)
> at org.apache.ignite.internal.util.IgniteUtils.
> convertException(IgniteUtils.java:952)
> at org.apache.ignite.internal.processors.service.
> GridServiceProxy.invokeMethod(GridServiceProxy.java:208)
> at org.apache.ignite.internal.processors.service.GridServiceProxy$
> ProxyInvocationHandler.invoke(GridServiceProxy.java:356)
> at com.sun.proxy.$Proxy31.println(Unknown Source)
> at com.gridfore.tfedyanin.deploy.Task1$MyComputeJobAdapter.
> execute(Task1.java:49)
> at org.apache.ignite.internal.processors.job.GridJobWorker$
> 2.call(GridJobWorker.java:566)
> at org.apache.ignite.internal.util.IgniteUtils.
> wrapThreadLoader(IgniteUtils.java:6608)
> at org.apache.ignite.internal.processors.job.GridJobWorker.
> execute0(GridJobWorker.java:560)
> at org.apache.ignite.internal.processors.job.GridJobWorker.
> body(GridJobWorker.java:489)
> at org.apache.ignite.internal.util.worker.GridWorker.run(
> GridWorker.java:110)
> at org.apache.ignite.internal.processors.job.GridJobProcessor.
> processJobExecuteRequest(GridJobProcessor.java:1181)
> at org.apache.ignite.internal.processors.job.GridJobProcessor$
> JobExecutionListener.onMessage(GridJobProcessor.java:1908)
> at org.apache.ignite.internal.managers.communication.
> GridIoManager.invokeListener(GridIoManager.java:1556)
> at org.apache.ignite.internal.managers.communication.GridIoManager.
> processRegularMessage0(GridIoManager.java:1184)
> at org.apache.ignite.internal.managers.communication.
> GridIoManager.access$4200(GridIoManager.java:126)
> at org.apache.ignite.internal.managers.communication.GridIoManager$9.run(
> GridIoManager.java:1097)
> at java.util.concurrent.ThreadPoolExecutor.runWorker(
> ThreadPoolExecutor.java:1149)
> at java.util.concurrent.ThreadPoolExecutor$Worker.run(
> ThreadPoolExecutor.java:624)
> at java.lang.Thread.run(Thread.java:748)
> Caused by: class org.apache.ignite.internal.IgniteDeploymentCheckedException:
> Failed to auto-deploy task (was task (re|un)deployed?): class
> org.apache.ignite.internal.processors.service.GridServiceProcessor$
> ServiceTopologyCallable
> at org.apache.ignite.internal.processors.task.GridTaskProcessor.startTask(
> GridTaskProcessor.java:644)
> at org.apache.ignite.internal.processors.task.GridTaskProcessor.execute(
> GridTaskProcessor.java:448)
> at org.apache.ignite.internal.processors.task.GridTaskProcessor.execute(
> GridTaskProcessor.java:428)
> at org.apache.ignite.internal.processors.closure.GridClosureProcessor.
> callAsyncNoFailover(GridClosureProcessor.java:599)
> at org.apache.ignite.internal.processors.service.GridServiceProcessor.
> serviceTopology(GridServiceProcessor.java:728)
> at org.apache.ignite.internal.processors.service.GridServiceProxy.
> randomNodeForService(GridServiceProxy.java:274)
> at org.apache.ignite.internal.processors.service.GridServiceProxy.
> nodeForService(GridServiceProxy.java:260)
> at org.apache.ignite.internal.processors.service.
> GridServiceProxy.invokeMethod(GridServiceProxy.java:170)
> ... 17 more
>
>
> I found out that this problem is connected with
> GridUriDeploymentClassLoader classloader which obtained in
> GridClassLoaderCache line 76:
>
> private static ClassLoader detectClassLoader(Class<?> cls) {
>     ClassLoader ctxClsLdr = Thread.currentThread().getContextClassLoader();
>
>
> In code of GridDeploymentManager on line 271 there is an instance check,
> but GridUriDeploymentClassLoader is not instance of
> GridDeploymentClassLoader.
>
> if (clsLdr instanceof GridDeploymentClassLoader) {
>     GridDeploymentInfo ldr = (GridDeploymentInfo)clsLdr;
>
> Therefore check fails and another branch start execution:
>
> else
>     return locStore.explicitDeploy(cls, clsLdr);
>
> I think that it causes incorrect work of GridTaskProcessor code on line
> 641:
>
> dep = ctx.deploy().deploy(cls, ldr);
>
> Can you help me with this problem?
> Or maybe I should use another solution for code deployment?
>
> Your sincerely, Dmitry.
>
>
> I create ignite configuration like this:
>
>  IgniteConfiguration cfg = new IgniteConfiguration();
>  cfg.setPeerClassLoadingEnabled(false);
>  UriDeploymentSpi deploymentSpi = new UriDeploymentSpi();
>  deploymentSpi.setUriList(getUris());
>  deploymentSpi.setTemporaryDirectoryPath("out/deployment");
>  cfg.setDeploymentSpi(deploymentSpi);
>
>
> Also I have Ignite Service  TestService with one simple method "println":
>
> @Slf4j
> public class TestServiceImpl implements Service, TestService {
>     private AtomicBoolean interupt = new AtomicBoolean(false);
>     @Override
>     public void println(String str) {
>         log.info(str);
>         System.err.println(str);
>     }
>     @Override
>     public void cancel(ServiceContext ctx) {
>         interupt.set(true);
>     }
>     @Override
>     public void init(ServiceContext ctx) throws Exception {
>         System.err.println("Service deployed");
>     }
>     @Override
>     public void execute(ServiceContext ctx) throws Exception {
>         while (!interupt.get()) {
>             TimeUnit.SECONDS.sleep(10);
>             String msg = "I'm service and I'm alive";
>             log.debug(msg);
>             System.err.println(msg);
>         }
>     }
> }
>
>
> And task which executes simple job on each cluster node:
>
> private static class MyComputeJobAdapter extends ComputeJobAdapter {
>     @ServiceResource(serviceName = TestService.name, proxyInterface = 
> TestService.class)
>     private  TestService service;
>     @Override
>     public Object execute() throws IgniteException {
>         int i = 10;
>         while (i-- > 0) {
>             System.err.println("Service " + service);
>             service.println(SameFullQualifiedClass.msg);
>             try {
>                 TimeUnit.SECONDS.sleep(10);
>             } catch (InterruptedException e) {
>                 e.printStackTrace();
>             }
>         }
>         return null;
>     }
> }
>
>
> I deploy TestService as a cluster singleton:
>
> IgniteServices svcs = ignite.services(ignite.cluster().forServers());
> svcs.deployClusterSingleton(TestService.name, new TestServiceImpl());
>
>
>

Reply via email to