Java 提高使用多个微服务填充材质爆炸树性能的方法
我想做一次物质爆炸。这意味着给定一个产品,我希望填充到一个树中,该树包含生产该产品所需的所有子组件。比如说制作一张桌子,我需要一个桌面,四条腿,8个螺丝和一罐油漆。因此,一旦我有了这些信息,我就可以通过将10乘以构建1个表所需的数量来理解构建10个表需要多少这些子组件 因此,给定一个材质,我首先将其填充为根节点,然后递归地获取子组件并开始构建树。我的限制是,当我从另一个服务获取这些信息时,我只能获取直接的子项,这意味着在单个级别上的子项 我的N数组树的结构如下所示:Java 提高使用多个微服务填充材质爆炸树性能的方法,java,algorithm,performance,architecture,microservices,Java,Algorithm,Performance,Architecture,Microservices,我想做一次物质爆炸。这意味着给定一个产品,我希望填充到一个树中,该树包含生产该产品所需的所有子组件。比如说制作一张桌子,我需要一个桌面,四条腿,8个螺丝和一罐油漆。因此,一旦我有了这些信息,我就可以通过将10乘以构建1个表所需的数量来理解构建10个表需要多少这些子组件 因此,给定一个材质,我首先将其填充为根节点,然后递归地获取子组件并开始构建树。我的限制是,当我从另一个服务获取这些信息时,我只能获取直接的子项,这意味着在单个级别上的子项 我的N数组树的结构如下所示: public class N
public class Node<T> {
private T data = null;
private Node<T> parent = null;
private List<Node<T>> children = new ArrayList<Node<T>>();
public Node(T data) {
this.data = data;
}
public Node(T data, Node<T> parent) {
this.data = data;
this.parent = parent;
}
public List<Node<T>> getChildren() {
return children;
}
public Node<T> getParent() {
return parent;
}
public void setParent(Node<T> parent) {
this.parent = parent;
}
public void addChild(T data) {
Node<T> child = new Node<T>(data);
this.addChild(child);
}
public void addChild(Node<T> child) {
child.setParent(this);
this.children.add(child);
}
public void addChildren(List<Node<T>> children) {
for (Node t : children) {
t.setParent(this);
}
this.children.addAll(children);
}
public T getData() {
return this.data;
}
public void setData(T data) {
this.data = data;
}
public boolean isRoot() {
return (this.parent == null);
}
public boolean isLeaf() {
return this.children.size() == 0;
}
public void removeParent() {
this.parent = null;
}
private class InOrderIterator implements Iterator<T> {
private final Queue<Node<T>> queue = new LinkedList<Node<T>>();
public InOrderIterator(Node<T> tree) {
queue.add(tree);
}
@Override
public boolean hasNext() {
return !queue.isEmpty();
}
@Override
public T next() {
Node<T> node = queue.remove();
queue.addAll(node.children);
return node.getData();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
public Iterable<T> inOrderTraversal = () -> (Iterator<T>) new InOrderIterator(Node.this);
}
公共类节点{
私有T数据=null;
私有节点父节点=null;
private List children=new ArrayList();
公共节点(T数据){
这个数据=数据;
}
公共节点(T数据,节点父节点){
这个数据=数据;
this.parent=parent;
}
公共列表getChildren(){
返回儿童;
}
公共节点getParent(){
返回父母;
}
公共void setParent(节点父节点){
this.parent=parent;
}
公共void addChild(T数据){
节点子节点=新节点(数据);
这个.addChild(child);
}
公共void addChild(节点子节点){
child.setParent(this);
this.children.add(child);
}
公共子项(列出子项){
用于(节点t:子节点){
t、 setParent(本);
}
this.children.addAll(children);
}
公共T getData(){
返回此.data;
}
公共无效设置数据(T数据){
这个数据=数据;
}
公共布尔值isRoot(){
返回(this.parent==null);
}
公共布尔isLeaf(){
返回此.children.size()==0;
}
public void removeParent(){
this.parent=null;
}
私有类InOrderIterator实现迭代器{
private final Queue=new LinkedList();
公共索引编者(节点树){
添加(树);
}
@凌驾
公共布尔hasNext(){
return!queue.isEmpty();
}
@凌驾
公共交通工具{
Node=queue.remove();
queue.addAll(node.children);
返回node.getData();
}
@凌驾
公共空间删除(){
抛出新的UnsupportedOperationException();
}
}
public Iterable inOrderTraversal=()->(迭代器)new inordereditor(Node.this);
}
现在我创建根节点,这里的最大深度是我想要获取子组件并构建树的树级别。默认数量为1,根级别为0
protected Node<Material> doMaterialExplosion(final String partNumber, final Integer maxDepth) {
Node<Material> root = new Node<>(Material.builder()
.productPartNumber(partNumber)
.materialPartNumber(partNumber)
.materialQuantity(DEFAULT_QUANTITY)
.level(ROOT_LEVEL)
.parentPartNumber(null)
.build());
return doMaterialExplosion(root, partNumber, maxDepth);
}
受保护节点域爆炸(最终字符串零件号,最终整数maxDepth){
节点根=新节点(Material.builder()
.productPartNumber(零件号)
.材料零件号(零件号)
.物料数量(默认数量)
.级别(根级别)
.parentPartNumber(空)
.build());
返回域材料爆炸(根、零件号、最大深度);
}
产品零件号是必须生产的主要产品,材料零件号是生产该产品所需的子组件,材料数量是所需材料的数量,级别是树级别,父零件号是子组件的直接父级。因此,对于根节点,将没有父零件号,但对于所有其他子组件,将有一个父零件号。另外,请注意,产品零件号在任何节点中都不会更改,因为它指定了正在生产的主要产品。
递归构造此树的代码段为:
private Node<Material> doMaterialExplosion(Node<Material> root,
final String partNumber, final Integer maxDepth) {
// Increment the level, in the tree
int childLevel = root.getData().getLevel() + 1;
if (maxDepth != null && childLevel <= maxDepth) {
// Fetch immediate sub-components, of a given material
List<SubComponent> subComponents = fetchData(partNumber);
Node<Material> child;
if (!subComponents.isEmpty()) {
LOG.info("'{}' child elements found for partNumber='{}'", subComponents.size(), partNumber);
for (SubComponents subComponent : subComponents) {
child = new Node<>(Material.builder()
.productPartNumber(root.getData().getProductPartNumber())
.materialPartNumber(subComponent.getMaterial())
.materialQuantity(subComponent.getMaterialQuantity())
.level(childLevel)
.parentPartNumber(root.getData().getMaterialPartNumber())
.build(), root);
root.addChild(child);
doMaterialExplosion(child, subComponent.getMaterial(), maxDepth);
}
}
}
return root;
}
私有节点域爆炸(节点根、,
最终字符串零件号,最终整数maxDepth){
//在树中增加级别
int childLevel=root.getData().getLevel()+1;
如果(maxDepth!=null&&childLevel您的体系结构允许您改进的唯一一件事是,在获取产品时,您可以记忆您已经获取的内容。因此,如果一个表有4个支腿,您可以获取一个表,一个支腿一次,然后应用支腿4x。然后,当您查找另一个表时,您只需查找它。数据共享通常比较困难但是我们在这里保留微服务架构是对的
我可以看到两种方式(然后可能是两种方式的混合):
- 增强第二个微服务API,这样您就可以从中获取项目列表,而不是逐个请求(请求机关枪!)。
它正在成为一种常见的API特性……可以将其视为对id的搜索,或者以GraphQL的方式
- 按照btilly的建议,在您的第一个微服务上组织一个缓存,可能更具攻击性。根据您以前的请求在内存中或在主微服务提供的本地数据库(nosql?)中组织一个缓存
性能最大的改进是:使第二个微服务不必通过网络从第一个微服务获取数据。让第二个微服务直接访问第一个微服务的数据库,或者使其完全相同。是的,我想过,但我没有违反基本原则吗这里是cs,也就是说…两个微服务不应该访问同一个数据库,每个微服务应该有自己的数据库?软件开发中的一切都是一种权衡;没有绝对。当你承诺“纯”微服务体系结构,您会得到更高的复杂性和性能损失,但会获得可维护性和可扩展性。我更喜欢实用主义而不是纯粹性。谢谢Robert的建议