- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个Spring Boot Web应用程序,该应用程序具有更新名为StudioLinking
的实体的功能。此实体描述了两个IoT设备之间的临时,可变,描述性逻辑链接,我的Web应用程序是它们的云服务。这些设备之间的链接本质上是短暂的,但是StudioLinking
实体保留在数据库中以用于报告。使用Spring Data / Hibernate以传统方式将StudioLinking
存储到基于SQL的数据存储中。该StudioLinking实体会不时地使用来自Rest API的新信息进行更新。链接更新后,设备需要响应(更改颜色,音量等)。现在,通过每5秒轮询一次来进行处理,但这会造成人类用户向系统中输入更新以及IoT设备实际更新时的延迟。可能只有一毫秒或最多5秒!显然,增加轮询的频率是不可持续的,并且绝大多数时间根本没有更新!
因此,我正在尝试使用HTTP Long Polling在同一应用程序上开发另一个Rest API,该API将在给定StudioLinking实体更新或超时后返回。侦听器不支持WebSocket或类似功能,使我无法进行Long Polling。长轮询可能会导致竞争状态,在这种情况下,您必须考虑以下可能性:对于连续消息,一条消息可能会在HTTP请求之间进入时“丢失”(在关闭和打开连接时,可能会出现新的“更新”如果使用发布/订阅,则不会被“注意到”)。
重要的是要注意,此“订阅更新” API应该只返回StudioLinking
的LATEST和CURRENT版本,但仅当存在实际更新或自上次 checkin 后发生更新时才这样做。 “订阅更新”客户端将首先发布API请求,以设置新的侦听 session 并将其传递,以便服务器知道它们是谁。因为可能有多个设备需要监视对同一个StudioLinking
实体的更新。我相信我可以通过在Redis XREAD中使用单独命名的使用者来完成此操作。 (请牢记这一点,以供稍后在问题中使用)
经过数小时的研究,我相信完成此操作的方法是使用redis流。
我在Spring Data Redis中找到了有关Redis流的以下两个链接:
https://www.vinsguru.com/redis-reactive-stream-real-time-producing-consuming-streams-with-spring-boot/
https://medium.com/@amitptl.in/redis-stream-in-action-using-java-and-spring-data-redis-a73257f9a281
我还阅读了有关长轮询的链接,这两个链接在长轮询期间都只有一个睡眠计时器,用于演示,但显然我想做一些有用的事情。
https://www.baeldung.com/spring-deferred-result
这两个链接都非常有帮助。现在,我很清楚如何将更新发布到Redis Stream上-(这是未经测试的“伪代码”,但我预计实现此目的不会有任何问题)
// In my StudioLinking Entity
@PostUpdate
public void postToRedis() {
StudioLinking link = this;
ObjectRecord<String, StudioLinking> record = StreamRecords.newRecord()
.ofObject(link)
.withStreamKey(streamKey); //I am creating a stream for each individual linking probably?
this.redisTemplate
.opsForStream()
.add(record)
.subscribe(System.out::println);
atomicInteger.incrementAndGet();
}
但是当涉及到上述流时,我会保持一致:所以基本上我想在这里做-请原谅伪造的伪代码,这仅出于想法目的。我很清楚,代码绝不表示语言和框架的实际行为:)
// Parameter studioLinkingID refers to the StudioLinking that the requester wants to monitor
// updateList is a unique token to track individual consumers in Redis
@GetMapping("/subscribe-to-updates/{linkId}/{updatesId}")
public DeferredResult<ResponseEntity<?>> subscribeToUpdates(@PathVariable("linkId") Integer linkId, @PathVariable("updatesId") Integer updatesId) {
LOG.info("Received async-deferredresult request");
DeferredResult<ResponseEntity<?>> output = new DeferredResult<>(5000l);
deferredResult.onTimeout(() ->
deferredResult.setErrorResult(
ResponseEntity.status(HttpStatus.REQUEST_TIMEOUT)
.body("IT WAS NOT UPDATED!")));
ForkJoinPool.commonPool().submit(() -> {
//----------------------------------------------
// Made up stuff... here is where I want to subscribe to a stream and block!
//----------------------------------------------
LOG.info("Processing in separate thread");
try {
// Subscribe to Redis Stream, get any updates that happened between long-polls
// then block until/if a new message comes over the stream
var subscription = listenerContainer.receiveAutoAck(
Consumer.from(studioLinkingID, updateList),
StreamOffset.create(studioLinkingID, ReadOffset.lastConsumed()),
streamListener);
listenerContainer.start();
} catch (InterruptedException e) {
}
output.setResult("IT WAS UPDATED!");
});
LOG.info("servlet thread freed");
return output;
}
因此,对于我将如何解决这个问题,是否有很好的解释?我认为答案就在
https://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/ReactiveRedisTemplate.html之内,但是我对Spring的熟练程度还不足以真正理解Java Docs中的术语(Spring文档确实很好,但是JavaDocs是用密集的技术语言编写的,对此我表示赞赏,但我不愿意相当了解)。
StudioLinking
是短暂的,因此我也需要进行一些清理。一旦我将整个事情付诸实践,我将在稍后实现,我确实知道将需要它。 最佳答案
为什么不使用阻塞式轮询机制?无需使用spring-data-redis的高级工具。只需使用5秒钟的简单阻塞读取,所以此调用可能需要6秒钟左右的时间。您可以减少或增加阻止超时。
class LinkStatus {
private final boolean updated;
LinkStatus(boolean updated) {
this.updated = updated;
}
}
// Parameter studioLinkingID refers to the StudioLinking that the requester wants to monitor
// updateList is a unique token to track individual consumers in Redis
@GetMapping("/subscribe-to-updates/{linkId}/{updatesId}")
public LinkStatus subscribeToUpdates(
@PathVariable("linkId") Integer linkId, @PathVariable("updatesId") Integer updatesId) {
StreamOperations<String, String, String> op = redisTemplate.opsForStream();
Consumer consumer = Consumer.from("test-group", "test-consumer");
// auto ack block stream read with size 1 with timeout of 5 seconds
StreamReadOptions readOptions = StreamReadOptions.empty().block(Duration.ofSeconds(5)).count(1);
List<MapRecord<String, String, String>> records =
op.read(consumer, readOptions, StreamOffset.latest("test-stream"));
return new LinkStatus(!CollectionUtils.isEmpty(records));
}
关于java - 在Spring Boot App中使用Redis Stream通过HTTP长轮询来阻止HTTP响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63555265/
我需要将文本放在 中在一个 Div 中,在另一个 Div 中,在另一个 Div 中。所以这是它的样子: #document Change PIN
奇怪的事情发生了。 我有一个基本的 html 代码。 html,头部, body 。(因为我收到了一些反对票,这里是完整的代码) 这是我的CSS: html { backgroun
我正在尝试将 Assets 中的一组图像加载到 UICollectionview 中存在的 ImageView 中,但每当我运行应用程序时它都会显示错误。而且也没有显示图像。 我在ViewDidLoa
我需要根据带参数的 perl 脚本的输出更改一些环境变量。在 tcsh 中,我可以使用别名命令来评估 perl 脚本的输出。 tcsh: alias setsdk 'eval `/localhome/
我使用 Windows 身份验证创建了一个新的 Blazor(服务器端)应用程序,并使用 IIS Express 运行它。它将显示一条消息“Hello Domain\User!”来自右上方的以下 Ra
这是我的方法 void login(Event event);我想知道 Kotlin 中应该如何 最佳答案 在 Kotlin 中通配符运算符是 * 。它指示编译器它是未知的,但一旦知道,就不会有其他类
看下面的代码 for story in book if story.title.length < 140 - var story
我正在尝试用 C 语言学习字符串处理。我写了一个程序,它存储了一些音乐轨道,并帮助用户检查他/她想到的歌曲是否存在于存储的轨道中。这是通过要求用户输入一串字符来完成的。然后程序使用 strstr()
我正在学习 sscanf 并遇到如下格式字符串: sscanf("%[^:]:%[^*=]%*[*=]%n",a,b,&c); 我理解 %[^:] 部分意味着扫描直到遇到 ':' 并将其分配给 a。:
def char_check(x,y): if (str(x) in y or x.find(y) > -1) or (str(y) in x or y.find(x) > -1):
我有一种情况,我想将文本文件中的现有行包含到一个新 block 中。 line 1 line 2 line in block line 3 line 4 应该变成 line 1 line 2 line
我有一个新项目,我正在尝试设置 Django 调试工具栏。首先,我尝试了快速设置,它只涉及将 'debug_toolbar' 添加到我的已安装应用程序列表中。有了这个,当我转到我的根 URL 时,调试
在 Matlab 中,如果我有一个函数 f,例如签名是 f(a,b,c),我可以创建一个只有一个变量 b 的函数,它将使用固定的 a=a1 和 c=c1 调用 f: g = @(b) f(a1, b,
我不明白为什么 ForEach 中的元素之间有多余的垂直间距在 VStack 里面在 ScrollView 里面使用 GeometryReader 时渲染自定义水平分隔线。 Scrol
我想知道,是否有关于何时使用 session 和 cookie 的指南或最佳实践? 什么应该和什么不应该存储在其中?谢谢! 最佳答案 这些文档很好地了解了 session cookie 的安全问题以及
我在 scipy/numpy 中有一个 Nx3 矩阵,我想用它制作一个 3 维条形图,其中 X 轴和 Y 轴由矩阵的第一列和第二列的值、高度确定每个条形的 是矩阵中的第三列,条形的数量由 N 确定。
假设我用两种不同的方式初始化信号量 sem_init(&randomsem,0,1) sem_init(&randomsem,0,0) 现在, sem_wait(&randomsem) 在这两种情况下
我怀疑该值如何存储在“WORD”中,因为 PStr 包含实际输出。? 既然Pstr中存储的是小写到大写的字母,那么在printf中如何将其给出为“WORD”。有人可以吗?解释一下? #include
我有一个 3x3 数组: var my_array = [[0,1,2], [3,4,5], [6,7,8]]; 并想获得它的第一个 2
我意识到您可以使用如下方式轻松检查焦点: var hasFocus = true; $(window).blur(function(){ hasFocus = false; }); $(win
我是一名优秀的程序员,十分优秀!