Spring Cloud Bus 消息总线介绍

简介: 本文配套可交互教程已登录阿里云知行动手实验室,PC 端登录 start.aliyun.com 在浏览器中立即体验。

头图.png

作者 | 洛夜
来源 | 阿里巴巴云原生公众号

本文配套可交互教程已登录阿里云知行动手实验室,PC 端登录 start.aliyun.com 在浏览器中立即体验

1.png

Spring Cloud Bus 对自己的定位是 Spring Cloud 体系内的消息总线,使用 message broker 来连接分布式系统的所有节点。Bus 官方的 Reference 文档 比较简单,简单到连一张图都没有。

这是最新版的 Spring Cloud Bus 代码结构(代码量比较少):

2.png

Bus 实例演示

在分析 Bus 的实现之前,我们先来看两个使用 Spring Cloud Bus 的简单例子。

1. 所有节点的配置新增

Bus 的例子比较简单,因为 Bus 的 AutoConfiguration 层都有了默认的配置,只需要引入消息中间件对应的 Spring Cloud Stream 以及 Spring Cloud Bus 依赖即可,之后所有启动的应用都会使用同一个 Topic 进行消息的接收和发送。

Bus 对应的 Demo 已经放到了 github 上, 该 Demo 会模拟启动 5 个节点,只需要对其中任意的一个实例新增配置项,所有节点都会新增该配置项。

Demo 地址:https://github.com/fangjian0423/rocketmq-binder-demo/tree/master/rocketmq-bus-demo

访问任意节点提供的 Controller 提供的获取配置的地址(key 为hangzhou):

curl -X GET 'http://localhost:10001/bus/env?key=hangzhou'

所有节点返回的结果都是 unknown,因为所有节点的配置中没有hangzhou这个 key。

Bus 内部提供了EnvironmentBusEndpoint这个 Endpoint 通过 message broker 用来新增/更新配置。

访问任意节点该 Endpoint 对应的 url: /actuator/bus-env?name=hangzhou&value=alibaba 进行配置项的新增(比如访问 node1 的url):

curl -X POST 'http://localhost:10001/actuator/bus-env?name=hangzhou&value=alibaba' -H 'content-type: application/json'

然后再次访问所有节点/bus/env获取配置:

$ curl -X GET 'http://localhost:10001/bus/env?key=hangzhou'
unknown%
~ ⌚
$ curl -X GET 'http://localhost:10002/bus/env?key=hangzhou'
unknown%
~ ⌚
$ curl -X GET 'http://localhost:10003/bus/env?key=hangzhou'
unknown%
~ ⌚
$ curl -X GET 'http://localhost:10004/bus/env?key=hangzhou'
unknown%
~ ⌚
$ curl -X GET 'http://localhost:10005/bus/env?key=hangzhou'
unknown%
~ ⌚
$ curl -X POST 'http://localhost:10001/actuator/bus-env?name=hangzhou&value=alibaba' -H 'content-type: application/json'
~ ⌚
$ curl -X GET 'http://localhost:10005/bus/env?key=hangzhou'
alibaba%
~ ⌚
$ curl -X GET 'http://localhost:10004/bus/env?key=hangzhou'
alibaba%
~ ⌚
$ curl -X GET 'http://localhost:10003/bus/env?key=hangzhou'
alibaba%
~ ⌚
$ curl -X GET 'http://localhost:10002/bus/env?key=hangzhou'
alibaba%
~ ⌚
$ curl -X GET 'http://localhost:10001/bus/env?key=hangzhou'
alibaba%

可以看到,所有节点都新增了一个 key 为hangzhou的配置,且对应的 value 是alibaba。这个配置项是通过 Bus 提供的 EnvironmentBusEndpoint 完成的。

这里引用 程序猿DD 画的一张图片,Spring Cloud Config 配合 Bus 完成所有节点配置的刷新来描述之前的实例(本文实例不是刷新,而是新增配置,但是流程是一样的):

3.png

2. 部分节点的配置修改

比如在 node1 上指定 destination 为 rocketmq-bus-node2 ( node2 配置了 spring.cloud.bus.id 为rocketmq-bus-node2:10002,可以匹配上) 进行配置的修改:

curl -X POST 'http://localhost:10001/actuator/bus-env/rocketmq-bus-node2?name=hangzhou&value=xihu' -H 'content-type: application/json'

访问/bus/env 获取配置(由于在 node1 上发送消息,Bus 也会对发送方的节点 node1 进行配置修改):

~ ⌚
$ curl -X POST 'http://localhost:10001/actuator/bus-env/rocketmq-bus-node2?name=hangzhou&value=xihu' -H 'content-type: application/json'
~ ⌚
$ curl -X GET 'http://localhost:10005/bus/env?key=hangzhou'
alibaba%
~ ⌚
$ curl -X GET 'http://localhost:10004/bus/env?key=hangzhou'
alibaba%
~ ⌚
$ curl -X GET 'http://localhost:10003/bus/env?key=hangzhou'
alibaba%
~ ⌚
$ curl -X GET 'http://localhost:10002/bus/env?key=hangzhou'
xihu%
~ ⌚
$ curl -X GET 'http://localhost:10001/bus/env?key=hangzhou'
xihu%

可以看到,只有 node1 和 node2 修改了配置,其余的 3 个节点配置未改变。

Bus 的实现

1. Bus 概念介绍

1)事件

Bus 中定义了远程事件RemoteApplicationEvent,该事件继承了 Spring 的事件ApplicationEvent,而且它目前有 4 个具体的实现:

4.png

  • EnvironmentChangeRemoteApplicationEvent:远程环境变更事件。主要用于接收一个 Map<String,String> 类型的数据并更新到 Spring 上下文中 Environment 中的事件。文中的实例就是使用这个事件并配合 EnvironmentBusEndpoint 和 EnvironmentChangeListener 完成的。
  • AckRemoteApplicationEvent:远程确认事件。Bus 内部成功接收到远程事件后会发送回AckRemoteApplicationEvent确认事件进行确认。
  • RefreshRemoteApplicationEvent: 远程配置刷新事件。配合 @RefreshScope 以及所有的 @ConfigurationProperties注解修饰的配置类的动态刷新。
  • UnknownRemoteApplicationEvent:远程未知事件。Bus 内部消息体进行转换远程事件的时候如果发生异常会统一包装成该事件。

Bus 内部还存在一个非RemoteApplicationEvent事件 -SentApplicationEvent消息发送事件,配合 Trace 进行远程消息发送的记录。

这些事件会配合ApplicationListener进行操作,比如EnvironmentChangeRemoteApplicationEvent配了EnvironmentChangeListener进行配置的新增/修改:

public class EnvironmentChangeListenerimplements ApplicationListener<EnvironmentChangeRemoteApplicationEvent> {private static Log log = LogFactory.getLog(EnvironmentChangeListener.class);@Autowiredprivate EnvironmentManager env;@Overridepublic void onApplicationEvent(EnvironmentChangeRemoteApplicationEvent event) {Map<String, String> values = event.getValues();log.info("Received remote environment change request. Keys/values to update "+ values);for (Map.Entry<String, String> entry : values.entrySet()) {env.setProperty(entry.getKey(), entry.getValue());}}
}

收到其它节点发送来EnvironmentChangeRemoteApplicationEven事件之后调用EnvironmentManager#setProperty进行配置的设置,该方法内部针对每一个配置项都会发送一个EnvironmentChangeEvent事件,然后被ConfigurationPropertiesRebinder所监听,进行 rebind 操作新增/更新配置。

2)Actuator Endpoint

Bus 内部暴露了 2 个 Endpoint,分别是EnvironmentBusEndpoint和RefreshBusEndpoint,进行配置的新增/修改以及全局配置刷新。它们对应的 Endpoint id 即 url 是 bus-env和bus-refresh。

3)配置

Bus 对于消息的发送必定涉及到 Topic、Group 之类的信息,这些内容都被封装到了BusProperties中,其默认的配置前缀为spring.cloud.bus,比如:

  • spring.cloud.bus.refresh.enabled用于开启/关闭全局刷新的 Listener。
  • spring.cloud.bus.env.enabled 用于开启/关闭配置新增/修改的 Endpoint。
  • spring.cloud.bus.ack.enabled 用于开启开启/关闭AckRemoteApplicationEvent事件的发送。
  • spring.cloud.bus.trace.enabled 用于开启/关闭息记录 Trace 的 Listener。

消息发送涉及到的 Topic 默认用的是springCloudBus,可以配置进行修改,Group 可以设置成广播模式或使用 UUID 配合 offset 为 lastest 的模式。

每个 Bus 应用都有一个对应的 Bus id,官方取值方式较复杂:

${vcap.application.name:${spring.application.name:application}}:${vcap.application.instance_index:${spring.application.index:${local.server.port:${server.port:0}}}}:${vcap.application.instance_id:${random.value}}

建议手动配置 Bus id,因为 Bus 远程事件中的 destination 会根据 Bus id 进行匹配:

spring.cloud.bus.id=${spring.application.name}-${server.port}

2. Bus 底层分析

Bus 的底层分析无非牵扯到这几个方面:

  • 消息是如何发送的
  • 消息是如何接收的
  • destination 是如何匹配的
  • 远程事件收到后如何触发下一个 action

BusAutoConfiguration自动化配置类被@EnableBinding(SpringCloudBusClient.class)所修饰。

@EnableBinding的用法在文章《Spring Cloud Stream 体系及原理介绍》中已经说明,且它的 value 为SpringCloudBusClient.class,会在SpringCloudBusClient中基于代理创建出 input 和 output 的DirectChannel:

public interface SpringCloudBusClient {String INPUT = "springCloudBusInput";String OUTPUT = "springCloudBusOutput";@Output(SpringCloudBusClient.OUTPUT)MessageChannel springCloudBusOutput();@Input(SpringCloudBusClient.INPUT)SubscribableChannel springCloudBusInput();
}

springCloudBusInput 和 springCloudBusOutput 这两个 Binding 的属性可以通过配置文件进行修改(比如修改 topic):

spring.cloud.stream.bindings:springCloudBusInput:destination: my-bus-topicspringCloudBusOutput:destination: my-bus-topic

消息的接收和发送:

// BusAutoConfiguration
@EventListener(classes = RemoteApplicationEvent.class) // 1
public void acceptLocal(RemoteApplicationEvent event) {if (this.serviceMatcher.isFromSelf(event)&& !(event instanceof AckRemoteApplicationEvent)) { // 2this.cloudBusOutboundChannel.send(MessageBuilder.withPayload(event).build()); // 3}
}
@StreamListener(SpringCloudBusClient.INPUT) // 4
public void acceptRemote(RemoteApplicationEvent event) {if (event instanceof AckRemoteApplicationEvent) {if (this.bus.getTrace().isEnabled() && !this.serviceMatcher.isFromSelf(event)&& this.applicationEventPublisher != null) { // 5this.applicationEventPublisher.publishEvent(event);}// If it's an ACK we are finished processing at this pointreturn;}if (this.serviceMatcher.isForSelf(event)&& this.applicationEventPublisher != null) { // 6if (!this.serviceMatcher.isFromSelf(event)) { // 7this.applicationEventPublisher.publishEvent(event);}if (this.bus.getAck().isEnabled()) { // 8AckRemoteApplicationEvent ack = new AckRemoteApplicationEvent(this,this.serviceMatcher.getServiceId(),this.bus.getAck().getDestinationService(),event.getDestinationService(), event.getId(), event.getClass());this.cloudBusOutboundChannel.send(MessageBuilder.withPayload(ack).build());this.applicationEventPublisher.publishEvent(ack);}}if (this.bus.getTrace().isEnabled() && this.applicationEventPublisher != null) { // 9// We are set to register sent events so publish it for local consumption,// irrespective of the originthis.applicationEventPublisher.publishEvent(new SentApplicationEvent(this,event.getOriginService(), event.getDestinationService(),event.getId(), event.getClass()));}
}
  1. 利用 Spring 事件的监听机制监听本地所有的RemoteApplicationEvent远程事件(比如bus-env会在本地发送EnvironmentChangeRemoteApplicationEvent事件,bus-refresh会在本地发送RefreshRemoteApplicationEvent事件,这些事件在这里都会被监听到)。
  2. 判断本地接收到的事件不是AckRemoteApplicationEvent远程确认事件(不然会死循环,一直接收消息,发送消息...)以及该事件是应用自身发送出去的(事件发送方是应用自身),如果都满足执行步骤 3。
  3. 构造 Message 并将该远程事件作为 payload,然后使用 Spring Cloud Stream 构造的 Binding name 为 springCloudBusOutput 的 MessageChannel 将消息发送到 broker。

4.@StreamListener注解消费 Spring Cloud Stream 构造的 Binding name 为 springCloudBusInput 的 MessageChannel,接收的消息为远程消息。

  1. 如果该远程事件是AckRemoteApplicationEvent远程确认事件并且应用开启了消息追踪 trace 开关,同时该远程事件不是应用自身发送的(事件发送方不是应用自身,表示事件是其它应用发送过来的),那么本地发送AckRemoteApplicationEvent远程确认事件表示应用确认收到了其它应用发送过来的远程事件,流程结束。
  2. 如果该远程事件是其它应用发送给应用自身的(事件的接收方是应用自身),那么进行步骤 7 和 8,否则执行步骤 9。
  3. 该远程事件不是应用自身发送(事件发送方不是应用自身)的话,将该事件以本地的方式发送出去。应用自身一开始已经在本地被对应的消息接收方处理了,无需再次发送。
  4. 如果开启了AckRemoteApplicationEvent远程确认事件的开关,构造AckRemoteApplicationEvent事件并在远程和本地都发送该事件(本地发送是因为步骤 5 没有进行本地AckRemoteApplicationEvent事件的发送,也就是自身应用对自身应用确认; 远程发送是为了告诉其它应用,自身应用收到了消息)。
  5. 如果开启了消息记录 Trace 的开关,本地构造并发送SentApplicationEvent事件。

5.png

bus-env触发后所有节点的EnvironmentChangeListener监听到了配置的变化,控制台都会打印出以下信息:

o.s.c.b.event.EnvironmentChangeListener  : Received remote environment change request. Keys/values to update {hangzhou=alibaba}

如果在本地监听远程确认事件 AckRemoteApplicationEvent,都会收到所有节点的信息,比如 node5 节点的控制台监听到的 AckRemoteApplicationEvent事件如下:

ServiceId [rocketmq-bus-node5:10005] listeners on {"type":"AckRemoteApplicationEvent","timestamp":1554124670484,"originService":"rocketmq-bus-node5:10005","destinationService":"**","id":"375f0426-c24e-4904-bce1-5e09371fc9bc","ackId":"750d033f-356a-4aad-8cf0-3481ace8698c","ackDestinationService":"**","event":"org.springframework.cloud.bus.event.EnvironmentChangeRemoteApplicationEvent"}
ServiceId [rocketmq-bus-node5:10005] listeners on {"type":"AckRemoteApplicationEvent","timestamp":1554124670184,"originService":"rocketmq-bus-node1:10001","destinationService":"**","id":"91f06cf1-4bd9-4dd8-9526-9299a35bb7cc","ackId":"750d033f-356a-4aad-8cf0-3481ace8698c","ackDestinationService":"**","event":"org.springframework.cloud.bus.event.EnvironmentChangeRemoteApplicationEvent"}
ServiceId [rocketmq-bus-node5:10005] listeners on {"type":"AckRemoteApplicationEvent","timestamp":1554124670402,"originService":"rocketmq-bus-node2:10002","destinationService":"**","id":"7df3963c-7c3e-4549-9a22-a23fa90a6b85","ackId":"750d033f-356a-4aad-8cf0-3481ace8698c","ackDestinationService":"**","event":"org.springframework.cloud.bus.event.EnvironmentChangeRemoteApplicationEvent"}
ServiceId [rocketmq-bus-node5:10005] listeners on {"type":"AckRemoteApplicationEvent","timestamp":1554124670406,"originService":"rocketmq-bus-node3:10003","destinationService":"**","id":"728b45ee-5e26-46c2-af1a-e8d1571e5d3a","ackId":"750d033f-356a-4aad-8cf0-3481ace8698c","ackDestinationService":"**","event":"org.springframework.cloud.bus.event.EnvironmentChangeRemoteApplicationEvent"}
ServiceId [rocketmq-bus-node5:10005] listeners on {"type":"AckRemoteApplicationEvent","timestamp":1554124670427,"originService":"rocketmq-bus-node4:10004","destinationService":"**","id":"1812fd6d-6f98-4e5b-a38a-4b11aee08aeb","ackId":"750d033f-356a-4aad-8cf0-3481ace8698c","ackDestinationService":"**","event":"org.springframework.cloud.bus.event.EnvironmentChangeRemoteApplicationEvent"}

那么回到本章节开头提到的 4 个问题,我们分别做一下解答:

  • 消息是如何发送的: 在BusAutoConfiguration#acceptLocal方法中通过 Spring Cloud Stream 发送事件到springCloudBustopic 中。
  • 消息是如何接收的: 在BusAutoConfiguration#acceptRemote方法中通过 Spring Cloud Stream 接收springCloudBustopic 的消息。
  • destination 是如何匹配的: 在BusAutoConfiguration#acceptRemote方法中接收远程事件方法里对 destination 进行匹配。
  • 远程事件收到后如何触发下一个 action: Bus 内部通过 Spring 的事件机制接收本地的RemoteApplicationEvent具体的实现事件再做下一步的动作(比如EnvironmentChangeListener接收了EnvironmentChangeRemoteApplicationEvent事件,RefreshListener接收了RefreshRemoteApplicationEvent事件)。

总结

Spring Cloud Bus 自身内容还是比较少的,不过还是需要提前了解 Spring Cloud Stream 体系以及 Spring 自身的事件机制,在此基础上,才能更好地理解 Spring Cloud Bus 对本地事件和远程事件的处理逻辑。

目前 Bus 内置的远程事件较少,大多数为配置相关的事件,我们可以继承RemoteApplicationEvent并配合@RemoteApplicationEventScan注解构建自身的微服务消息体系。

作者简介

方剑(花名:洛夜),GitHub ID @fangjian0423,开源爱好者,阿里巴巴高级开发工程师,阿里云产品 EDAS 开发,Spring Cloud Alibaba 开源项目负责人之一。

原文链接

本文为阿里云原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/513562.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

更灵活的边缘云原生运维:OpenYurt 单元化部署新增 Patch 特性

简介&#xff1a; 在正文开始之前&#xff0c;我们先回顾一下单元化部署的概念和设计理念。在边缘计算场景下&#xff0c;计算节点具有很明显的地域分布属性&#xff0c;相同的应用可能需要部署在不同地域下的计算节点上。 作者 | 张杰&#xff08;冰羽&#xff09; 来源 | 阿里…

Gartner:2022年全球IT支出将超4万亿美元,软件增速最高

编辑 | 宋慧 供稿 | Gartner 根据Gartner的最新预测&#xff0c;2022年全球IT支出预计将达到4.5万亿美元&#xff0c;相比2021年增长5.5%。 Gartner杰出研究副总裁John-David Lovelock表示&#xff1a;“越来越多的企业将构建新技术和软件&#xff0c;而不是购买和部署它们&am…

Flink 实时计算在微博的应用

简介&#xff1a; 微博通过将 Flink 实时流计算框架跟业务场景相结合&#xff0c;在平台化、服务化方面做了很大的工作&#xff0c;在开发效率、稳定性方面也做了很多优化。我们通过模块化设计和平台化开发&#xff0c;提高开发效率。 微博机器学习研发中心数据计算负责人&…

移动云帮我养出了一片致富鱼塘

“通过U鱼智慧管理平台&#xff0c;水产养殖由‘人治’转变为‘智治’&#xff0c;养得舒心、卖得放心、吃得安心。”广东省渔业种质保护中心相关负责人表示。准确研究&#xff0c;提升科学养殖水平广东省渔业种质保护中心坐落于广州市南沙区东涌镇&#xff0c;占地580亩&#…

sketch里的ios控件_使用Sketch建立Design System

一、 有关Design System之前的文章《使用Adobe XD建立Design System》中介绍了什么是Design System&#xff0c;它有什么用&#xff0c;在设计的哪个阶段使用以及如何用Adobe XD来搭建。这篇文章主要侧重在UI风格已确定的设计后期&#xff0c;用Sketch工具来搭建一个Design Sys…

论好文章和烂文章

简介&#xff1a; 我们为何写作&#xff1f;对于许多技术同学来说&#xff0c;写作是一件比写代码困难许多的事情&#xff0c;和电脑相顾无言数小时&#xff0c;发现自己写不出什么像样的东西来&#xff0c;着实不是一种很好的体验。 作者 | 许晓斌 来源 | 阿里巴巴云原生公众号…

好代码实践:基于Redis的轻量级分布式均衡消费队列

简介&#xff1a; 好代码&#xff0c;给人第一个印象的感觉&#xff0c;就像一篇好文章一样&#xff0c;读起来朗朗上口。不同的文章有不同的风格体裁&#xff0c;不同的代码也有不同的编程风格要求。Python有严格的缩进&#xff0c;像诗歌一样工整对仗&#xff1b;C语言面向过…

浅析低功耗广域网及在智慧城市中的应用

作者 | 沈建华、冷咏雪根据知名物联网分析机构IoT Analytics预测&#xff0c;到2025年&#xff0c;物联网连接数将达到非物联网连接数的3倍。低功耗广域网(LPWAN)作为物联网连接的核心基础设施&#xff0c;其业务特点是发送数据极小&#xff0c;并且为了维持电池供电设备的长时…

rocketmq怎么保证数据不会重复_RocketMQ保证信息有序性和防止重复

分布式开放消息系统(RocketMQ)的原理与实践分布式消息系统做为实现分布式系统可扩展、可伸缩性的关键组件&#xff0c;须要具备高吞吐量、高可用等特色。而谈到消息系统的设计&#xff0c;就回避不了两个问题&#xff1a;java消息的顺序问题消息的重复问题RocketMQ做为阿里开源…

云效Codeup代码评审中的代码协同

简介&#xff1a; 云效 Codeup 汇集了阿里巴巴最新的代码托管、代码协同技术&#xff0c;希望能够造福更多中国和世界的开发者。 大神说&#xff1a;“Show me the code”&#xff0c;于是就有了代码评审。 “Talk is cheap. Show me the code.” ——Linus Torvalds, founder …

代码安全无忧—云效Codeup代码加密技术发展之路

简介&#xff1a; 从代码服务及代码安全角度出发&#xff0c;看看云效代码加密技术如何解决这一问题 代码数据存在云端&#xff0c;如何保障它的安全&#xff1f; 部分企业管理者对于云端代码托管存在一丝担心&#xff1a;我的代码存在云端服务器&#xff0c;会不会被泄露&…

杀死 Oculus ,Facebook 改名 Meta ,是押注元宇宙还是“金蝉脱壳”?

整理 | 祝涛出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;美东时间10月28日周四&#xff0c;在名为Facebook Connect的年度大会上&#xff0c;Facebook宣布&#xff0c;Facebook将公司名称更改为“Meta”&#xff0c;这个新名字反映了该公司在社交媒体之外的雄心…

java sdp_[java,SDP] java 7 SDP 技术/Socket Direct Protocol 2

With Java 7 and Sockets Direct Protocol , Java Now does RDMA ( Remote Direct Memory Access)有了 SDP 技术支持之后的 Java 7 已经开始逐步实现 RDMA 技术 (远程内存直接访问)RDMA is Remote Dynamic Memory Accesss -- which is a way of moving application buffers bet…

百信银行基于 Apache Hudi 实时数据湖演进方案

简介&#xff1a; 本文介绍了百信银行实时计算平台的建设情况&#xff0c;实时数据湖构建在 Hudi 上的方案和实践方法&#xff0c;以及实时计算平台集成 Hudi 和使用 Hudi 的方式。 本文介绍了百信银行实时计算平台的建设情况&#xff0c;实时数据湖构建在 Hudi 上的方案和实践…

如何做一场高质量的分享

简介&#xff1a; 每个人在分享前都应该先问自己这么一个问题&#xff0c;我为什么要分享&#xff1f;我觉得分享就一个最纯粹的原因&#xff0c;就是“我有一些知识&#xff0c;是别人不知道的&#xff0c;但对他人会有所帮助&#xff0c;所以我想分享给大家”。 作者 | 阿相 …

RTE2021,实时互动技术的进化与蝶变

10 月 22—23 日&#xff0c;由声网 Agora 主办的 RTE2021 实时互联网大会在北京圆满落幕。大会以“万象频道”为主题&#xff0c;带来了 20 余场实时互联网全生态线下论坛及活动、近百场的精彩演讲分享&#xff0c;覆盖技术开发、行业观察、创业投资、趋势洞察等多维度话题。同…

Java编程技巧之单元测试用例编写流程

简介&#xff1a; 立足于“如何来编写单元测试用例”&#xff0c;让大家“有章可循”&#xff0c;快速编写出单元测试用例。 作者 | 常意 来源 | 阿里技术公众号 温馨提示&#xff1a;本文较长&#xff0c;同学们可收藏后再看 :)前言 清代杰出思想家章学诚有一句名言&#xff…

KubeVela + KEDA:为应用带来“与生俱来”的弹性伸缩能力

简介&#xff1a; 在这篇博文中&#xff0c;我们将简要解释需要考虑的领域&#xff0c;KEDA 如何使应用自动伸缩变得简单&#xff0c;以及为什么阿里云企业分布式应用服务&#xff08;EDAS&#xff09;在 KEDA 上完全标准化。 联合作者 | Yan Xun&#xff0c;阿里云 EDAS 团队…

mysql行转列函数_一个小知识点-Hive行转列实现Pivot

前言传统关系型数据库中&#xff0c;无论是Oracle(11g之后)还是SQLserver(2005之后)&#xff0c;都自带了Pivot函数实现行转列功能&#xff0c;本文主要讲述在Hive中实现行转列的两种方式。传统数据库方式这种方式是借鉴在Oracle或者SQLserver在支持Pivot函数之前实现行转列的方…

安全之心:一文读懂可信计算

简介&#xff1a; 信 or 不信&#xff0c;这是个问题 可信计算 TC &#xff08;Trusted Computing&#xff09; 业界新宠&#xff0c;越来越被高频提到 本质是创造可信执行环境的芯片级安全防护方案 然而&#xff0c;江湖流传 TA 的传说 却鲜少有人见过真身 阿里云作为亚太区最…