常规和 Spring 抽象的 Ignite 事务失败并出现 IllegalStateException post 手动重新连接 clientReconnectDisabled 为真

Regular & Spring abstracted Ignite transactions fail with IllegalStateException post manual reconnect with clientReconnectDisabled as true

我们是 运行 2.4 版并使用 Spring IgniteSpringBean, SpringTransactionManager & Spring Data 存储库进行集群和事务缓存访问。

由于我们遇到了很多与 IgniteClientDisconnectedException 相关的问题,我正在编写一个手动分段解析器(通过禁用自动客户端重新连接并将 clientReconnectDisabled 设置为 true)来检测这种情况(使用定期运行的简单缓存查询) ) 并通过 IgniteSpringBean#close followed by a reconnect as described

发起断开连接

我在缓存访问方面遇到了其他问题,我已按照描述解决了这些问题

但问题是,每当我尝试使用 spring 事务注释方法时,它都无法创建带有 IllegalStateException 的事务,指出网格处于无效状态。

我怀疑它又是我之前遇到的相同问题(上面提到过),引用过时,可能需要通过更新 SpringTransactionManager 中的内核引用来在代码中处理它。我正在尝试该修复程序,如果有效,我会更新。

同时,如果有人有 easier/quicker 修复 approach/suggestion,请分享。

以下是例外,

com.***.dcm.exception.InternalServerErrorException: Error while creating the definition. Message is : Could not create Ignite transaction; nested exception is java.lang.IllegalStateException: Grid is in invalid state to perform this operation. It either not started yet or has already being or have stopped [igniteInstanceName=null, state=STOPPED]
    at com.***.dcm.topology.middleware.controller.TopologyServiceControllerHelper.createTopologyDefinition(TopologyServiceControllerHelper.java:124)
    at com.***.dcm.topology.middleware.controller.TopologyServiceController.createTopologyDefinition(TopologyServiceController.java:129)
2018-07-24 14:11:00.519 ERROR b731ba99e9b2 --- [nio-7099-exec-1] .d.t.m.c.TopologyServiceControllerHelper : Error while creating the definition. Message is : Could not create Ignite transaction; nested exception is java.lang.IllegalStateException: Grid is in invalid state to perform this operation. It either not started yet or has already being or have stopped [igniteInstanceName=null, state=STOPPED]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:474)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:783)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:798)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1434)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)

我之前提到的修复有效。对于可能面临此问题的其他人,修复涉及更新 SpringTransactionManager 中的 ignite 内核引用 post 重新连接。

以下是所需的代码更改,

在SpringTransactionManager.java,

/**
 * @author mlekshma
 * 
 * @param ignite
 */
protected void setResourceFactory(final Ignite ignite) {
    this.ignite = ignite;
}

我正在使用 SpringTransactionManager 的匿名内部 class 来破解注入,因为 ignite-spring 2.4 中的集成问题(更多关于 ),

/**
 * @author mlekshma
 *
 */
@Configuration
@EnableScheduling
@ComponentScan("com.***.***")
@EnableIgniteRepositories(basePackages={"com.***.***"})
@ImportResource("classpath:ignite-client-conf.xml")
@PropertySource("classpath:ignite-client.properties")
@EnableTransactionManagement
public class IgniteClientConfig {

    private static final Logger LOGGER = LoggerFactory.getLogger(IgniteClientConfig.class);

    public IgniteClientConfig() {
    }

    /**
     * @return
     */
    @Bean
    @DependsOn("igniteInstance")
    @Primary
    @Lazy
    public PlatformTransactionManager transactionManager() {
        final SpringTransactionManager springTransactionManager = new SpringTransactionManager() {

            private boolean isInitialized = false;

            @Override 
            public void afterPropertiesSet() throws Exception {
                if (isInitialized) {
                    if(((IgniteKernal) getResourceFactory()).context().gateway().getState() == GridKernalState.STOPPED) {
                        IgniteKernal igniteKernal = (IgniteKernal) Ignition.ignite(getIgniteInstanceName());
                        if(igniteKernal != null) {
                            setResourceFactory(igniteKernal);
                        }
                    }
                }
            }

            /**
             * @param event
             */
            @EventListener
            public void handleContextRefresh(final ContextRefreshedEvent event) throws Exception {
                LOGGER.info("Setting up tx support..");
                super.afterPropertiesSet();
                isInitialized = true;
            }
        };
        // Use default grid client instance created..
        springTransactionManager.setTransactionConcurrency(TransactionConcurrency.PESSIMISTIC);
        return springTransactionManager;
    }

}

2.5版本修复重连后关闭缓存问题( https://issues.apache.org/jira/browse/IGNITE-2766).

据我了解,您想创建一个新的 ignite 实例并将一个实例用于 SpringTransactionManager。 我认为这不是正确的方法,因为例如 IgniteRepositoryImpl#cache 中的缓存实例也需要重新初始化。

我推荐使用 IgniteClientDisconnectedException#reconnectFuture() returns 重新连接发生时将完成的未来方法。 因此,您可以阻止客户端并等到未来得到解决并且客户端变得活跃。 例如:

public void checkAndReconnect(){
    try{
        // make ignite query
    }catch(IgniteClientDisconnectedException ex){
       ex.reconnectFuture().get();
    }
}

希望对解决连接问题有所帮助。