在外部服务器设置中使用SDN 3.3.1和Neo4j 2.1.7。
每当我执行以下执行模式时,我都有java.net.SocketTimeoutException: Read timed out
:
MyEntity entity = myRepository.findByUuid(uuid);
neo4jOperations.query("match (e{uuid:"theuuid"})<-[r:THE_RELATION]-() delete r);
entity.setTitle("New title");
myRepository.save(entity);
- &gt; 等了很长时间才得到 SocketTimeoutException
经过一些分析后,在我看来 1。在事务外的 AND 内进行http调用,正如您在此Neo4j http日志提取中所看到的那样:
127.0.0.1 - - [20/août/2015:10:47:57 +0200] "POST /db/data/transaction HTTP/1.1" 201 659 "-" "neo4j-rest-graphdb/0"
127.0.0.1 - - [20/août/2015:10:47:57 +0200] "GET /db/data/node/135/relationships/in/WITH_ROLE HTTP/1.1" 200 391 "-" "neo4j-rest-graphdb/0"
127.0.0.1 - - [20/août/2015:10:47:57 +0200] "GET /db/data/node/149 HTTP/1.1" 200 1780 "-" "neo4j-rest-graphdb/0"
127.0.0.1 - - [20/août/2015:10:47:57 +0200] "GET /db/data/node/135/relationships/out/DEFAULT_ENTITY HTTP/1.1" 200 401 "-" "neo4j-rest-graphdb/0"
127.0.0.1 - - [20/août/2015:10:47:57 +0200] "GET /db/data/node/227 HTTP/1.1" 200 1884 "-" "neo4j-rest-graphdb/0"
127.0.0.1 - - [20/août/2015:10:47:57 +0200] "GET /db/data/node/135/relationships/in/WITH_PENDING_ROLE HTTP/1.1" 200 2 "-" "neo4j-rest-graphdb/0"
所以我的第一个问题是:
然后, 2。中的删除操作在事务中正确完成:
127.0.0.1 - - [20/août/2015:10:47:58 +0200] "POST /db/data/transaction/2720 HTTP/1.1" 200 254 "-" "neo4j-rest-graphdb/0"
点 3。显然不会生成http请求。
最后,点 4。在被&#34;阻止后生成SocketTimeoutException
&#34;一段时间(确切地说是30秒),最终生成2个http请求:
127.0.0.1 - - [20/août/2015:10:48:28 +0200] "DELETE /db/data/transaction/2720 HTTP/1.1" 200 26 "-" "neo4j-rest-graphdb/0"
127.0.0.1 - - [20/août/2015:10:48:28 +0200] "PUT /db/data/node/135/properties HTTP/1.1" 204 0 "-" "neo4j-rest-graphdb/0"
删除是因为事务是回滚的,我认为PUT对应于save()
在我看来,由于PUT在交易之外,因此发生了死锁! 所以,主要的问题是:
save()
在事务之外进行PUT而不是事务内的POST?有没有办法强制使用事务端点完成实体更新?谢谢:)
编辑:添加了SDN配置
<beans ...>
<tx:annotation-driven />
<context:component-scan base-package="com.myproject.mw.neo4j.service,com.myproject.mw.neo4j.aspect" />
<aop:aspectj-autoproxy />
<!-- External database config -->
<bean id="graphDatabaseServiceExternal" class="org.springframework.data.neo4j.rest.SpringCypherRestGraphDatabase"
lazy-init="true">
<constructor-arg index="0" value="${neo4j.path}" />
</bean>
<alias name="graphDatabaseService${neo4j.mode}" alias="graphDatabaseService" />
<neo4j:config base-package="com.myproject.mw.neo4j.domain"
graphDatabaseService="graphDatabaseService" />
<neo4j:repositories base-package="com.myproject.mw.neo4j.repository" />
</beans>
EDIT 2 :添加实体定义和简单测试以重现
请注意,我的Neo4j服务器位于localhost。
测试:
@Test
@Transactional
@Rollback(false)
public void testEntityNotFound() {
BusinessCard card = genericRepository.findByUuid("4bce6162-bc6f-bce2-bc71-bc70b63dff00");
Entity entity = genericRepository.findByUuid("04947df8-0e9e-4471-a2f9-9af509fb5889");
neo4jOperations.createRelationshipBetween(neo4jOperations.getNode(entity.getId()),
neo4jOperations.getNode(card.getId()), "FAKE2", null);
neo4jOperations.save(card);
}
BusinessCard实体:
public class BusinessCard extends GenericNode {
@Indexed
private String title;
@RelatedTo(type = RelationNames.WITH_ROLE, direction = Direction.INCOMING)
private User user;
@RelatedTo(type = RelationNames.WITH_PENDING_ROLE, direction = Direction.INCOMING)
private User pendingUser;
@RelatedTo(type = RelationNames.DEFAULT_ENTITY)
private Entity defaultEntity;
}
实体实体:
public class Entity extends GenericNode {
private String logo;
@Indexed
private String entityName;
@RelatedTo(type = RelationNames.IS_IN_CITY)
private CityNode mainCity;
@RelatedTo(type = RelationNames.IS_IN_COUNTRY)
private CountryNode mainCountry;
@RelatedTo(type = RelationNames.IS_IN_COUNTRIES)
private Set<CountryNode> countries;
@Fetch
@RelatedToVia(type = RelationNames.TRANSLATION)
private Set<EntityToEntityTranslatedContent> entityTranslatedContent;
@Fetch
@RelatedTo(type = RelationNames.HAS_KEY_STAGES)
private KeyStage lastKeyStage;
@GraphProperty(propertyType = Long.class)
private Date lastProfileUpdateDateTime;
private Integer profilCompletionIndice;
@RelatedToVia(type = RelationNames.WORKS_AT, direction = Direction.INCOMING)
private Set<BusinessCardWorkAt> employees = new HashSet<>();
...+34 more fields...
}
答案 0 :(得分:1)
我假设您使用的是org.springframework.data.neo4j.rest.SpringRestGraphDatabase
,现已弃用,并且不支持正确的交易。 (参见生成PUT的this代码)
有一个新的基于密码的数据库org.springframework.data.neo4j.rest.SpringCypherRestGraphDatabase
,它可能会做你想要的。
您还希望了解4.x版本,这是对SDN的一次改革,重点是以更有效的方式远程使用neo4j。它应该很快就会进入GA。
此博客http://jexp.de/blog/2014/12/spring-data-neo4j-improving-remoting-performance/
提供了更多解释答案 1 :(得分:0)
然后,您的实体出现了一些问题,似乎花了很多时间将数据写入服务器。来自你的线程转储:
at org.neo4j.rest.graphdb.ExecutingRestRequest.put(ExecutingRestRequest.java:155)
at org.neo4j.rest.graphdb.RestAPIImpl.setPropertiesOnEntity(RestAPIImpl.java:633)
at org.neo4j.rest.graphdb.entity.RestEntity.flush(RestEntity.java:189)
at org.springframework.data.neo4j.support.mapping.SourceStateTransmitter.copyPropertiesTo(SourceStateTransmitter.java:109)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityConverterImpl.write(Neo4jEntityConverterImpl.java:170)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister$CachedConverter.write(Neo4jEntityPersister.java:179)
和转储2:
at org.neo4j.rest.graphdb.ExecutingRestRequest.put(ExecutingRestRequest.java:155)
at org.neo4j.rest.graphdb.RestAPIImpl.setPropertiesOnEntity(RestAPIImpl.java:633)
at org.neo4j.rest.graphdb.entity.RestEntity.flush(RestEntity.java:189)
at org.springframework.data.neo4j.support.mapping.SourceStateTransmitter.copyPropertiesTo(SourceStateTransmitter.java:109)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityConverterImpl.write(Neo4jEntityConverterImpl.java:170)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister$CachedConverter.write(Neo4jEntityPersister.java:179)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.persist(Neo4jEntityPersister.java:247)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.persist(Neo4jEntityPersister.java:235)
at org.springframework.data.neo4j.support.Neo4jTemplate.save(Neo4jTemplate.java:365)
还必须有其他东西,因为
org.springframework.data.neo4j.rest.SpringCypherRestGraphDatabase
应该 NOT 使用普通的Rest端点和GET,PUT,DELETE等,但只是普通的Cypher。
您还应该检查服务器的延迟和带宽,SDN3仍然非常繁琐。
因此,您应该共享实体的代码,您在调用该保存之前/之后的确切操作以及将多少数据发送到服务器。
为了获得更好的SDN + Server体验,我建议您查看为此目的从头开始编写的SDN4。 SDN4 RC2于上周五发布:
http://docs.spring.io/spring-data/neo4j/docs/4.0.0.RC2/reference/html/
答案 2 :(得分:0)
这已在SDN 3.4中修复(见https://jira.spring.io/browse/DATAGRAPH-699)。 此jira票证内容是一个不同的主题,但您可以依赖修改后的标题“单独为基于Cypher的REST-API实现缺少的操作”。 从3.4开始,使用@Transactional时不再有超出事务的REST请求。