在本文中,您将学习如何运行Spring Boot微服务,这些服务在Knative上相互通信。我还向您展示了如何使用GraalVM准备Spring Boot应用程序的本机映像。然后我们将使用Skaffold和jibmaven插件在Kubernetes上运行它。
在Knative上,您可以运行任何类型的应用程序,而不仅仅是函数。在本文中,当我编写“微服务”时,实际上,我考虑的是服务对服务的通信。
作为本文中的微服务示例,我使用了两个应用程序callme service和caller service。它们都公开了一个端点,该端点打印应用程序pod的名称。调用方服务应用程序还调用callme服务应用程序公开的端点。
在Kubernetes上,这两个应用程序都将作为Knative服务部署在多个版本中。我们还将使用Knative路由在这些修订版中分配流量。下图说明了我们的示例系统的体系结构。
准备Spring Boot微服务
我们有两个简单的Spring Boot应用程序,它们公开一个REST端点、运行状况检查,并运行内存中的H2数据库。我们使用Hibernate和Lombok。因此,我们需要在Maven pom.xml 中包含以下依赖项列表。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
每次调用ping端点时,它都会创建一个事件并将其存储在H2数据库中。REST端点返回Kubernetes中pod和命名空间的名称以及事件的id。该方法在我们对集群的手动测试中很有用。
@RestController
@RequestMapping("/callme")
public class CallmeController {
@Value("${spring.application.name}")
private String appName;
@Value("${POD_NAME}")
private String podName;
@Value("${POD_NAMESPACE}")
private String podNamespace;
@Autowired
private CallmeRepository repository;
@GetMapping("/ping")
public String ping() {
Callme c = repository.save(new Callme(new Date(), podName));
return appName + "(id=" + c.getId() + "): " + podName + " in " + podNamespace;
}
}
这是我们的模型课—— Callme 。调用者服务应用程序中的模型类非常类似。
@Entity
@Getter
@Setter
@NoArgsConstructor
@RequiredArgsConstructor
public class Callme {
@Id
@GeneratedValue
private Integer id;
@Temporal(TemporalType.TIMESTAMP)
@NonNull
private Date addDate;
@NonNull
private String podName;
}
另外,让我们看看 CallerController 中 ping 方法的第一个版本。稍后我们将在讨论通信和跟踪时对其进行修改。现在,理解这个方法还调用callme服务公开的ping方法并返回整个响应是很重要的。
@GetMapping("/ping")
public String ping() {
Caller c = repository.save(new Caller(new Date(