使用Fabric8在CDI管理的bean中注入Kubernetes Services

序幕

在Kubernetes中我最喜欢的就是发现服务的方式。 为什么?

主要是因为用户代码不必处理注册,查找服务,也没有网络意外(如果您曾经尝试过基于注册表的方法,那么您就会知道我在说什么)

这篇文章将介绍如何使用Fabric8以便使用CDI在Java中注入Kubernetes服务。

Kubernetes服务

深入介绍Kubernetes Services超出了本文的范围,但是我将尝试对其进行非常简要的概述。

在Kubernetes中,应用程序打包为Docker容器。 通常,将应用程序分成多个部分是一个好主意,因此您将拥有多个Docker容器,这些容器很可能需要彼此通信。 通过将某些容器放置在同一Pod中 ,可以将某些容器并置在一起,而另一些容器则可以位于较远的位置,并且需要彼此通信的方式。 这就是服务进入画面的地方。

容器可以绑定到一个或多个端口,从而为其他容器提供一个或多个“服务”。 例如:

  • 数据库服务器。
  • 消息代理。
  • 休息服务。

问题是其他容器如何知道如何访问这些服务?

所以, Kubernetes让你“标签”每个吊舱 ,并使用这些标签来“选择” 吊舱提供一个逻辑服务。 这些标签是简单的键,值对。

这是一个示例,说明如何通过使用键和值mysql指定标签来“标记”容器。

{"apiVersion" : "v1beta3","kind" : "ReplicationController","metadata" : {"labels" : {"name" : "mysql"},"name" : "mysql"},"spec" : {"replicas" : 1,"selector" : {    "name" : "mysql"},"template" : {"metadata" : {"labels" : {"name" : "mysql"}},"spec" : {"containers" : [ {"image" : "mysql","imagePullPolicy" : "IfNotPresent","name" : "mysql","ports" : [ {"containerPort" : 3306,"name" : "mysql"} ]                  }]}}}}

下面是我们如何定义一个例子服务暴露了MySQL端口。 服务选择器正在使用我们在上面指定的键/值对,以便定义提供服务的Pod。

{"kind": "Service","apiVersion": "v1beta3","metadata": {"name": "mysql"},"spec": {"ports": [{"name": "mysql","protocol": "TCP","port": 3306,"targetPort": 3306}],"selector": {"name": "mysql"}}
}

Kubernetes将服务信息作为环境变量传递给每个容器。 对于创建的每个容器, Kubernetes将确保为容器可见的所有服务传递适当的环境变量。

对于上述示例的mysql服务,环境变量将为:

  • MYSQL_SERVICE_HOST
  • MYSQL_SERVICE_PORT

Fabric8提供了一个CDI扩展,可以通过提供Kubernetes资源注入来简化Kubernetes应用程序的开发。

Fabric8 CDI扩展入门

要使用cdi扩展,第一步是将依赖项添加到项目中。

<dependency><groupId>io.fabric8</groupId><artifactId>fabric8-cdi</artifactId><version>2.1.11</version>
</dependency>

下一步是确定要向哪个字段注入的服务,然后向其添加@ServiceName批注。

import javax.inject.Inject;
import io.fabric8.annotations.ServiceName;public class MysqlExample {private static final DB = "mydb";private static final TCP_PROTO = "tcp";private static final JDBC_PROTO = "jdbc:mysql";private final Connection connection;public MysqlExample(@Inject @ServiceName("mysql") String serivceUrl) {Class.forName("com.mysql.jdbc.Driver");return DriverManager.getConnection(toJdbcUrl(serivceUrl));}private static String toJdbcUrl(String url) {return url.replaceFirst(TCP_PROTO, JDBC_PROTO) +"/" +DB;}//More stuff
}

在上面的示例中,我们有一个类,需要通过JDBC连接到可通过Kubernetes Services进行访问的mysql数据库。

注入的serivceUrl的格式为:[tcp | udp]:// [host]:[port]。 这是一个非常好的URL,但不是正确的jdbc url。 因此,我们需要一个实用程序来进行转换。 这是toJdbcUrl的目的。

即使可以在定义服务时指定协议,但只能指定核心传输协议,例如TCP或UDP,而不能指定http,jdbc等。

@Protocol批注

必须查找并用应用程序协议替换“ tcp”或“ udp”值,这很臭,而且很快就会变旧。 为了删除该样板, Fabric8提供了@Protocol批注。 该批注允许您在注入的服务URL中选择所需的应用程序协议。 在前面的示例中为“ jdbc:mysql”。 因此,代码可能类似于:

import javax.inject.Inject;
import io.fabric8.annotations.Protocol;
import io.fabric8.annotations.ServiceName;public class MysqlExampleWithProtocol {private static final DB = "mydb";private final Connection connection;public MysqlExampleWithProtocol(@Inject @Protocol("jdbc:mysql") @ServiceName("mysql") String serivceUrl) {Class.forName("com.mysql.jdbc.Driver");return DriverManager.getConnection(serivceUrl + "/" + DB);}//More stuff
}

毫无疑问,这要干净得多。 它仍然不包含有关实际数据库的信息或通常作为JDBC Url的一部分传递的任何参数,因此这里有改进的余地。

人们可能希望本着同样的精神,可以使用@Path或@Parameter批注,但这两者都是属于配置数据的,因此不适合将其硬编码为代码。 而且,Fabric8的CDI扩展并不希望成为URL转换框架。 因此,相反,它允许您直接实例化用于访问任何给定服务的客户端并将其注入源中,从而解决了问题。

使用@Factory注释为Services创建客户端

在前面的示例中,我们看到了如何获取服务的URL并使用该URL创建JDBC连接。 任何需要JDBC连接的项目都可以复制该代码段,并且只要用户记得他需要设置实际的数据库名称,它就可以很好地工作。

如果不是复制并粘贴该代码片段就可以对其进行组件化和重用,那岂不是很棒吗? 这是工厂注释的开始。您可以使用@Factory注释任何接受服务URL作为参数并返回使用URL创建的对象的方法(例如,服务的客户端)。 因此,对于前面的示例,我们可以有一个MysqlConnectionFactory:

import java.sql.Connection;
import io.fabric8.annotations.Factory;
import io.fabric8.annotations.ServiceName;public class MysqlConnectionFactory {@Factory@ServiceNamepublic Connection createConnection(@ServiceName @Protocol("jdbc:mysql") String url) {Class.forName("com.mysql.jdbc.Driver");return DriverManager.getConnection(serivceUrl + "/" + DB); }
}

然后,可以不注入URL而直接注入连接,如下所示。

import java.sql.Connection;
import javax.inject.Inject;
import io.fabric8.annotations.ServiceName;public class MysqlExampleWithFactory {private Connection connection;public MysqlExampleWithProtocol(@Inject @ServiceName("mysql") Connection connection) {this.connection = connection;}//More stuff
}

这里会发生什么?

当CDI应用程序启动时,Fabric8扩展将接收有关所有带注释方法的事件。 它将跟踪所有可用的工厂,因此对于使用@ServiceName注释的任何非String注入点,它将创建一个在后台使用匹配的@Factory的Producer。

在上面的示例中,首先将注册MysqlConnectionFactory,并且当检测到具有@ServiceName限定符的Connection实例时,将创建委托给MysqlConnectionFactory的Producer (将遵守所有限定符)

这很棒,但是也很简单 。 为什么?

因为很少有这样的工厂仅需要该服务的URL。 在大多数情况下,需要其他配置参数,例如:

  • 认证信息
  • 连接超时
  • 更多 …。

将@Factory与@Configuration一起使用

在下一节中,我们将看到使用配置数据的工厂。 我将使用mysql jdbc示例,并添加对指定可配置凭据的支持。 但是在此之前,我要问一个反问的问题?

“如何配置容器化的应用程序?”

可能的最短答案是“使用环境变量”。

因此,在此示例中,我假设使用以下环境变量将凭据传递到需要访问mysql的容器:

  • MYSQL_USERNAME
  • MYSQL_PASSWORD

现在我们需要看看我们的@Factory如何使用它们。

我以前曾经想在CDI中使用环境变量,但是很有可能已经使用了Apache DeltaSpike 。 这个项目提供了@ConfigProperty批注,该批注允许您将环境变量注入CDI bean中(它的作用比实际更多)

import org.apache.deltaspike.core.api.config.ConfigProperty;
import javax.inject.Inject;public class MysqlConfiguration {@Inject@ConfigProperty(name = "USERNAME", defaultValue = "admin")private String username;@Inject@ConfigProperty(name = "PASSWORD", defaultValue = "admin")private String password;@Inject@ConfigProperty(name = "DATABASE_NAME", defaultValue = "mydb")private String databaseName;public String getUsername() {return username;}public String getPassword() {return password;}public String getDatabaseName() {return databaseName;}}

该bean可以与@Factory方法结合使用,以便我们可以将配置传递给工厂本身。

但是,如果我们有多个数据库服务器,配置了不同的凭据集或多个数据库怎么办? 在这种情况下,我们可以使用服务名称作为前缀,并让Fabric8确定应该为每个@Configuration实例查找哪些环境变量。

import javax.inject.Inject;
import io.fabric8.annotations.ServiceName;
import io.fabric8.annotations.Factory;
import io.fabric8.annotations.Protocol;
import io.fabric8.annotations.Configuration;public class MysqlExampleWithFactoryAndConfiguration {@Factory@ServiceNamepublic Connection createConnection(@ServiceName @Protocol("jdbc:mysql") String url, @Configuration MysqlConfiguration conf) {Class.forName("com.mysql.jdbc.Driver");return DriverManager.getConnection(serivceUrl + "/" + conf.getDatabaseName(), conf.getUsername(), conf.getPassword()); }
}

现在,我们有了一个可重用的组件,可以与在kubernetes内部运行的任何mysql数据库一起使用,并且可以完全配置。

Fabric8 CDI扩展中还有其他功能,但是由于本篇文章过长,以后的文章中将介绍它们。

敬请关注。

翻译自: https://www.javacodegeeks.com/2015/06/injecting-kubernetes-services-in-cdi-managed-beans-using-fabric8.html

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

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

相关文章

意外分配– JIT编译抖动

在研究ByteWatcher时 &#xff08;请参阅我的上一篇 文章 &#xff09;&#xff0c;我遇到了一些非常奇怪的事情。 这是实际的代码段&#xff0c;用于找出特定线程上的分配量&#xff1a; return (long) mBeanServer.invoke(name,GET_THREAD_ALLOCATED_BYTES,PARAMS,SIGNATUR…

fastd java下载_FastReport VCL报表控件

FastReport VCL报表控件是著名的 Delphi 打印控件。含全部源码。支持 Delphi 10.2 Tokyo&#xff0c;FastReport可以在大量的方式报表的创建过程中操纵对象。快速发展的报表和随后的打印&#xff0c;这样的优点&#xff0c;正如预览打印文档的外观。专业版除了报表标准版的功能…

#102030:在30天内运行20 10K来庆祝Java的20年

1995年5月23日是技术史上的重要时刻。 业界似乎并没有意识到当天发布的语言会在未来几年内完全改变技术的格局。 Java将在今年的同一天庆祝20岁生日。 Java 20年&#xff0c;哇&#xff01; 回顾20年前的存储器时代&#xff0c;思考一下Java的发明时间/方式。 万维网专用于精…

View 的 android:visibility属性的讨论

Android VIEW 中的 visibility 属性&#xff0c;在API中的描述为&#xff1a;Controls the initial visibility of the view. [控制VIEW的初始可见性]。 其中包含三个参数&#xff1a; * 默认值为visible&#xff0c;可见。这里需要注意的是 "invisible" 和 "go…

jms java client mq_将Java客户端(JMS)连接到IBM MQ时出现问题

我正在尝试使用基本上通过以下方式构建的Java客户端使用SSL消耗IBM MQ(版本8.0.0.8)&#xff1a;Oracle JKD 8和IBM JRE 7(出于测试目的&#xff0c;我每个都有一个客户端)com.ibm.mq.allclient-9.1.0.0.jarjavax.jms-api-2.0.1.jarspring-jms-4.3.7.RELEASE.jarspring-jms-4.3…

JQuery-Dialog(弹出窗口,遮蔽窗口)

在Ajax中经常用到的弹出窗口和遮蔽窗口。自己写肯定是一个最佳方案&#xff0c;但时间和成本上&#xff0c;还是决定了寻找现成的吧。大概罗列一下。需要我满足我几个条件 一定要简洁方便拥有遮蔽功能&#xff0c;Model Dialog &#xff0c;所谓的模态窗口可以根据HTML弹出窗口…

java 设置系统参数_Java如何设置系统参数和运行参数

系统参数系统级全局变量&#xff0c;该参数在程序中任何位置都可以访问到。优先级最高&#xff0c;覆盖程序中同名配置。系统参数的标准格式为&#xff1a;-Dargnameargvalue&#xff0c;多个参数之间用空格隔开&#xff0c;如果参数值中间有空格&#xff0c;则用引号括起来。其…

HDU 1244 DP

题目大意: 我们需要将一串数字分成多个确定个数的连续段&#xff0c;在得到所有段的和的最大值 定义一个dp[i][j]数组表示在前j个数中取满 i 个段所能得到的最大值 那么也就是说明在这道题目当中每一段都是必须要被取到的 能够取到的前提是 j > cnt[i] //表示前 i 段的数字个…

java怎么生成字母_java自动生成字母

新建一个类SpringContextUtil.java&#xff1a;import org.springframework.beans.BeansException;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;/*** 获取spring容器&#xff0c;以访问容器中定义的其…

一天一块钱第二天翻倍_再把钱翻倍

一天一块钱第二天翻倍总览 很久以前&#xff0c;我写了一篇关于用双倍赚钱的文章。 但是&#xff0c;当解决方案相当简单时&#xff0c;仍然是许多开发人员普遍担心的问题。 用双倍赚钱的问题 double有两种类型的错误。 它存在表示错误。 即它不能精确地表示所有可能的十进制…

移动端回到顶部

PC端回到顶部&#xff0c;很多人都是用js来写的。这样效果比较好一些了&#xff0c;但是在移动端的时候&#xff0c;就没必要搞个animate的动画了&#xff0c;然后实现回到顶部的方法也有&#xff1a;window.scrollTo(0,0)。但是更简单的就是a锚点里面href"#"&#x…

java调用接口实现的方法_java调用接口的实现方法

java调用接口的实现方法发布时间&#xff1a;2020-06-29 11:08:46来源&#xff1a;亿速云阅读&#xff1a;78作者&#xff1a;Leah本篇文章给大家分享的是有关java调用接口的实现方法&#xff0c;小编觉得挺实用的&#xff0c;因此分享给大家学习&#xff0c;希望大家阅读完这篇…

Java EE应用程序的单片到微服务重构

您是否曾经想过将现有的Java EE整体应用程序重构为基于微服务的应用程序需要做什么&#xff1f; 该博客解释了一个简单的购物车示例如何转换为基于微服务的应用程序&#xff0c;以及围绕它的一些担忧。 整体和基于微服务的应用程序的完整代码库位于&#xff1a; github.com/ar…

Java代码韦伯分布_第十五节、韦伯局部描述符(WLD,附源码)

纹理作为一种重要的视觉线索&#xff0c;是图像中普遍存在而又难以描述的特征&#xff0c;图像的纹理特征一般是指图像上地物重复排列造成的灰度值有规则的分布。纹理特征的关键在于纹理特征的提取方法。目前&#xff0c;用于纹理特征提取的方法有很多&#xff0c;最具有代表性…

windows和linux删除文件方法

Windows下bat文件内容如下&#xff1b;复制代码 代码如下: echo offforfiles -p "D:\servers\apache2.2\logs" -s -m *.log -d -15 -c "cmd /c del path"forfiles -p "D:\servers\mysql\logs" -s -m *.log -d -15 -c "cmd /c del path"…

JavaFX真实世界应用程序:欧洲电视网广播联盟

我荣幸地与今年在德累斯顿Saxonia 系统公司工作的Alexander Casall一起在JavaOne上展示了多个JavaFX Real-World应用程序。 在准备本次演讲时&#xff0c;我们向客户和合作伙伴发送了一份调查表&#xff0c;并向他们询问了一些与他们的项目&#xff0c;他们的应用程序以及他们对…

java 三大集合_java中的三大集合入门笔记(简单实用)

为什么使用集合框架如图&#xff1a;集合的好处&#xff1a;集合弥补了数组的缺陷&#xff0c;它比数组更灵活更实用&#xff0c;可大大提高软件的开发效率&#xff0c;而且不同的集合适用于不同的场合。Java集合主要分为以下3种类型Java集合框架提供了一套性能优良、使用方便的…

java POI 写入百万数据到 excel

.xls文件只支持6w的数据写入 .xlsx文件只支持104w数据的写入 在java中jxl工具类只能操作.xls的文件&#xff0c;不能操作.xlsx的文件 POI工具类能够支持.xlsx的文件操作。 excel的数据读写都相应的简单&#xff0c;网上也有很多的代码&#xff0c;我这里要说的是怎么样写入100w…

摆脱困境:将运行时配置作为JSON返回

如果需要确定部署到远程服务器的Spring Web应用程序的运行时配置&#xff0c;则需要读取从远程服务器找到的属性文件。 这很麻烦。 幸运的是&#xff0c;有更好的方法。 这篇博客文章描述了我们如何 启动我们的Web应用程序时&#xff0c;将运行时配置写入日志文件。 返回运行…

网络爬虫依赖的架包

网络爬虫依赖的架包 commons-codec-1.3.jarcommons-httpclient-3.1.jarcommons-logging-1.0.4.jarhtmllexer.jarhtmlparser.jar 转载于:https://www.cnblogs.com/aicpcode/p/4194898.html