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

php cdi

序幕

我在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

php cdi

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

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

相关文章

oracle日志恢复启用命令,oracle 日志恢复数据详解

1&#xff1a;首先查找redo&#xff0c;如果redo有可供恢复的信息&#xff0c;就那redo中的信息进行恢复&#xff0c;此时一般在恢复时&#xff0c;类似如下:SQL> recover database;Media recovery complete.2&#xff1a;如果在redo中没有找到可供恢复的信息&#xff0c;or…

9 个很酷的 CMD 命令

点击蓝字关注我们ipconfig功能&#xff1a;查询本机IP地址操作方法&#xff1a;只要在在打开的cmd命令界面中输入“ipconfig”就可以了。msg功能&#xff1a;向对方电脑发送一条文本提示操作方法&#xff1a;首先你要知道对方的IP地址&#xff0c;接下来输入命令“msg /server:…

使用java进行婚礼庆祝_#102030:在30天内运行20 10K,庆祝Java 20年

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

oracle 插入出错_使用sqlca打印错误原因,ORACLE-Proc:SQLCA

SQL 通信区是用下列语句描述的&#xff1a;EXEC SQL INCLUDE SQLCA&#xff1b;此部分提供了用户运行程序的成败记录和错误处理。SQLCA的组成SQLCA是一个结构类型的变量&#xff0c;它是ORACLE 和应用程序的一个接口。在执行 Pro*C程序时&#xff0c; ORACLE 把每一个嵌入SQL语…

这几行 C++ 代码,真的骚!

点击蓝字关注我们事情是这么一回事&#xff1a;国外有个大佬在StackExchange上发起了一个叫做 Tweetable Mathematical Art 的比赛。参赛者需要用C编写代表三原色的RD、GR、BL三个函数&#xff0c;每个函数都不能超过 140 个字符。每个函数都会接到 i 和 j 两个整型参数&#x…

sts集成jboss_JBoss BPM Travel Agency演示与现代BPM数据集成

sts集成jboss不久前&#xff0c;我们启动了一个规模较大的JBoss Travel Agency演示项目&#xff0c;以展示JBoss BPM Suite的一些更有趣的功能。 我们提供了一系列视频 &#xff0c;不仅向您展示了如何安装它&#xff0c;项目中各种规则和流程工件的含义&#xff0c;还向您介绍…

详解C语言的C#数组

点击蓝字关注我们数组是一种存储相同类型元素的固定大小顺序集合。数组用于存储数据集合&#xff0c;但一般会将数组视为存储在连续存储器位置的相同类型的变量的集合。如果要存储表示100名称学生的分数&#xff0c;需要独立地声明100整数变量。例如&#xff1a;number0.number…

jdk注解_我们正在下注:这个注解很快就会出现在JDK中

jdk注解Yahor最近提出的Stack Overflow问题引起了我的兴趣&#xff1a; 如何在Java 8编译时确保方法签名“实现”功能接口 。 这是一个很好的问题。 让我们假设以下名义类型&#xff1a; FunctionalInterface interface LongHasher {int hash(long x); }该类型强加了清晰的合同…

oracle的连接函数,Oracle各种连接函数总结

1.前言Oracle可用连接函数会介绍以下几个Oracle列转行函数 Listagg()strcat()wmsys.wm_concat()2.Oracle列转行函数 Listagg()2.1最基础的用法&#xff1a;LISTAGG(XXX,XXX) WITHIN GROUP( ORDER BY XXX)用法就像聚合函数一样&#xff0c;通过Group by语句&#xff0c;把每个Gr…

抽象工厂模式设计模式_21世纪的设计模式:抽象工厂模式

抽象工厂模式设计模式这是我的演讲的第二部分&#xff0c;“ 21世纪的设计模式” 。 此模式在Java代码中到处都有使用&#xff0c;尤其是在更多“企业”代码库中。 它涉及一个接口和一个实现。 该界面如下所示&#xff1a; public interface Bakery {Pastry bakePastry(Toppi…

对 C 语言指针最详尽的讲解

点击蓝字关注我们指针对于C来说太重要。然而&#xff0c;想要全面理解指针&#xff0c;除了要对C语言有熟练的掌握外&#xff0c;还要有计算机硬件以及操作系统等方方面面的基本知识。所以本文尽可能的通过一篇文章完全讲解指针。为什么需要指针&#xff1f;指针解决了一些编程…

app http routes.php,Laravel:我的应用程序没有被路由(Laravel : My app doesn't get routed)

Laravel&#xff1a;我的应用程序没有被路由(Laravel : My app doesnt get routed)我正在运行我的第一个laravel应用程序&#xff0c;在接下来的几个小时中遇到依赖项安装错误。对不起它可能是一个小错误&#xff0c;但似乎我无法找到。图片较暗&#xff0c;电脑坏了。应用程序…

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

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

为什么 Android 必须在主线程更新 UI ?

点击蓝字关注我们为什么Android必须在主线程更新UI&#xff1f;站在各位大牛的肩膀上&#xff0c;谢谢&#xff01;正常情况下&#xff0c;Android需要在UI线程更新UI&#xff0c;然鹅&#xff0c;在特殊情况下&#xff0c;子线程也能更新UI不在讨论之列&#xff0c;这篇文章主…

如何对linux文件进行编译,Linux下将源文件编译成目标文件的过程解析

简介请讲一下linux如何源文件逐步编译成可执行文件。解答首先先上图对编译的整个过程有个感性的认识&#xff0c;然后再逐步分析各个过程。以hello.c 程序为例# include main{printf("hello\n");}一个.c源程序需要经过预处理器生成.i文件&#xff0c;再经过编译器生成…

eclipse m2e配置_使用此首选项可加快Eclipse m2e配置

eclipse m2e配置谁不认识他们。 Eclipse中的旧式JFace对话框可以使您直观地看到实际上是一个相当简单的XML或属性文件。 对于m2e&#xff0c;它看起来像这样&#xff1a; 不幸的是&#xff0c;此屏幕的加载速度有点慢&#xff0c;除了检查版本号和其他您将永远不会更改的东西…

学点 STL C++ 的线性容器

点击蓝字关注我们std::array看到这个容器的时候肯定会出现这样的问题&#xff1a;为什么要引入 std::array 而不是直接使用 std::vector&#xff1f;已经有了传统数组&#xff0c;为什么要用 std::array?先回答第一个问题&#xff0c;与 std::vector 不同&#xff0c;std::arr…

linux at查看进程命令,at命令 - Linux命令大全 | linux教程

at命令允许指定运行脚本时间&#xff0c;at的守护进程atd会以后台模式运行&#xff0c;检查系统上的一个特殊目录来获取at命令的提交的作业。默认情况下&#xff0c;atd守护进程每60秒检查一次目录。有作业时会检查作业运行时间&#xff0c;如果与当前时间匹配&#xff0c;则运…

java替换数组中的元素_如何使用Java 8流快速替换列表中的元素

java替换数组中的元素假设您有一个项目清单&#xff1a; List<String> books Arrays.asList("The Holy Cow: The Bovine Testament","True Hip Hop","Truth and Existence","The Big Book of Green Design" );&#xff08;不要…

C++:良好的编程习惯与编程要点

点击蓝字关注我们以良好的方式编写C class假设现在我们要实现一个复数类complex&#xff0c;在类的实现过程中探索良好的编程习惯。① Header(头文件)中的防卫式声明complex.h: # ifndef __COMPLEX__ # define __COMPLEX__ class complex {} # endif防止头文件的内容被多次包含…