合肥企业建网站,如何实现企业网站推广的系统性,全部游戏免费(试玩),wordpress文章分类显示php cdi序幕 我在Kubernetes中最喜欢的是发现服务的方式。 为什么#xff1f; 主要是因为用户代码不必处理注册#xff0c;查找服务#xff0c;也没有网络意外#xff08;如果您曾经尝试过基于注册表的方法#xff0c;那么您就会知道我在说什么#xff09; 。 这篇文章… 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扩展第一步是将依赖项添加到项目中。 dependencygroupIdio.fabric8/groupIdartifactIdfabric8-cdi/artifactIdversion2.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而不能指定httpjdbc等。 Protocol批注 必须查找并用应用程序协议替换“ tcp”或“ udp”值这很臭而且很快就会老化。 为了删除该样板 Fabric8提供了Protocol批注。 该批注允许您在注入的服务URL中选择所需的应用程序协议。 在前面的示例中为“ jdbcmysql”。 因此代码可能类似于 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 {FactoryServiceNamepublic 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 {InjectConfigProperty(name USERNAME, defaultValue admin)private String username;InjectConfigProperty(name PASSWORD, defaultValue admin)private String password;InjectConfigProperty(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 {FactoryServiceNamepublic 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.htmlphp cdi