欢迎访问我的GitHub

https://github.com/zq2599/blog_demos

内容:所有原创文章分类汇总及配套源码,涉及Java、Docker、Kubernetes、DevOPS等;

概览

  1. 本文是《Kubernetes官方java客户端》系列的第八篇,以下提到的java客户端都是指client-jar.jar;
  2. 前文《Kubernetes官方java客户端之七:patch操作》涉及的知识点、代码、操作都太多了,对作者和读者都是莫大的折磨,到了本篇咱们轻松一下,写几段简单流畅的代码,了解java客户端对fluent style编程的支持,并且编码完成后的验证操作也很简单;

关于fluent styel

  1. 也称为fluid coding, fluent programming,是一种增强代码可读性的风格,使得阅读代码时更加自然流畅,特点是函数返回有关类型,使得多个函数的调用前后链接起来。
  2. 关于fluent style可以参考Martin Flowler于2005年发表的文章,地址是:https://martinfowler.com/bliki/FluentInterface.html ,使用fluent style前后的代码对比如下图所示:

源码下载

  1. 如果您不想编码,可以在GitHub下载所有源码,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos):
名称 链接 备注
项目主页 https://github.com/zq2599/blog_demos 该项目在GitHub上的主页
git仓库地址(https) https://github.com/zq2599/blog_demos.git 该项目源码的仓库地址,https协议
git仓库地址(ssh) git@github.com:zq2599/blog_demos.git 该项目源码的仓库地址,ssh协议
  1. 这个git项目中有多个文件夹,本章的应用在kubernetesclient文件夹下,如下图红框所示:

实战步骤概述

  1. 在父工程kubernetesclient下面新建名为fluent的子工程;
  2. fluent工程中只有一个类FluentStyleApplication,启动的main方法以及fluent style的代码都在此类中;
  3. FluentStyleApplication.java提供四个web接口,功能分别是:新建namespace、新建deployment、新建service、删除前面三个接口新建的所有资源;
  4. fluent工程编码完成后,不需要做成镜像部署在kubernetes环境内部,而是作为一个普通SpringBoot应用找个java环境启动即可,与《Kubernetes官方java客户端之三:外部应用 》一文的部署和启动一致;
  5. 依次调用每个接口,验证功能是否符合预期;

编码

  1. 在父工程kubernetesclient下面新建名为fluent的maven子工程,pom.xml内容如下,需要注意的是排除掉spring-boot-starter-json,原因请参考《Kubernetes官方java客户端之二:序列化和反序列化问题 》
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>kubernetesclient</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent> <groupId>com.bolingcavalry</groupId>
<artifactId>fluent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>fluent</name>
<description>Demo project for fluent style</description>
<packaging>jar</packaging> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</exclusion>
</exclusions>
</dependency> <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency> <dependency>
<groupId>io.kubernetes</groupId>
<artifactId>client-java</artifactId>
</dependency> </dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.0.RELEASE</version>
</plugin>
</plugins>
</build> </project>
  1. 新建FluentStyleApplication.java,首先,该类作为启动类,要有main方法:
public static void main(String[] args) {
SpringApplication.run(FluentStyleApplication.class, args);
}
  1. 定义常量NAMESPACE作为本次实战的namespace:
private final static String NAMESPACE = "fluent";
  1. 用@PostConstruct注解修饰setDefaultApiClient方法,令其在实例化时执行一次,里面做了一些全局性的初始化设置,注意kubeConfigPath变量对应的config文件路径要正确:
/**
* 默认的全局设置
* @return
* @throws Exception
*/
@PostConstruct
private void setDefaultApiClient() throws Exception {
// 存放K8S的config文件的全路径
String kubeConfigPath = "/Users/zhaoqin/temp/202007/05/config";
// 以config作为入参创建的client对象,可以访问到K8S的API Server
ApiClient client = ClientBuilder
.kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath)))
.build(); // 会打印和API Server之间请求响应的详细内容,生产环境慎用
client.setDebugging(true); // 创建操作类
Configuration.setDefaultApiClient(client);
}
  1. 接下来是创建namespace的web服务,如下所示,由于namespace在kubernetes的apiVersion是v1,因此创建的是V1Namespace实例:
 @RequestMapping(value = "/fluent/createnamespace")
public V1Namespace createnamespace() throws Exception { V1Namespace v1Namespace = new V1NamespaceBuilder()
.withNewMetadata()
.withName(NAMESPACE)
.addToLabels("label1", "aaa")
.addToLabels("label2", "bbb")
.endMetadata()
.build(); return new CoreV1Api().createNamespace(v1Namespace, null, null, null);
}
  1. 为了更清晰的展现fluent style效果,将上述代码与创建namespace的yaml文件内容放在一起对比,如下图所示,可见对照着yaml文件就能将代码写出来:

  2. 接下来是创建service的代码,为了便于和yaml对应起来,代码中特意加了缩进:

 @RequestMapping(value = "/fluent/createservice")
public V1Service createservice() throws Exception {
V1Service v1Service = new V1ServiceBuilder()
// meta设置
.withNewMetadata()
.withName("nginx")
.endMetadata() // spec设置
.withNewSpec()
.withType("NodePort")
.addToPorts(new V1ServicePort().port(80).nodePort(30103))
.addToSelector("name", "nginx")
.endSpec()
.build(); return new CoreV1Api().createNamespacedService(NAMESPACE, v1Service, null, null, null);
}
  1. 创建deployment的代码如下,因为内容较多所以相对复杂一些,请注意,由于deployment在kubernetes的apiVersion是extensions/v1beta1,因此创建的是ExtensionsV1beta1Deployment实例:
 @RequestMapping(value = "/fluent/createdeployment")
public ExtensionsV1beta1Deployment createdeployment() throws Exception {
ExtensionsV1beta1Deployment v1Deployment = new ExtensionsV1beta1DeploymentBuilder()
// meta设置
.withNewMetadata()
.withName("nginx")
.endMetadata() // spec设置
.withNewSpec()
.withReplicas(1)
// spec的templat
.withNewTemplate()
// template的meta
.withNewMetadata()
.addToLabels("name", "nginx")
.endMetadata() // template的spec
.withNewSpec()
.addNewContainer()
.withName("nginx")
.withImage("nginx:1.18.0")
.addToPorts(new V1ContainerPort().containerPort(80))
.endContainer()
.endSpec() .endTemplate()
.endSpec()
.build(); return new ExtensionsV1beta1Api().createNamespacedDeployment(NAMESPACE, v1Deployment, null, null, null);
}
  1. 从上述代码可见,withXXX和endXXX是成对出现的,请在编程的时候注意不要遗漏了endXXX,建议在写withXXX的同时就把endXXX写上;
  2. 最后一个方法是清理所有资源的,前面创建的deployment、service、namespace都在此一次性清理掉,实际操作中发现了一个尴尬的情况:删除deployment和namespace时,发送到API Server的删除请求都收到的操作成功的响应,但kubernetes客户端在反序列化响应内容时抛出异常(日志中显示了详细情况),鄙人能力有限暂未找到解决之道,因此只能用try catch来避免整个方法抛出异常,好在kubernetes实际上已经删除成功了,影响不大:
    @RequestMapping(value = "/fluent/clear")
public String clear() throws Exception { // 删除deployment
try {
new ExtensionsV1beta1Api().deleteNamespacedDeployment("nginx", NAMESPACE, null, null, null, null, null, null);
} catch (Exception e)
{
log.error("delete deployment error", e);
} CoreV1Api coreV1Api = new CoreV1Api(); // 删除service
coreV1Api.deleteNamespacedService("nginx", NAMESPACE, null, null, null, null, null, null); // 删除namespace
try {
coreV1Api.deleteNamespace(NAMESPACE, null, null, null, null, null, null);
} catch (Exception e)
{
log.error("delete namespace error", e);
} return "clear finish, " + new Date();
}
  1. 编码已完成,启动fluent工程,接下来开始验证功能是否正常;

验证

  1. 将fluent工程直接在IEDA环境启动;

  2. 浏览器访问:http://localhost:8080/fluent/createnamespace ,页面会展示API Server返回的完整namespace信息:

  3. 浏览器访问:http://localhost:8080/fluent/createservice ,页面会展示API Server返回的完整service信息:

  4. 浏览器访问:http://localhost:8080/fluent/createdeployment ,页面会展示API Server返回的完整deployment信息:

  5. 验证前面几个接口创建的服务是否可用,我这里kubernetes的IP地址是192.168.50.135,因此访问:http://192.168.50.135:30103 ,可以正常显示nginx首页:

  1. SSH登录kubernetes服务器查看,通过kubernetes的java客户端创建的资源都正常:

  2. 验证完成后,浏览器访问:http://localhost:8080/fluent/clear ,即可清理掉前面三个接口创建的资源;

  • 至此,基于fluent style调用java客户端的实战就完成了,希望您能熟练使用此风格的API调用,使得编码变得更加轻松流畅,顺便预告一下,下一篇继续做一些简单轻松的操作,目标是熟悉java客户端的常用操作;

你不孤单,欣宸原创一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 数据库+中间件系列
  6. DevOps系列

欢迎关注公众号:程序员欣宸

微信搜索「程序员欣宸」,我是欣宸,期待与您一同畅游Java世界...

https://github.com/zq2599/blog_demos

Kubernetes官方java客户端之八:fluent style的更多相关文章

  1. elasticsearch系列七:ES Java客户端-Elasticsearch Java client(ES Client 简介、Java REST Client、Java Client、Spring Data Elasticsearch)

    一.ES Client 简介 1. ES是一个服务,采用C/S结构 2. 回顾 ES的架构 3. ES支持的客户端连接方式 3.1 REST API ,端口 9200 这种连接方式对应于架构图中的RE ...

  2. zookeeper生产最广泛使用java客户端curator介绍及其它客户端比较

    关于zookeeper的原理解析,可以参见zookeeper核心原理详解,本文所述大多数实践基于对zookeeper原理的首先理解. Curator是Netflix公司开源的一个Zookeeper客户 ...

  3. Java与WCF交互(一)补充:用WSImport生成WSDL的Java客户端代码

    在<Java与WCF交互(一):Java客户端调用WCF服务>一 文中,我描述了用axis2的一个Eclipse控件生成WCF的Java客户端代理类,后来有朋友建议用Xfire.CXF,一 ...

  4. Java与WCF交互(一):Java客户端调用WCF服务

    最近开始了解WCF,写了个最简单的Helloworld,想通过java客户端实现通信.没想到以我的基础,居然花了整整两天(当然是工作以外的时间,呵呵),整个过程大费周折,特写下此文,以供有需要的朋友参 ...

  5. 使用Java客户端操作elasticsearch

    Java REST客户端有两种风格: Java低级别REST客户端(Java Low Level REST Client,以后都简称低级客户端算了,难得码字):Elasticsearch的官方low- ...

  6. 使用java客户端调用redis

    Redis支持很多编程语言的客户端,有C.C#.C++.Clojure.Common Lisp.Erlang.Go.Lua.Objective-C.PHP.Ruby.Scala,甚至更时髦的Node. ...

  7. Memcached学习笔记 — 第四部分:Memcached Java 客户端-gwhalin(1)-介绍及使用

     介绍 Memcached java client是官方推荐的最早的memcached java客户端.最新版本:java_memcached-release_2.6.1. 官方下载地址:http ...

  8. axis根据wsdl生成java客户端代码

    根据wsdl生成java客户端代码有多个方法,其中使用axis生成的代码比较友好,也是经常用的一种方法.首先下载axis jar包:axis-bin-1_4.zip 官方地址:http://ws.Ap ...

  9. zookeeper的Java客户端API

    zookeeper作为一个分布式服务框架,主要用来解决分布式数据一致性问题,对多种语言提供了API.这里主要记录下JAVA客户端API的使用. 1.创建会话 客户端可以通过创建一个ZooKeeper实 ...

  10. FastDFS分布文件系统Java客户端集成

    参考博客:http://blog.csdn.net/xyang81/article/details/52847311 官网Java客户端源代码: https://github.com/happyfis ...

随机推荐

  1. There are no resources that can be added or removed from the server

    第1步.新建一个“Dynamic Web Project” 第2步.把新建项目里面的.project文件和.settings文件夹复制到导入的那个项目里面. 第3步.把web projiect set ...

  2. 【2016-10-11】【坚持学习】【Day2】【代理模式】

    今天学习了代理模式. 定义 官方: 代理模式:给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问. Proxy Pattern: Provide a surrogate or plac ...

  3. TDBGridEh的 搜索面板 TDBGridSearchPanel

    TCustomDBGridEh.Create FSearchPanelControl := TDBGridSearchPanelControlEh.Create(Self); //这里,创建的构造函数 ...

  4. 《C#并行编程高级教程》第8章 线程池 笔记

    主要的几个概念(详细最好还是看书,配合插图看)   任务是会被分配到线程上的,而这些线程都在线程池引擎下管理 线程池引擎管理着合适数量的线程池,线程从全局队列获取工作项执行. .NET4 Framew ...

  5. ABAP更换请求

    当创建的程序或表操作失误存储在其他的请求下边如何更换请求呢? 事务代码:SE09 双击请求号,复制存储错误的对象 打开一个新窗口,双击正确的请求,点击修改,将复制的对象粘贴在正确的请求下 将错误的请求 ...

  6. python批量修改文件内容及文件编码方式的处理

    最近公司在做tfs迁移,后面要用新的ip地址去访问tfs 拉取代码  ,所以原来发布脚本中.bat类型的脚本中的的ip地址需要更换 简单说下我们发布脚本层级目录 :每个服务站点下都会有一个发布脚本 . ...

  7. Verilog TestBench Coding Style

    Abtract 关于编写testbench的一些经验总结心得. Introduction 1.基本的Testbench结构 1)常用的编码结构 `timescale 1 ns / 1 ps       ...

  8. mysql 取得各种时间

    转载 取得当前日期:DATE_FORMAT(NOW(),'%e'): 取得当前年月:DATE_FORMAT(NOW(),'%Y-%c'):Y:四位.y:两位:m:两位.c:前面不加0: /*当前时间加 ...

  9. python基础知识回顾之元组

    元组与列表的方法基本一样,只不过创建元组是用小括号()把元素括起来,两者的区别在于,元组的元素不可被修改. 元组被称为只读列表,即数据可以被查询,但不能被修改,列表的切片操作适用于元组. 元组写在小括 ...

  10. PowerDNS简单教程(3):管理篇

    目录: PowerDNS简单教程(1):安装篇 http://www.cnblogs.com/anpengapple/p/5205130.html PowerDNS简单教程(2):功能篇 http:/ ...