osgi 模块化_OSGi案例研究:模块化vert.x

osgi 模块化

OSGi使Java代码可以清晰地划分为多个模块,这些模块称为捆绑软件 ,可以访问由每个捆绑软件的类加载器控制的代码和资源。 OSGi 服务提供了一种附加的分离机制:接口的用户无需依赖于实现类,工厂等。

以下案例研究旨在使OSGi捆绑包和服务的上述优势具体化。 它采用了一个有趣的Java项目vert.x,并展示了如何将其嵌入OSGi并利用OSGi的功能。

免责声明:我不建议更换vert.x容器或其模块系统。 这主要是在OSGi的使用中进行的案例研究,尽管某些发现应促使对vert.x进行改进,尤其是将其嵌入具有自定义类加载器的应用程序中时。

版本号

vert.x开源项目提供了node.js的JVM替代方案:异步,事件驱动的编程模型,用于以多种语言(包括Java,Groovy,JavaScript和Ruby)编写Web应用程序。

vert.x支持HTTP以及现代协议,例如WebSockets和sockjs (与WebSockets 相比 ,它们在更多的浏览器中工作,并且可以更轻松地穿越防火墙)。
vert.x具有分布式事件总线,允许已知为verticles并称为busmods共享代码库vert.x应用程序之间进行传播JSON消息。 busmod是一种特殊的Verticle,它处理事件总线中的事件。 vert.x附带了一些busmod,例如MongoDB的 “ persistor”,用户可以编写自己的。

vert.x的线程模型很有趣,因为每个顶点(或busmod)在其生命周期内都绑定到特定线程,因此,顶点代码无需关注线程安全性。 线程池用于在顶点上分派工作,并且每个顶点必须避免阻塞或长时间运行的操作,以免影响服务器吞吐量(vert.x提供了有效地实现长时间运行的操作的单独机制)。 这类似于CICS事务处理器中的准可重入线程模型。 1个

这里特别受关注的是vert.x模块系统,该系统每个顶点都有一个类加载器,还有称为模块的代码库,它们被加载到使用它们的每个顶点的类加载器中。 因此,除了通过事件总线之外,没有其他方法可以在各个顶点之间共享代码。

vert.x具有出色的文档,包括主要手册 , java手册 (以及其他语言的手册), 教程和可运行的代码示例 。

OSGi

如果您还不熟悉OSGi,请阅读我的OSGi简介帖子,但是现在不要再理会该帖子中的链接-您可以随时返回并稍后再做。

在OSGi中嵌入vert.x

我通过几个小步骤来完成此操作,下面依次介绍了这些步骤:将vert.x JAR转换为OSGi捆绑包,然后模块化verticle,busmod和事件总线客户端。

将vert.x JAR转换为OSGi捆绑软件

vert.x手册鼓励用户使用vert.x核心JAR将vert.x嵌入自己的应用程序中,因此将vert.x嵌入OSGi的第一步是将vert.x核心JAR转换为OSGi捆绑包,因此可以将其加载到OSGi运行时中。

我使用了Bundlor工具,尽管其他工具(例如bnd)也可以很好地工作。 Bundlor接受一个模板,然后分析JAR的字节码以产生带有适当OSGi清单标头的新JAR。 请立即参阅SpringSource Bundlor文档以获取有关Bundlor的更多信息,因为在撰写本文时Eclipse Virgo Bundlor文档尚未发布,即使Bundlor项目已转移到Eclipse.org。

vert.x核心JAR的模板如下:

Bundle-ManifestVersion: 2
Bundle-SymbolicName: org.vertx.core
Bundle-Version: 1.0.0.final
Bundle-Name: vert.x Core
Import-Template:org.jboss.netty.*;version="[3.4.2.Final,4.0)",org.codehaus.jackson.*;version="[1.9.4,2.0)",com.hazelcast.*;version="[2.0.2,3.0)";resolution:=optional,groovy.*;resolution:=optional;version=0,org.codehaus.groovy.*;resolution:=optional;version=0,javax.net.ssl;resolution:=optional;version=0,org.apache.log4j;resolution:=optional;version=0,org.slf4j;resolution:=optional;version=0
Export-Template: *;version="1.0.0.final"

(此案例研究的模板和所有其他部分都可以在github上找到 。)

这是为JAR依赖的软件包定义有效的版本范围(范围“ 0”表示0或更大的版本范围),这些软件包是可选的还是强制的,以及JAR自己的软件包应为哪个版本出口处。 它还为捆绑软件提供了符号名称 (用于标识捆绑软件),版本和(描述性)名称。 有了这些信息,OSGi然后通过委派包类加载器之间的类加载和资源查找,将包的依赖关系连接在一起。

值得庆幸的网状网络JAR和杰克逊 JSON JAR文件将vert.x核心JAR取决于附带有效的OSGi清单。

为了验证清单是否有效,我尝试在处女座内核中部署vert.x核心软件包。 只需将vert.x核心软件包放置在拾取目录中,并将其依赖项放置在repository / usr目录中,然后启动内核即可。 以下控制台消息显示vert.x核心捆绑包已安装并成功解决:

<hd0001i> Hot deployer processing 'INITIAL' event for file 'vert.x-core-1.0.0.final.jar'.
<de0000i> Installing bundle 'org.vertx.core' version '1.0.0.final'.
<de0001i> Installed bundle 'org.vertx.core' version '1.0.0.final'.
<de0004i> Starting bundle 'org.vertx.core' version '1.0.0.final'.
<de0005i> Started bundle 'org.vertx.core' version '1.0.0.final'.

然后使用处女座外壳,检查线束的接线:

osgi> ss
"Framework is launched."id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.7.1.R37x_v20110808-1106
...
89      ACTIVE      org.vertx.core_1.0.0.final
90      ACTIVE      jackson-core-asl_1.9.4
91      ACTIVE      jackson-mapper-asl_1.9.4
92      ACTIVE      org.jboss.netty_3.4.2.Finalosgi> bundle 89
org.vertx.core_1.0.0.final [89]...Exported packages...org.vertx.java.core; version="1.0.0.final"[exported]org.vertx.java.core.buffer; version="1.0.0.final"[exported]...Imported packagesorg.jboss.netty.util; version="3.4.2.Final"<org.jboss.netty_3.4.2.final [92]>...org.codehaus.jackson.map; version="1.9.4"<jackson-mapper-asl_1.9.4 [91]>...

我还按照以后需要的类似方式将vert.x平台JAR转换为OSGi捆绑软件。

模块化顶点

一个典型的顶点如下所示:

public class ServerExample extends Verticle {public void start() {vertx.createHttpServer().requestHandler(new Handler<httpserverrequest>() {public void handle(HttpServerRequest req) {...}}).listen(8080);}
}

调用start方法时,它将创建一个HTTP服务器,并向该服务器注册一个处理程序,并设置服务器在端口上侦听。 除了处理程序的主体之外,该代码的其余部分都是样板。 因此,我决定将样板分解为一个通用的OSGi捆绑包(org.vertx.osgi),并用包含处理程序和一些等同于样板的声明性元数据的模块化顶包来替换该竖版。 常见的OSGi捆绑包使用白板模式来侦听OSGi服务注册表中的特定种类的服务,基于元数据创建样板,并向生成的HTTP服务器注册处理程序。

让我们看一下模块化的vertical bundle。 它的代码包含一个HttpServerRequestHandler类: 2

public final class HttpServerRequestHandler implements Handler<httpserverrequest> {public void handle(HttpServerRequest req) {...}}

它还具有服务属性形式的声明性元数据,这些声明元数据与处理程序一起在OSGi服务注册表中注册。 我可以使用OSGi蓝图服务来执行此操作,尽管我可以使用OSGi声明性服务,甚至可以使用OSGi API以编程方式注册该服务。 蓝图元数据是捆绑软件中的文件blueprint.xml ,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"><service interface="org.vertx.java.core.Handler" ref="handler"><service-properties><entry key="type" value="HttpServerRequestHandler"><entry key="port" value="8090"></service-properties></service><bean class="org.vertx.osgi.sample.basic.HttpServerRequestHandler"id="handler"/></blueprint>

此元数据声明应创建HTTP服务器(通过类型服务属性),向其注册的处理程序以及侦听端口8090的服务器集(通过端口服务属性)。 当org.vertx.osgi捆绑包运行时,这一切都是通过白板模式完成的,如下所示。

请注意,模块化Verticle仅依赖于Handler和HttpServerRequest类,而原始Verticle也依赖于Vertx,HttpServer和Verticle类。 对于那些喜欢单元测试(除了容器内测试)的人来说,这也使事情变得简单得多,因为需要的模拟或存根数量更少。

那么我们现在有什么呢? 将两个包添加到我们之前安装的包中:一个org.vertx.osgi包,它封装了样板代码;一个应用程序包,它代表一个模块化的verticle。 我们还需要一个Blueprint服务实现-从Virgo 3.5开始,Virgo内核内置了一个Blueprint实现。 以下交互图显示了一种可能的事件序列:

在OSGi中,每个捆绑包都有其自己的生命周期,并且通常设计捆绑包时,无论它们相对于其他捆绑包启动的顺序如何,它们都将正确运行。 在上面的示例中,假定的启动顺序为:蓝图服务,org.vertx.osgi包,模块化verticle包。 但是,org.vertx.osgi捆绑包可以在模块化Verticle捆绑包之后开始,并且最终结果将是相同的:将创建服务器,并且在服务器上注册模块化Verticle捆绑包的处理程序,并且服务器设置监听。 如果蓝图服务是在org.vertx.osgi和模块化Verticle捆绑包之后启动的,那么直到蓝图服务启动后,org.vertx.osgi捆绑包才会检测到该模块化Verticle捆绑包的处理程序服务出现在服务注册表中,但是最终结果将再次相同。

github项目包含一些示例模块化verticle的源代码: 基本的HTTP垂直版本 (在8090端口上运行)和sockjs verticle (在8091端口上运行)。 org.vertx.osgi捆绑软件需要更多代码来支持sockjs,而模块化的sockjs verticle除了提供HTTP处理程序外,还需要提供sockjs处理程序。

模块化BusMods

MongoDB持久程序是处理来自事件总线的消息的busmod的典型示例:

public class MongoPersistor extends BusModBase implements Handler<message<jsonobject>> {private String address;private String host;private int port;private String dbName;private Mongo mongo;private DB db;public void start() {super.start();address = getOptionalStringConfig("address", "vertx.mongopersistor");host = getOptionalStringConfig("host", "localhost");port = getOptionalIntConfig("port", 27017);dbName = getOptionalStringConfig("db_name", "default_db");try {mongo = new Mongo(host, port);db = mongo.getDB(dbName);eb.registerHandler(address, this);} catch (UnknownHostException e) {logger.error("Failed to connect to mongo server", e);}}public void stop() {mongo.close();}public void handle(Message<jsonobject> message) {...}}

同样,这里混合了样板代码(用于注册事件总线处理程序),启动/停止逻辑,配置处理以及事件总线处理程序本身。 我对其他版本应用了类似的方法,并将样板代码分离到org.vertx.osgi包中,将处理程序和元数据(包括配置)保留在模块化busmod中。 持久性对MongoDB客户端JAR(mongo.jar)的依赖很方便,因为此JAR附带了有效的OSGi清单。

这是blueprint.xml :

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"><service ref="handler" interface="org.vertx.java.core.Handler"><service-properties><entry key="type" value="EventBusHandler"/><entry key="address" value="vertx.mongopersistor"/></service-properties></service><bean id="handler" class="org.vertx.osgi.mod.mongo.MongoPersistor"destroy-method="stop"><argument type="java.lang.String"><value>localhost</value></argument><argument type="int"><value>27017</value></argument><argument type="java.lang.String"><value>default_db</value></argument></bean></blueprint>

请注意,样板配置由处理程序类型和事件总线地址组成。 其他配置(主机,端口和数据库名称)特定于MongoDB持久程序。

这是模块化的MongoDB busmod代码 :

public class MongoPersistor extends BusModBaseimplements Handler<Message<JsonObject>> {private final String host;private final int port;private final String dbName;private final Mongo mongo;private final DB db;public MongoPersistor(String host, int port, String dbName)throws UnknownHostException, MongoException {this.host = host;this.port = port;this.dbName = dbName;this.mongo = new Mongo(host, port);this.db = this.mongo.getDB(dbName);}public void stop() {mongo.close();}public void handle(Message<JsonObject> message) {...}}

该代码仍然扩展了BusModBase,仅仅是因为BusModBase提供了几种方便的辅助方法。 同样,与非模块化等效代码相比,生成的代码更简单,更易于单元测试。

模块化事件总线客户端

最后,我需要一个模块化的Verticle来测试模块化的MongoDB持久性。 这些verticle需要做的就是将适当的消息发布到事件总线。 普通的vert.x垂直版本使用Vertx类获取事件总线,但是我再次使用了Blueprint服务,这次是在服务注册表中查找事件总线服务,并将其注入到模块化垂直版本中。 我还扩展了org.vertx.osgi捆绑包,以便在服务注册表中发布事件总线服务。

模块化事件总线客户端的blueprint.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"><reference id="eventBus" interface="org.vertx.java.core.eventbus.EventBus"/><bean class="org.vertx.osgi.sample.mongo.MongoClient"><argument ref="eventBus"/><argument type="java.lang.String"><value>vertx.mongopersistor</value></argument></bean></blueprint>

然后, 模块化事件总线客户端代码非常简单:

public final class MongoClient {public MongoClient(EventBus eventBus, String address) {JsonObject msg = ...eventBus.send(address, msg,new Handler<Message<JsonObject>>(){...});}}

旋转一下

1.我已经在git的bundles目录中提供了所有必需的OSGi捆绑包 。 您可以通过克隆git存储库来获取它们:

git clone git://github.com/glyn/vert.x.osgi.git

或通过下载git repo的zip文件 。

2. vert.x需要Java 7 ,因此请设置一个终端外壳以使用Java7 。确保正确设置了JAVA_HOME环境变量。 (如果现在无法获取Java 7,则将捆绑软件部署到OSGi时会看到一些错误,并且您将无法在步骤8和9中运行示例。)

3.如果您是OSGi用户,只需在您喜欢的OSGi框架或容器中安装并启动捆绑软件,然后跳至步骤8。否则,请按以下方式使用git存储库中的Virgo内核副本。

4.将目录更改为git repo的本地副本中的virgo-kernel-…目录。

5.在UNIX上,发出:

bin/startup.sh -clean

或在Windows上,发出:

bin\startup.bat -clean

6.处女座内核应启动并在其拾取目录中部署各种捆绑软件:

  • org.vertx.osgi捆绑包( org.vertx.osgi-0.0.1.jar
  • HTTP示例模块化org.vertx.osgi.sample.basic-1.0.0.jarorg.vertx.osgi.sample.basic-1.0.0.jar
  • SockJS示例模块化verticle( org.vertx.osgi.sample.sockjs-1.0.0.jar
  • MongoDB持久性示例模块化busmod( org.vertx.osgi.mods.mongo-1.0.0.jar

7.如果要查看现在正在运行的捆绑软件,请从另一个终端启动Virgo Shell:

telnet localhost 2501

并使用sslb命令汇总已安装的捆绑软件。 help命令将列出其他可用命令,而disconnect将使您脱离Virgo Shell。 这是ss命令的典型输出:

...
89      ACTIVE      org.vertx.osgi_0.0.1
90      ACTIVE      jackson-core-asl_1.9.4
91      ACTIVE      jackson-mapper-asl_1.9.4
92      ACTIVE      org.jboss.netty_3.4.2.Final
93      ACTIVE      org.vertx.core_1.0.0.final
94      ACTIVE      org.vertx.osgi.mods.mongo_1.0.0
95      ACTIVE      com.mongodb_2.7.2
96      ACTIVE      org.vertx.platform_1.0.0.final
97      ACTIVE      org.vertx.osgi.sample.basic_1.0.0
98      ACTIVE      org.vertx.osgi.sample.sockjs_1.0.0

lb命令(包括更具描述性的Bundle-Name标头):

...89|Active     |    4|vert.x OSGi Integration (0.0.1)90|Active     |    4|Jackson JSON processor (1.9.4)91|Active     |    4|Data mapper for Jackson JSON processor (1.9.4)92|Active     |    4|The Netty Project (3.4.2.Final)93|Active     |    4|vert.x Core (1.0.0.final)94|Active     |    4|MongoDB BusMod (1.0.0)95|Active     |    4|MongoDB (2.7.2)96|Active     |    4|vert.x Platform (1.0.0.final)97|Active     |    4|Sample Basic HTTP Verticle (1.0.0)98|Active     |    4|Sample SockJS Verticle (1.0.0)

8.现在,您可以使用Web浏览器在localhost:8090尝试基本的HTTP示例,该示例应响应“ hello”,或在http:// localhost:8091的SockJS示例应显示一个框,您可以在其中输入一些文本和一个按钮,单击该按钮会弹出一个窗口:

9.如果要尝试(无头的)MongoDB事件总线客户端,请下载MondoDB并在其默认端口上本地启动 ,然后将org.vertx.osgi.sample.mongo-1.0.0.jarbundles目录复制到Virgo的提取目录。 此捆绑包启动后,它将立即向事件总线发送一条消息,并驱动MongoDB持久程序更新数据库。 如果您不想使用MongoDB来检查是否已进行了更新,请查看处女座的日志(在serviceability/logs/log.log )以查看一些System.out行,如下所示,该行确认了发生的情况:

System.out Sending message: {action=save, document={x=y}, collection=vertx.osgi} 
... 
System.out Message sent 
...
System.out Message response {_id=95..., status=ok}

OSGi和vert.x模块化

在本案例研究中,各种示例OSGi捆绑包都依赖于并共享vert.x核心捆绑包。 每个捆绑包都加载在其自己的类加载器中,并且OSGi根据OSGi捆绑包的连接方式控制类加载和资源查找的委派。 以相同的方式,写为OSGi包的顶点可以自由地依赖和共享其他OSGi包。

这与vert.x模块系统大不相同,在vert.x模块系统中,一个verticle依赖的任何模块(除了busmod之外)都被加载到与verticle相同的类加载器中。

OSGi模块系统的优点在于,每个模块的单个副本安装在系统中,并且对于诸如Virgo shell之类的工具可见并且可以由其管理。 它还使占地面积最小。

vert.x模块系统的优点是,在各个顶点之间不存在模块共享,因此编写不当的模块不会无意或有意地泄漏独立顶点之间的信息。 另外,每个使用它的垂直模块都有每个(非busmod)模块的单独副本,因此可以编写模块而不必担心线程安全,因为每个副本仅在其垂直线程上执行。 但是,OSGi用户可能很高兴要求可重用的模块具有线程安全性,并谨慎地管理任何可变的静态数据,以避免线程之间的泄漏。  

更换容器?

当我提出将vert.x嵌入OSGi的话题时, vert.x的负责人蒂姆·福克斯(Tim Fox)问我是否正在编写当前容器的替代品,对此我回答“不是真的”。 我之所以这么说是因为我喜欢vert.x的事件驱动编程模型及其线程模型,它们似乎是“容器”的一部分。 但想更换一对夫妇的vert.x容器方面:模块系统和verticles登记处理的方式。

后来让我吃惊的是,“容器”作为整体实体的概念在模块化系统中可能有点奇怪,最好考虑多个单独的容器概念,然后可以采用不同的方式组合以适应不同的容器用户。 但是,上面看到的类加载和线程模型之间的微妙相互作用表明,包含的不同概念可以相互依赖。 我想知道其他人如何看待“容器”的概念吗?

结论

由于OSGi框架是一个相当严格的应用程序,因此vert.x声称它可以嵌入其他应用程序中的说法已得到验证。

vert.x模块系统虽然未在模块之间提供隔离,但确实在应用程序之间(包括顶点及其模块)提供了隔离,并且使模块的编写无需关注线程安全性。

提出了一个vert.x问题2 ,这应该使vert.x更易于使用自定义类加载器嵌入其他环境。

vert.x可以遵循netty,jackson和MongoDB JAR的示例,并在其核心JAR和平台JAR中包含OSGi清单,以避免OSGi用户不得不将这些JAR转换为OSGi捆绑软件。 我将这个问题留给其他人提出,因为我无法评估在OSGi中使用vert.x的需求。

在OSGi中运行vert.x可以满足一些出色的vert.x要求,例如如何自动化容器内测试(OSGi有许多解决方案,包括Pax Exam,而Virgo有集成测试框架)以及如何开发verticles并将它们部署到vert .x在IDE的控制下(请参阅Virgo IDE工具指南 )。 处女座还提供了许多附带的好处,包括用于检查和管理束和顶点的管理外壳,复杂的诊断程序以及更多其他功能(有关详细信息,请参阅处女座白皮书 )。

该练习还为处女座带来了一些不错的收益。 修复了370253错误 ,这是在Java 7下运行Virgo的唯一已知问题。Virgo3.5依赖于在此环境中中断的Gemini蓝图,因此引发并修复了错误379384 。 我使用了新的基于Eclipse的Virgo工具来开发各种捆绑软件并在Virgo中运行它们。 结果,我在工具中发现了一些小问题,这些问题将适时解决。

最后,在Virgo内核上运行vert.x进一步验证了该内核适合构建自定义服务器运行时,因为现在除了Tomcat,Jetty以及在内核上运行的一两个自定义服务器之外,我们还拥有vert.x。

脚注:

  1. 在IBM的日子里,我曾在CICS开发团队工作过。 SpringSource的一位同事给了我“ CICS做到了!” 我们开始合作后不久就穿了T恤。 旧习难改。
  2. 模块化垂直模块当前需要拦截vert.x的资源查找逻辑,以便可以轻松提供捆绑中的文件。 将此通用代码移至org.vertx.osgi捆绑包会更好,但这需要首先实现vert.x问题161 。

参考: OSGi案例研究:来自Mind the Gap博客的JCG合作伙伴 Glyn Normington 的模块化vert.x。


翻译自: https://www.javacodegeeks.com/2012/07/osgi-case-study-modular-vertx.html

osgi 模块化

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

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

相关文章

第三场阴影场与属性访问器接口

这是“ 影子字段与属性访问器”界面的 第3轮 。 如果您是新手&#xff0c;但不确定要怎么做&#xff0c;请查看我以前的文章或关于开发JavaFX应用程序时节省内存的第一篇文章 。 作为Java开发人员&#xff0c;我主要关心的是在开发JavaFX域模型时在性能 &#xff0c; 内存使用和…

移动端布局三种视口_前端基础:必须要知道的移动端适配(4)——视口

视口(viewport)代表当前可见的计算机图形区域。在Web浏览器术语中&#xff0c;通常与浏览器窗口相同&#xff0c;但不包括浏览器的UI&#xff0c; 菜单栏等——即指你正在浏览的文档的那一部分。一般我们所说的视口共包括三种&#xff1a;布局视口、视觉视口和理想视口&#xf…

平安性格测试题及答案_面试要求做性格测试,该怎么做?

为了筛选到更符合岗位&#xff0c;许多企业在招聘时都选择了“性格测试”。比如&#xff0c;像“华为、宝洁、阿里”等这样的大厂&#xff0c;据说每年都有不少人因为性格测试而凉凉&#xff0c;性格测试真有决定你“生死”的作用吗&#xff1f;那么&#xff0c;在做测试题的时…

CSS行内元素和块级元素的水平居中,垂直居中,水平垂直居中实现

常用内联元素&#xff1a;a,img,input,lable,select,span,textarea,font 常用的块级元素&#xff1a;div,p,table,form,h1,h2,h3,h4,h5,h6,dl,ol,ul,li 一、水平居中 行内元素居中&#xff1a; text-align:center 图片&#xff0c;单个块级元素居中&#xff1a;margin-left和…

mysql scrapy 重复数据_大数据python(scrapy)爬虫爬取招聘网站数据并存入mysql后分析...

基于Scrapy的爬虫爬取腾讯招聘网站岗位数据视频(见本头条号视频)根据TIOBE语言排行榜更新的最新程序语言使用排行榜显示&#xff0c;python位居第三&#xff0c;同比增加2.39%&#xff0c;为什么会越来越火&#xff0c;越来越受欢迎呢&#xff0c;背后折射出的是人工智能、机器…

如何在几分钟内安装Red Hat Container Development Kit(CDK)

作为负责开发容器化应用程序提供的可能性的应用程序开发人员或架构师&#xff0c;将所有工具集中在一起以使您入门时几乎没有帮助。 到现在。 红帽容器开发套件&#xff08;CDK&#xff09; 安装变得简单&#xff01; 红帽提供了一个容器开发套件&#xff08;CDK&#xff0…

enum 定义3个属性_和平精英:合金龙骨有3个隐藏属性,比玛莎“水下无敌”还唬人...

欢迎诸位小伙伴们来到天哥开讲的《和平精英》“精英那点事儿”~接下来呢&#xff0c;咱们聊聊合金龙骨的3个隐藏属性、土豪玩家“自投罗网”以及游戏里的“公主病患者”等有趣的玩家游戏经历与发现~得&#xff0c;废话不多说了&#xff0c;还是各位小伙伴们熟悉的“老配方”&am…

java中缓冲区和缓存_Java中的Google协议缓冲区

java中缓冲区和缓存总览 协议缓冲区是一种用于结构化数据的开源编码机制。 它是由Google开发的&#xff0c;旨在实现语言/平台中立且可扩展。 在本文中&#xff0c;我的目的是介绍Java平台上下文中协议缓冲区的基本用法。 Protobuff比XML更快&#xff0c;更简单&#xff0c;并…

三十七 Python分布式爬虫打造搜索引擎Scrapy精讲—将bloomfilter(布隆过滤器)集成到scrapy-redis中...

Python分布式爬虫打造搜索引擎Scrapy精讲—将bloomfilter(布隆过滤器)集成到scrapy-redis中&#xff0c;判断URL是否重复 布隆过滤器(Bloom Filter)详解 基本概念 如果想判断一个元素是不是在一个集合里&#xff0c;一般想到的是将所有元素保存起来&#xff0c;然后通过比较确定…

绩效管理的实际案例:2024年绩效提升重要方法

案例一&#xff1a;目标设定与衡量的艺术 背景&#xff1a;某科技公司每年都会为其全球员工设定年度目标。然而&#xff0c;这些目标往往过于模糊&#xff0c;导致员工不清楚自己需要完成什么。 问题&#xff1a;目标设定不清晰&#xff0c;导致员工感到困惑和不满。 解决方…

array python 交集_模糊数学Python库简介和评测

写在前面模糊数学是国内外许多工学、管理学研究生以上的选修甚至必修课程。但对于非数学专业而言&#xff0c;掌握模糊数学的各种计算方法、了解各种方法的用途&#xff08;应用场景&#xff09;其实要比理解模糊数学的“数学”理论要重要得多。目前在Matlab等数学工具中其实也…

架构设计器_大厂案例:马蜂窝大交通业务监控报警系统架构设计与实现

部门的业务线越来越多&#xff0c;任何一个线上运行的应用&#xff0c;都可能因为各种各样的原因出现问题&#xff1a;比如业务层面&#xff0c;订单量比上周减少了&#xff0c;流量突然下降了&#xff1b;技术层面的问题&#xff0c;系统出现 ERROR &#xff0c;接口响应变慢了…

使用mpvue开发小程序

一、安装node.js 1、在官网中安装nodejs最新版本。地址&#xff1a;https://nodejs.org/en/download/&#xff0c;根据自己环境&#xff0c;进行下载安装。 2、安装完成后&#xff0c;进行nodejs版本及npm版本查看。 打开cmd命令行&#xff0c;输入 node -v 和 npm -v&#…

iOS----------UITextField实现过滤选中状态拼音

2018年上班的第二天&#xff0c;就这样背了一个大锅。我们项目中有一个搜索功能&#xff0c;在这一期的版本中&#xff0c;为了增强优化&#xff0c;去除了过滤空格的请求&#xff0c;这样或许能增加很好的用户体验&#xff0c;恰恰相反&#xff0c;偷鸡不成蚀把米。没想到苹果…

ai电磁组属于什么组_RPA+AI 创新案例挑战赛 2020 【专业组】amp;【校园组】优胜名单来也!...

大赛介绍本次大赛由 RPA 产业推进方阵为指导单位&#xff0c;来也科技为主办单位&#xff0c;面向所有来也科技合作伙伴及深圳地区大学生公开报名征集【专业组】&【校园组】参赛案例。RPA 产业推进方阵是在中国人工智能产业发展联盟指导下&#xff0c;由中国信息通信研究院…

具有Spring Boot和Yeoman的单页Angularjs应用程序

我非常感谢yeoman之类的工具&#xff0c;它们提供了一种非常快速的方法来将不同的javascript库组合在一起成为一个一致的应用程序。 Yeoman提供了UI层&#xff0c;如果您需要开发服务层和静态资产的Web层&#xff0c;则打包的一种好方法是使用Spring Boot 。 我知道有像JHipste…

vue项目封装axios请求

目录&#xff1a; 一&#xff0c;src/utils/request.js import axios from axios import { getToken } from /utils/auth import store from /storeconst service axios.create({baseURL: process.env.VUE_APP_BASE_API,withCredentials: true,timeout: 5000,// headers:{ …

自定义函数_python3基础07函数(自定义)

"pythonic生物人"的第43篇分享。详细介绍python中&#xff1a;自定义函数的构建&#xff1b;参数传递&#xff1b;模块中调用函数。目录0、楔子1、自定义函数格式2、编写函数说明文档3、函数参数函数形参和实参区别位置实参关键字实参默认实参让实参可选传递任意数量…

curl -windows下接口通讯

1&#xff0c;下载curl -----url命令传输工具2&#xff0c;配置curl环境变量3&#xff0c;在cmd环境中使用举例&#xff1a;curl -G http://xxxxxxx.com&#xff1f;参数使用&#xff1a;curl -G "www.baidu.com" 最原始的批量通讯返回可以将通讯命令保存为bat格式文…

sqlserver 存储过程 C#调用 实现从数据库Get数据

在最近的项目中我想建立一个EFDBfirst的模型但是失败了&#xff0c;生成的edmx中没有实体类和表结构&#xff0c;到处需求解决方案&#xff0c;未果。 问题请见&#xff1a;https://q.cnblogs.com/q/102743/ 后来使用本文写的这个方法 /// 1.在sqlserver中建立存储过程 在一个d…