日期:
来源:ImportNew收集编辑:
(给ImportNew加星标,提高Java技能)
在本文中,您将了解在 Kubernetes 上运行 Java 应用程序的最佳实践。大多数这些建议也适用于其他语言。但是,我正在考虑 Java 特性范围内的所有规则,并且还展示了可用于基于 JVM 的应用程序的解决方案和工具。当使用最流行的 Java 框架(如 Spring Boot 或 Quarkus)时,这些 Kubernetes 建议中的一些是设计强制的。我将向您展示如何有效地利用它们来简化开发人员的生活。
1、不要将 Limit 设置得太低
2、首先考虑内存使用
3、适当的 liveness 和 readiness 探针
3.1 介绍
3.2 配置详情
management:endpoint:health:probes:enabled: true
spring:application:name: sample-spring-boot-on-kubernetesdata:mongodb:host: ${MONGO_URL}port: 27017username: ${MONGO_USERNAME}password: ${MONGO_PASSWORD}database: ${MONGO_DATABASE}authentication-database: adminmanagement:endpoint.health:show-details: alwaysgroup:readiness:include: mongo # (1)additional-path: server:/readiness # (2)probes:enabled: trueserver:port: 8081
spring:application:name: sample-spring-kotlin-microservicedatasource:url: jdbc:postgresql://postgres:5432/postgresusername: postgrespassword: postgres123hikari:connection-timeout: 2000initialization-fail-timeout: 0jpa:database-platform: org.hibernate.dialect.PostgreSQLDialectrabbitmq:host: rabbitmqport: 5672connection-timeout: 2000
4、选择合适的 JDK
apiVersion: skaffold/v2beta22kind: Configmetadata:name: sample-spring-boot-on-kubernetesbuild:artifacts:- image: piomin/sample-spring-boot-on-kubernetesbuildpacks:builder: paketobuildpacks/builder:basebuildpacks:- paketo-buildpacks/amazon-corretto- paketo-buildpacks/javaenv:- BP_JVM_VERSION=17
5、考虑迁移到原生编译
<profiles><profile><id>native</id><activation><property><name>native</name></property></activation><properties><skipITs>false</skipITs><quarkus.package.type>native</quarkus.package.type></properties></profile></profiles>
$ mvn clean package -Pnative
<plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><executions><execution><goals><goal>build-info</goal><goal>build-image</goal></goals></execution></executions><configuration><image><builder>paketobuildpacks/builder:tiny</builder><env><BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE><BP_NATIVE_IMAGE_BUILD_ARGUMENTS>--allow-incomplete-classpath</BP_NATIVE_IMAGE_BUILD_ARGUMENTS></env></image></configuration></plugin>
6、正确配置日志记录
<dependency><groupId>net.logstash.logback</groupId><artifactId>logstash-logback-encoder</artifactId><version>7.2</version></dependency>
<configuration><appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender"><encoder class="net.logstash.logback.encoder.LogstashEncoder"/></appender><logger name="jsonLogger" additivity="false" level="DEBUG"><appender-ref ref="consoleAppender"/></logger><root level="INFO"><appender-ref ref="consoleAppender"/></root></configuration>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>
<?xml version="1.0" encoding="UTF-8"?><configuration><springProperty name="destination" source="app.amqp.url" /><appender name="AMQP"class="org.springframework.amqp.rabbit.logback.AmqpAppender"><layout><pattern>{"time": "%date{ISO8601}","thread": "%thread","level": "%level","class": "%logger{36}","message": "%message"}</pattern></layout><addresses>${destination}</addresses><applicationId>api-service</applicationId><routingKeyPattern>logs</routingKeyPattern><declareExchange>true</declareExchange><exchangeName>ex_logstash</exchangeName></appender><root level="INFO"><appender-ref ref="AMQP" /></root></configuration>
7、创建集成测试
<dependency><groupId>io.quarkus</groupId><artifactId>quarkus-container-image-jib</artifactId></dependency>
@QuarkusIntegrationTestpublic class EmployeeControllerIT {@TestHTTPEndpoint(EmployeeController.class)@TestHTTPResourceURL url;@Testvoid add() {EmployeeService service = RestClientBuilder.newBuilder().baseUrl(url).build(EmployeeService.class);Employee employee = new Employee(1L, 1L, "Josh Stevens",23, "Developer");employee = service.add(employee);assertNotNull(employee.getId());}@Testpublic void findAll() {EmployeeService service = RestClientBuilder.newBuilder().baseUrl(url).build(EmployeeService.class);Set<Employee> employees = service.findAll();assertTrue(employees.size() >= 3);}@Testpublic void findById() {EmployeeService service = RestClientBuilder.newBuilder().baseUrl(url).build(EmployeeService.class);Employee employee = service.findById(1L);assertNotNull(employee.getId());}}
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)@Testcontainers@TestMethodOrder(MethodOrderer.OrderAnnotation.class)public class PersonControllerTests {@AutowiredTestRestTemplate restTemplate;@Containerstatic PostgreSQLContainer<?> postgres =new PostgreSQLContainer<>("postgres:15.1").withExposedPorts(5432);@DynamicPropertySourcestatic void registerMySQLProperties(DynamicPropertyRegistry registry) {registry.add("spring.datasource.url", postgres::getJdbcUrl);registry.add("spring.datasource.username", postgres::getUsername);registry.add("spring.datasource.password", postgres::getPassword);}@Test@Order(1)void add() {Person person = Instancio.of(Person.class).ignore(Select.field("id")).create();person = restTemplate.postForObject("/persons", person, Person.class);Assertions.assertNotNull(person);Assertions.assertNotNull(person.getId());}@Test@Order(2)void updateAndGet() {final Integer id = 1;Person person = Instancio.of(Person.class).set(Select.field("id"), id).create();restTemplate.put("/persons", person);Person updated = restTemplate.getForObject("/persons/{id}", Person.class, id);Assertions.assertNotNull(updated);Assertions.assertNotNull(updated.getId());Assertions.assertEquals(id, updated.getId());}}
8、最后的想法
转自:云云众生s / 岱军,
英文链接:piotrminkowski.com/2023/02/13/best-practices-for-java-apps-on-kubernetes/
- EOF -
看完本文有收获?请转发分享给更多人
关注「ImportNew」,提升Java技能
点赞和在看就是最大的支持❤️