六种开发环境部署大全:基于Openshift

前言

本文包含在Openshift上部署六种开发环境的步骤,分别是:

OpenShift for Fuse DevelopersEclipse Vert.x developmentSpring Boot developmentWildFly Swarm developmentNode.js developmentJava EE Batch Processing with OpenShift, WildFly

文中实验源自:https://learn.openshift.com/middleware/,本文内容仅供参考。

第一种:部署Wildfly Swarm

Jave EE的应用通常被创建成ear或者war包。ear或者war包含应用和应用的所有依赖包,并被部署到应用服务器上。多个Java EE的应用可以被部署到一个应用服务器上。

而WildFly Swarm提供新的打包和运行 Java EE 应用的方式:直接在JVM桑通过 java -jar来运行Java应用。

WildFly Swarm基于WildFly,它是Jave EE标准的一个子集,因此它大大简化了Jave EE应用实现微服务的复杂度。

在本实验中,我们将在OCP上部署Wildfly Swarm。

首先先看一个Maven项目:

$ tree

├── pom.xml

└── src

└── main

├── fabric8

│ └── deployment.yml

├── java

│ └── com

│ └── example

│ ├── ApplicationConfig.java

│ ├── Greeting.java

│ └── GreetingResource.java

└── webapp

└── index.html

7 directories, 6 files

项目中:

pom.xml文件描述了如何构建这个项目。

ApplicationConfig.java:应用对外提供服务,接受外部请求。Greeting.java:描述了一个Java对象,它包含一个发送的问候信息。

GreetingResource.java:定义了/greeting and /stop RESTful 的endpoints.

接下来,用maven编译并运行这个应用:

mvn wildfly-swarm:run

然后通过浏览器访问这个应用进行测试:

接下来,在OCP中部署这个应用:

通过maven触发fabric工具,在OCP中通过S2I部署这个应用:

mvn clean fabic8:deploy -Popenshift

查看应用routes

通过浏览器访问routes:

第二种:部署Node.js

Node.js是一个基于Chrome V8的JavaScript运行时。

接下来,我们通过实验展示在OCP上部署Node.js的应用。

先看一个Node.js的源码:

package.json:项目的元数据,包括名称、版本、依赖等。

app.js:主应用逻辑

app-config.yml :用于触发、OpenShift ConfigMap

index.html :Web应用的页面

先安装依赖:

然后启动应用:

通过浏览器访问应用:

接下来,在OCP中部署应用:

通过浏览器访问应用的route:

还可以给应用增加Configure Map

增加完以后,访问route:

第三种:部署Java EE批处理,WildFly & JBeret

批处理通常是非交互式、后台执行的。批处理通通常涉及大量的数据处理和密集计算。

JBeret项目实现JSR 352(Java平台的批处理应用程序)以及Java SE和Java EE环境中的其他高级批处理功能。 JBeret包含在WildFly和JBoss EAP中,提供企业批处理功能。

接下来,我们通过实验来展示 。

基于 WildFly image, 通过S2I的方式部署 Java batch应用:

部署应用:

oc rollout status dc/intro-jberet

oc expose svc intro-jberet

然后通过浏览器访问应用:

接下来,创建PostgreSQL 数据库:

oc new-app postgresql-ephemeral --name postgresql --param POSTGRESQL_USER=jberet --param POSTGRESQL_PASSWORD=jberet

#oc rollout status dc/postgresql

本实验的批处理任务默认在作业XML文件csv2db中定义,包含两个步骤:

csv2db.step1:它执行特定的任务:初始化数据库表MOVIES。

"jdbc:postgresql://#?:postgresql;/#?:sampledb;"/>

"#?:jberet;"/>

"#?:jberet;"/>

CREATE TABLE IF NOT EXISTS MOVIES (

rank INTEGER NOT NULL PRIMARY KEY,

tit VARCHAR(128),

grs NUMERIC(12, 3),

opn DATE);

DELETE FROM MOVIES"/>

csv2db.step2:块类型的步骤,读取、处理和写入数据块,并重复读取过程写入过程,直到输入结束。

"https://raw.githubusercontent.com/jberet/jsr352/master/jberet-support/src/test/resources/movies-2012.csv"/>

"java.util.Map"/>

"rank,tit,grs,opn"/>

"ParseInt;

NotNull, StrMinMax(1, 100);

ParseDate('yyyy-MM-dd')"/>

"insert into MOVIES (rank,tit,grs,opn)

VALUES (?, ?, ?, ?)"/>

"rank,tit,grs,opn"/>

"Int,String,Double,Date"/>

"java.util.Map"/>

在csv2db作业中,使用jberet-support库中的3个批处理工件来实现处理逻辑:

jdbcBatchlet:针对目标数据库执行SQL语句。csvItemReader:从CSV输入源读取,一次一行。jdbcItemWriter:将块中的累积数据写入目标数据库。

使用curl命令行工具来调用REST API来执行各种批处理操作。 JSON输出使用python -m json.tool格式化。

启动csv2db任务:

curl -s -X POST -H 'Content-Type:application/json' "http://intro-jberet-jberet-lab.2886795303-80-simba02.environments.katacoda.com/intro-jberet/api/jobs/csv2db/start" | python -m json.tool

查看任务执行情况:

curl -s http://intro-jberet-jberet-lab.2886795303-80-simba02.environments.katacoda.com/intro-jberet/api/jobexecutions/1 | python -m json.tool

查看任务的所有执行步骤:

curl -s http://intro-jberet-jberet-lab.2886795303-80-simba02.environments.katacoda.com/intro-jberet/api/jobexecutions/1/stepexecutions/ | python -m json.tool

查看第二个任务的执行结果:

curl -s http://intro-jberet-jberet-lab.2886795303-80-simba02.environments.katacoda.com/intro-jberet/api/jobexecutions/1/stepexecutions/2 | python -m json.tool

登录到数据库的pod中,查看表的内容:

第四种:部署JBoss Fuse开发环境

本实验将展示基于OCP部署JBoss Fuse Integration Services(FIS)2.0。JBoss FIS 2.0是一个敏捷、轻量级、现代化的开发框架,用于构建和部署高度可扩展的模块化API。它不仅提供了基于容器的开发实践,还提供了微服务框架,如:断路器,追踪,路由,转换,审计等等。

JBoss FIS有两种运行方式:

1.作为一个独立的Java应用程序(SpringBoot)

2.作为Apache Karaf(OSGi)的服务

FIS在Openshift上有三种部署方式:

1.通过docker image

2.本地构建,然后push到OCP,利用B2I完成后续的工作。

3.使用S2I的方式构建。

本实验展示的内容是:在Fuse上部署一个基于Spring Boot的People Service应用,该应用对外提供Rest API,实现微服务架构。

接下来,我们看实验过程:

根据模板创建应用:

这个模板定义了和build相关的地址链接和信息:

创建了如下资源:

接下来,手工触发build:

查看构建过程:

build成功,push镜像:

然后触发dc,构建了应用:

接下来,我们查看JBoss Fuse Hawtio console,查看Route Diagram10个子模块被调用的情况:

在cli发起查询一个用户信息请求

再次查看Route Diagram,查看上一步curl操作调用的模块(数字1表示被调用一次):

再发起一次查询:

查看Route Diagram,相关模块调用次数增加了一次:

再次触发查询

查看Route Diagram,相关模块调用次数增加了一次:

这次我们换一种查询方式,查看用户列表:

查看Route Diagram,有两个新的模块被调用(最右边一列)

接下来,为用户列表增加一个新的用户:

查看Route Diagram,又有两个新的模块被调用:

第五种:部署Eclipse Vert.x开发环境

Eclipse Vert.x是一个轻量级的微服务框架。本实验中,我们将在OCP中通过fabric工具部署vert.x应用。

我们先看一个Http Java应用的源码:

package com.example;

public class HttpApplication extends AbstractVerticle {

static final String template = "Hello, %s!";

@Override

public void start() {

// TODO: Create a router object

// TODO: Add router for /api/greeting here

// TODO: Add a StaticHandler for accepting incoming requests

// TODO: Create the HTTP server listening on port 8080

System.out.println("THE HTTP APPLICATION HAS STARTED");

}

// TODO: Add method for greeting here

}

接下来,我们通过maven编译并运行这个应用:

应用已经运行:

接下来,分别动态为源码增加如下内容(增加路由信息),应用自动刷新,实现响应式编程:

Router router = Router.router(vertx);

router.get("/*").handler(StaticHandler.create());

vertx.createHttpServer().requestHandler(router::accept).

三次输入触发了三次重新编译和重新部署:

接下来,通过浏览器访问应用:

接下来,为源码动态增加如下内容:

private void greeting(RoutingContext rc) {

String name = rc.request().getParam("name");

if (name == null) {

name= "World";

}

JsonObject response = new JsonObject()

.put("content", String.format(template,name));

rc.response()

.putHeader(CONTENT_TYPE, "application/json; charset=utf-8")

.end(response.encodePrettily());

}

再在源码中增加一个route:router.get("/api/greeting").handler(this::greeting);

然后,再次访问应用链接,这次在页面中输入template,会有相应的返回值:

接下来,我们在OCP中部署vert.x。

先在OCP中创建一个项目:

部署应用,下图fabric8:deploy是个小工具,通过mvn触发,实现vertx应用的整个S2I的过程:

接下来,查看应用的route并进行访问:

第六种:部署Spring Boot

Spring是最受欢迎的Java框架之一,提供了Java EE编程模型的替代方案。本实验中,我们将在OCP中部署一个Spring Boot应用:

我们先看一个maven project:

$ tree

.

├── pom.xml

└── src

├── main

│ ├── fabric8

│ │ ├── credentials-secret.yml

│ │ ├── deployment.yml

│ │ └── route.yml

│ ├── java

│ │ └── com

│ │ └── example

│ │ ├── Application.java

│ │ └── service

│ └── resources

│ ├── application-local.properties

│ ├── application-openshift.properties

│ └── static

│ └── index.html

└── test

└── java

└── com

└── example

13 directories, 8 files

fabric8下的内容,是和容器相关的内容;

java下的内容是源码和相关内容;

resources下分别是应用的配置文件和openshit的配置文件;

我们看一下Java的源码:

查看应用的pom.xml:

Copyright 2016-2017 Red Hat, Inc, and individual contributors.

Licensed under the Apache License, Version 2.0 (the "License");

you may not use this file except in compliance with the License.

You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software

distributed under the License is distributed on an "AS IS" BASIS,

WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

See the License for the specific language governing permissions and

limitations under the License.

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

com.example

fruits

15-SNAPSHOT

Simple Fruits Application

Spring Boot - CRUD Booster

9.4.1212

1.5.8.RELEASE

2.20

3.5.30

me.snowdrop

spring-boot-bom

$

pom

import

spring-boot-starter

spring-boot-starter-test

test

spring-boot-maven-plugin

$

local

exec

repackage

local

true

openshift

io.fabric8

fabric8-maven-plugin

$

fmp

resource

build

通过在pom.xml中增加如下内容,将 Tomcat增加到应用中:

接下来,编译并运行应用:

mvn spring-boot:run

浏览器访问应用的route,此时应用还没有连接数据库,因此没有内容。

接下来,给应用增加 JPA (Hibernate) ,让它可以访问关系型数据库。在pom.xml中增加。

接下来,在pom.xml增加一段in-memory内存的描述

接下来,创建一个java的源码Fruit.java,定义Entity class以更新数据库中的内容(一个数据库表模型):

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.GenerationType;

import javax.persistence.Id;

@Entity

public class Fruit {

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

private Integer id;

private String name;

public Fruit() {

}

public Fruit(String type) {

this.name = type;

}

public Integer getId() {

return id;

}

public void setId(Integer id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

再创建一个FruitRepository.java,它定义了对数据库操作服务。

public interface FruitRepository extends CrudRepository {

}

再定义可一个sql,用于向数据中插入数据:

insert into fruit (name) values ('Cherry');

insert into fruit (name) values ('Apple');

insert into fruit (name) values ('Banana');

最后书写一个应用测试程序:

package com.example;

import java.util.Collections;

import org.junit.Before;

import org.junit.Test;

import static org.junit.Assert.assertFalse;

import static org.junit.Assert.assertTrue;

@RunWith(SpringRunner.class)

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

public class ApplicationTest {

@Autowired

private FruitRepository fruitRepository;

@Before

public void beforeTest() {

}

@Test

public void testGetAll() {

assertTrue(fruitRepository.findAll().spliterator().getExactSizeIfKnown()==3);

}

@Test

public void getOne() {

assertTrue(fruitRepository.findOne(1)!=null);

}

@Test

public void updateAFruit() {

Fruit apple = fruitRepository.findOne(2);

assertTrue(apple!=null);

assertTrue(apple.getName().equals("Apple"));

apple.setName("Green Apple");

fruitRepository.save(apple);

assertTrue(fruitRepository.findOne(2).getName().equals("Green Apple"));

}

@Test

public void createAndDeleteAFruit() {

int orangeId = fruitRepository.save(new Fruit("Orange")).getId();

Fruit orange = fruitRepository.findOne(orangeId);

assertTrue(orange!=null);

fruitRepository.delete(orange);

assertTrue(fruitRepository.findOne(orangeId)==null);

}

@Test

public void getWrongId() {

assertTrue(fruitRepository.findOne(9999)==null);

}

}

接下来,运行并进行检查:

mvn verify

接下来,创建应用对外的service:FruitController.java

import java.util.List;

import java.util.Objects;

import java.util.Spliterator;

import org.springframework.web.bind.annotation.DeleteMapping;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.PutMapping;

import org.springframework.web.bind.annotation.RequestMapping;

@Controller

@RequestMapping(value = "/api/fruits")

public class FruitController {

private final FruitRepository repository;

@Autowired

public FruitController(FruitRepository repository) {

this.repository = repository;

}

@ResponseBody

@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)

public List getAll() {

return StreamSupport

.stream(repository.findAll().spliterator(), false)

.collect(Collectors.toList());

}

//TODO: Add additional service calls here

}

接下来,运行应用:

mvn spring-boot:run -DskipTests

运行成功以后,通过浏览器访问应用,已经可以看到数据库中的内容,并可以对它进行操作:

同样,我们可以很方便地将这个应用部署到OCP中:

创建数据库:

oc new-app -e POSTGRESQL_USER=luke \ -e POSTGRESQL_PASSWORD=secret \ -e POSTGRESQL_DATABASE=my_data \ openshift/postgresql-92-centos7 \ --name=my-database

在应用pom.xml定义对数据库的访问内容:

pom.xml增加对spring boot的健康检查内容:

部署应用:

mvn packagefabric8:deploy -Popenshift -DskipTests

访问route:

参考链接:https://learn.openshift.com

大卫分享:

魏新宇

"大卫分享"运营者、红帽资深解决方案架构师

专注开源云计算、容器及自动化运维在金融行业的推广

拥有红帽RHCE/RHCA、VMware VCP-DCV、VCP-DT、VCP-Network、VCP-Cloud、ITIL V3、Cobit5、C-STAR、AIX、HPUX等相关认证。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180210B0284B00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券