Teach&WK_Platform_record
目的:记录项目 platform 开发问题及解决方案
1.问题归纳及总结
1. foreground system
1.1. Spring Web; present 页面重定向问题 (fixed)
1.2 Spring boot-RabbitMQ config; infrastructure, message transfer system -- Spring boot-RabbitMQ config ack confirm, return ( 处理中)
1.3 Spring bean 生命周期; @Scope, request, prototype webApplication.... (fixed)
2. BRMS system
2.1 Java8 Steam ; parallel 数据失效, fixed
1.1 Spring Web

普通的页面 controller 与 RestController 分隔开,
1.2 Spring boot RabbitMQ integration
1. 配置 ConfirmCallBack, ReturnCallBack
2. Sender 在发送消息时候的设置, listener 在接收到信息时的 basicAck , 出现异常时的 reject, naAck



1.3 Spring 注解生成新实例无效, 处理中.....



2. Integration foreground 接收BRMS返回数据无效, BRMS 的在以 performance 创建 baseLine 时 parallelStream() 数据失信,
以及类似的 并行Stream().
2021-01-01 23:48:45
Web controller taskExecutor 的使用报错问题, 需后续处理
java.lang.IllegalStateException: No thread-bound request found:
Are you referring to request attributes outside of an actual web request,
or processing a request outside of the originally receiving thread?
If you are actually operating within a web request and still receive this message,
your code is probably running outside of DispatcherServlet: In this case,
use RequestContextListener or RequestContextFilter to expose the current request.



Spring bean Scope 作用域的问题 2021-01-02 00:24:12
问题已解决:
- spring web controller request scope , invoke present 之后自会在request生效. 不要额外加 @Scope
- repository 应对数据一次处理完,而非相同的数据两次处理,然后在内部维护了状态,此为根源。数据重复。
- infrastructure rabbitmq 后续验证@scope("prototype") 是否也是必须。
1. spring controller , resetController 分开,注入的present 不会受影响。






2 repository isParseCompleted == true


延申参考《Spring 实战》 p86 Web 使用会话和请求作用域
以电商情景为例,购物车,如果是单例,则所有用户商品均加到单例购物车里。
如果是原型,则应用中某一个地方往购物车中添加商品,在应用的另一个地方则不可用。
就购物车bean 来说,会话 session作用域最为合适
@Component
@Scope( value=WebApplicationContext.SCOPE_SESSION, proxyModel=ScopedProxyMode.Innterfaces)
Spring Boot IDEA 运行正常,但是打包为 jar 后,采用内置 tomcat 发生页面跳转 pending..
经查是 facade while( xx == null ) { } ,阻塞。

2. BRMS system
2.1 Java8 Steam ; parallel 数据失效, fixed



2021-01-11 19:53:24
Persent 前端显示时, 合并相同内容的行. jqGrid, merge cell
技术实现思路:
1. 获取当前 table 的所有 dataIDs()
2.遍历该集合,比较上下行的指定 column 内容,因此要求: 1. gridComplete() ,其他事项完成,2.数据有序。
3. 如果相同,调用 api rowspan 设置



实践中出现错行情况, 搜集信息: key: true 等情况验证

在解决前端页面合并单元格时,jqGrid subGrid
其思路是
1. 数据组织成两个 数据集,子数据集的id 与 父数据集 关联。
2. 主Grid 和 subGrid 各自加载相应的数据集.


2021-01-17 10:41:18
platform - forground 并发环境下注意
1. ConcurrencyHashMap, 替代同步且基于散列的Map,
以及CopyOnWriteArrayList,用于遍历操作为主要操作的情况下代替同步的List.
新的 ConcurrentMap 接口增加了对一些常见复合操作的支持,例如“若没有则添加”,替换,以及有条件删除。
ConcurrentSkipListMap 替代 SortedMap
ConcurrentSkipListSet 替代 SotedSet
synchronizedMap 包装的 TreeMap 或 TreeSet
2. Queue 和 BlockingQueue
ConcurrentLinkedQueue 传统的先进先出, PriorityQueue (非并发)优先队列。
BlockingQueue 可阻塞的插入和获取。”生产者-消费者“设计模式中,非常有用。
ConcurrentHashMap 使用了一种不同的加锁策略来提供更高的并发性和伸缩性。
并不是将每一个方法都在同一个锁上同步并使得每次只能有一个线程访问容器。
而是使用粒度更细的加锁机制来实现更大程度的共享,这种机制被称为 分段锁 Lock Striping.
这种机制下,任意数量的读线程可以并发地访问Map,
执行读取操作的线程和执行写入操作的线程可以并发地访问Map,并且一定数量的写入线程可以并发地修改Map.
在并发环境下将实现更高的吞吐量,在单机环境下只损失非常小的性能。
提供的迭代器不会抛出 ConcurrentModificationException, 因此不需要再迭代过程中加锁。
返回的迭代器具有弱一致性,并非”及时失败“。
弱一致性的迭代器可以容忍并发的修改,当创建迭代器时会遍历已有元素,并可以(但不保证)在迭代器被构造后
将修改操作反映给容器。
size() 和 isEmpty() 会过期。但在并发环境下用处少,让位于 get, put, containsKey 和 remove
Hashtable 和 synchronizedMap中,获得Map的锁能防止其他线程访问这个Map. 例如通过原子方式添加一些映射,
或者对Map迭代若干次并在此期间保持元素顺序相同。

CopyOnWriteArrayList CopyOnWriteArraySet
”Copy-on-Write" 容器的线程安全性在于,只要正确地发布一个事实不变的对象,在访问对象时就不需要进一步 的同步。
在每次修改时,都会创建并重新发布一个新的容器副本,从而实现可变性。
“写入时复制”容器的迭代器保留一个指向底层基础数组的引用,这个数组当前位于迭代器的起始位置,由于它不会被修改,因此
在对其进行同步时只需确保数组内容的可见性。因此,多个线程可以同时对这个容器进行迭代,而不会彼此干扰或者与修改容器
的线程相互干扰。
容器返回的迭代器不会抛出 ConcurrentModificationException,且返回的元素与迭代器创建时的元素完全一致,而不必考虑之后
修改操作所带来的影响。
每当修改容器时都会复制底层数组。需要一定的开销。
提供了更好的并发性能,并且在迭代期间不需要对容器进行加锁或复制。
当容器的规模较大时,仅当迭代操作远远多于修改操作时,才应该使用”写入时复制“容器。
准测的运用---
事件通知系统:在分发通知时需要迭代已注册监听器链表,并调用每一个监听器,
在大多数情况下,注册和注销事件监听器的操作远少于接收事件通知的操作。
阻塞队列 和 生产者 - 消费者 模式
生产者-消费者模式 消除了生产者类 和 消费者类之间的代码依赖性,该模式将生产数据的过程与使用数据的过程解耦
以简化工作负载的管理,这两个过程在处理数据的速率有所不同.
BlockingQueue 简化了生产者-消费者设计的实现过程,支持任意数量的生产者和消费者,常见的生产者-消费者设计模式就是
线程池与工作队列的组合,在Executor任务执行框架中就体现了这种模式。
如果生产者生成工作的速率比消费者处理工作的速率快,则工作项会在队列中累积起来,最终耗尽内存。
put 方法的阻塞特性也极大地简化了生产者的编码,使用有界队列,则当队列充满时,生产者将阻塞且不能继续生成工作,
而消费者就有时间赶上工作处理进度。
阻塞队列提供了一个offer方法,如果数据项不能被添加到队列中,那么将返回一个失败状态.就能够创建灵活的策略来处理:
减轻负载,将多余的工作项序列化到磁盘,减少生产者线程的数量,或通过某种方式来一致生产者线程.
在构建高可靠的应用程序时,有界队列是一种强大的资源管理工具:它们能一致并防止
产生过多的工作项,使应用程序在负荷过载的情况下变得更加强壮。
生产者,消费者的行为会通过共享队列间接地耦合在一起,
不能架构消费者处理工作的速率能赶上生产者生成工作项的速率,不为工作队列设置边界,将导致在之后
重新设计系统架构.
应尽早地通过阻塞队列在设计中构建资源管理机制--这件事做得越早,越容易.
如果阻塞队列不完全符合设计需求,通过信号量(Semaphore) 来创建其他的阻塞数据结构。
LinkedBlockingQueue 和 ArrayBlockingQueue, 类似于LinkedList 和 ArrayList, 但比同步List有更好的并发性能.
PriorityBlockingQueue 优先级队列,既可根据元素的自然顺序来比较(实现了Comparable 方法),也可以使用Comparator来比较。
SynchronousQueue 维护一组线程,在等待着将元素加入或移出队列。可以直接降低将数据从生产者移动到消费者的延迟。
没有存储功能,使用场景:
有足够多的消费者,并且总是有一个消费者准备好交付工作时,才适合使用同步队列。

浙公网安备 33010602011771号