1、创建项目
目录结构:
learnspringwfw
├─docker
│ └─common
│ └─docker-compose.yml
└─licensing-service
│ └─src
│ ├ ── ─main
│ │ │ ├─docker
│ │ │ │ ├─Docker
│ │ │ │ └─run.sh
│ │ │ ├─java
│ │ │ │ └─com
│ │ │ │ └─example
│ │ │ │ └─licenses
│ │ │ │ ├─controllers
│ │ │ │ │ └─LicenseServiceController
│ │ │ │ ├─model
│ │ │ │ │ └─License
│ │ │ │ │ └─Organization
│ │ │ │ └─services
│ │ │ │ └─LicenseService
│ │ │ │ └─OrganizationService
│ │ │ └─resources
│ │ │ └─application.properties
│ │ └─test
│ │ └─java
│ │ └─com
│ │ └─example
│ │ └─licenses
│ └─ pom.xml
└─pom.xml
最外层的 pom.xml:
<?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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>learnspringwfw</artifactId>
<packaging>pom</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>learnspringwfw-parent-pom</name>
<description>Parent Pom for the learnspringwfw project</description>
<modules>
<module>licensing-service</module>
</modules>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<baseImage>java</baseImage>
<imageName>example</imageName>
</configuration>
</plugin>
</plugins>
</build>
</project>
licensing-service模块的pom.xml:
<?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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>licensing-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>licensing-service</name>
<description>Demo project for Licensing Service</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>com.example.licenses.LicensingServiceApplication</start-class>
<docker.image.name>learnspringwfw/my-licensing-service</docker.image.name>
<docker.image.tag>learndemo2</docker.image.tag>
</properties>
<!-- 依赖 -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- We use the Resources plugin to filer Dockerfile and run.sh, it inserts actual JAR filename -->
<!-- The final Dockerfile will be created in target/dockerfile/Dockerfile -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<!-- here the phase you need -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/dockerfile</outputDirectory>
<resources>
<resource>
<directory>src/main/docker</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<imageName>${docker.image.name}:${docker.image.tag}</imageName>
<dockerDirectory>${basedir}/target/dockerfile</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
LicensingServiceApplication :
package com.example.licenses;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class LicensingServiceApplication {
public static void main(String[] args) {
SpringApplication.run(LicensingServiceApplication.class, args);
}
}
LicenseServiceController:
package com.example.licenses.controllers;
import com.example.licenses.model.License;
import com.example.licenses.services.LicenseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping(value="v1/organizations/{organizationId}/licenses")
public class LicenseServiceController {
@Autowired
private LicenseService licenseService;
@RequestMapping(value="/{licenseId}",method = RequestMethod.GET)
public License getLicenses( @PathVariable("organizationId") String organizationId,
@PathVariable("licenseId") String licenseId) {
//return licenseService.getLicense(licenseId);
return new License()
.withId(licenseId)
.withOrganizationId(organizationId)
.withProductName("Teleco")
.withLicenseType("Seat");
}
@RequestMapping(value="{licenseId}",method = RequestMethod.PUT)
public String updateLicenses( @PathVariable("licenseId") String licenseId) {
return String.format("This is the put");
}
@RequestMapping(value="{licenseId}",method = RequestMethod.POST)
public String saveLicenses( @PathVariable("licenseId") String licenseId) {
return String.format("This is the post");
}
@RequestMapping(value="{licenseId}",method = RequestMethod.DELETE)
@ResponseStatus(HttpStatus.NO_CONTENT)
public String deleteLicenses( @PathVariable("licenseId") String licenseId) {
return String.format("This is the Delete");
}
}
LicenseServiceController 这个类将公开4个 HTTP 端点。
@RestController注解与传统的 Spring的 @Controller 注解不同,@RestController 注解并不需要从控制器类返回 ResponseBody类。
这一切都由@RestController 注解进行处理,它包含了@ResponseBody 注解。
License:
package com.example.licenses.model;
public class License{
private String id;
private String organizationId;
private String productName;
private String licenseType;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getOrganizationId() {
return organizationId;
}
public void setOrganizationId(String organizationId) {
this.organizationId = organizationId;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getLicenseType() {
return licenseType;
}
public void setLicenseType(String licenseType) {
this.licenseType = licenseType;
}
public License withId(String id){
this.setId( id );
return this;
}
public License withOrganizationId(String organizationId){
this.setOrganizationId(organizationId);
return this;
}
public License withProductName(String productName){
this.setProductName(productName);
return this;
}
public License withLicenseType(String licenseType){
this.setLicenseType(licenseType);
return this;
}
}
Organization :
package com.example.licenses.model;
public class Organization {
String id;
String name;
String contactName;
String contactEmail;
String contactPhone;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContactName() {
return contactName;
}
public void setContactName(String contactName) {
this.contactName = contactName;
}
public String getContactEmail() {
return contactEmail;
}
public void setContactEmail(String contactEmail) {
this.contactEmail = contactEmail;
}
public String getContactPhone() {
return contactPhone;
}
public void setContactPhone(String contactPhone) {
this.contactPhone = contactPhone;
}
}
LicenseService :
package com.example.licenses.services;
import com.example.licenses.model.License;
import org.springframework.stereotype.Service;
import java.util.UUID;
@Service
public class LicenseService {
public License getLicense(String licenseId){
return new License()
.withId(licenseId)
.withOrganizationId( UUID.randomUUID().toString() )
.withProductName("Test Product Name")
.withLicenseType("PerSeat");
}
public void saveLicense(License license){
}
public void updateLicense(License license){
}
public void deleteLicense(License license){
}
}
OrganizationService :
package com.example.licenses.services;
import org.springframework.stereotype.Service;
@Service
public class OrganizationService {
}
docker-compose.yml:
version: '3'
services:
licensingservice:
image: learnspringwfw/my-licensing-service:learndemo2
ports:
- "8080:8080"
Dockerfile:
扫描二维码关注公众号,回复:
12813397 查看本文章
FROM openjdk:8-jdk-alpine
RUN apk update && apk upgrade && apk add netcat-openbsd
RUN mkdir -p /usr/local/licensingservice
ADD @[email protected] /usr/local/licensingservice/
ADD run.sh run.sh
RUN chmod +x run.sh
CMD ./run.sh
run.sh:
#!/bin/sh
echo "********************************************************"
echo "Starting License Server"
echo "********************************************************"
java -jar /usr/local/licensingservice/@[email protected]
1)单个运行:
①在模块根目录下运行Maven命令:
mvn spring-boot:run
②在postman或者curl或浏览器输入地址:
http://localhost:8080/v1/organizations/abcd123/licenses/qweqwe123123
返回响应:
{
"id": "qweqwe123123",
"organizationId": "abcd123",
"productName": "Teleco",
"licenseType": "Seat"
}
2)通过docker运行:
①在根目录执行以下命令来启动Docker容器:
docker-compose -f docker/common/docker-compose.yml up
运行上面这个docker-compose命令,会启动docker-compose.yml文件中定义的所有服务。每个服务将打印标准输出到控制台。
2、devops 构建原则
步骤 | 说明 | 说明 |
---|---|---|
服务装配 | 打包和部署微服务 | 源代码与其运行时引擎一起被编译和打包。如:mvn clean package && java Cjar target/licensing-service-0.1-SNAPSHOT.jar |
服务引导 | 管理微服务的配置 | 发生在微服务首次启动并需要加载其应用程序配置信息的时候 |
服务注册/发现 | 客户端如何与微服务通信 | 从微服务消费者的角度来看,微服务应该是位置透明的。微服务实例需要向第三方代理注册,此注册过程称为服务发现包括2点:1.服务实例的物理 IP 地址或域名地址2.以及应用程序可以用来查找服务的逻辑名称 。然后,服务客户端与发现代理进行通信以查找服务的位置。 |
服务监控 | 微服务的健康状况 | 服务发现代理监视其注册的每个服务实例的健康状况,并从其路由表中移除有问题的服务实例,以确保客户端不会访问已经发生故障的服务实例。在SpringBoot中,通过公开一个端点,如Spring Actuator 提供了开箱即用的端点。在Maven构建文件中,包含以下依赖项:Spring Actuator。然后访问/health。 |