Quarkus ผสมผสาน MicroProfile และ Spring เข้าด้วยกันอย่างไร

สวัสดีทุกคน นี่คือโพสต์ที่สามของซีรีส์ Quarkus!

Quarkus ผสมผสาน MicroProfile และ Spring เข้าด้วยกันอย่างไร

เมื่อพัฒนา Java microservices มักเชื่อกันว่า คราสไมโครโปรไฟล์ и สปริงบูต เป็น API ที่แยกจากกันและเป็นอิสระ ตามค่าเริ่มต้น โปรแกรมเมอร์มักจะใช้ API ที่พวกเขาคุ้นเคย เนื่องจากการเรียนรู้เฟรมเวิร์กและส่วนประกอบรันไทม์ใหม่ใช้เวลานาน วันนี้เราจะพยายามทำให้การพัฒนายอดนิยมบางอย่างง่ายขึ้น MicroProfile API สำหรับนักพัฒนา Spring และแสดงวิธีใช้ Spring API และฟีเจอร์ใหม่ที่มีประโยชน์ไปพร้อมๆ กัน ควาร์คัส.

ในรายละเอียดเพิ่มเติมเล็กน้อย ก่อนอื่นเราจะดูขอบเขตและรายละเอียดว่า Quarkus รองรับ Spring API อย่างไรเพื่อแสดงให้นักพัฒนา Spring เห็นถึงวิธีใช้ MicroProfile API ในการทำงานในแต่ละวัน จากนั้น เราจะพูดถึง MicroProfile API ซึ่งมีประโยชน์สำหรับนักพัฒนา Spring เมื่อสร้างไมโครเซอร์วิส

ทำไมต้องควาร์ก? ประการแรก นี่คือการเขียนโค้ดแบบสด นั่นคือการโหลดการเปลี่ยนแปลงใดๆ ใน MicroProfile API, Spring API และ Java API อื่นๆ โดยอัตโนมัติ ซึ่งดำเนินการด้วยคำสั่งเดียว: mvn quarkus:dev ประการที่สอง กล่าวถึงใน ในตัวอย่างของเรา บริการ Person (ซึ่งคอมไพล์จาก Spring, MicroProfile และ JPA API เป็นไบนารี่โดยใช้อิมเมจ GraalVM ดั้งเดิม) เริ่มต้นในเวลาเพียง 0.055 วินาทีและใช้ RAM (RSS) ประมาณ 90 MB บนจุดสิ้นสุดแอปพลิเคชัน RESTful ยิ่งไปกว่านั้น การคอมไพล์นั้นดำเนินการด้วยคำสั่งเดียว: mvn package -Pnative

เราจะไม่ลงรายละเอียดเกี่ยวกับ MicroProfile นอกจากเพื่อช่วยให้นักพัฒนา Spring เข้าใจว่าพวกเขาสามารถใช้ Spring API กับ MicroProfile API ใน Quarkus ได้อย่างไร

คอนเทนเนอร์และ Kubernetes

เพื่อให้บทความนี้เข้าใจง่าย เราจะกล่าวถึงเฉพาะการสนับสนุนระดับสูงเท่านั้นที่นี่ Kubernetesเพราะสิ่งสำคัญคือต้องเข้าใจ Quarkus อยู่ในตำแหน่งที่เป็น Java Stack สำหรับ Kubernetes โดยได้รับการออกแบบมาเพื่อลดการใช้หน่วยความจำและเวลาเริ่มต้นของแอปพลิเคชันและบริการ Java ส่งผลให้เพิ่มความหนาแน่นบนโฮสต์และลดต้นทุนโดยรวม

ควาร์กก็เช่นกัน รองรับการสร้างอัตโนมัติ ทรัพยากรและข้อเสนอของ Kubernetes มัคคุเทศก์ สำหรับการปรับใช้บนแพลตฟอร์ม Kubernetes และ Red Hat OpenShift นอกจากนี้ Quarkus จะสร้างไฟล์ Dockerfile.jvm (แพ็คเกจ JVM) และ Dockerfile.native (แพ็คเกจไบนารีดั้งเดิม) โดยอัตโนมัติซึ่งจำเป็นในการสร้างคอนเทนเนอร์

สุดท้ายนี้ ด้วยการมุ่งเน้นไปที่ Kubernetes เป็นสภาพแวดล้อมการปรับใช้เป้าหมาย Quarkus จะไม่ใช้กรอบงาน Java ในกรณีที่มีการใช้งานฟังก์ชันที่คล้ายกันในระดับของแพลตฟอร์ม Kubernetes เอง ตารางที่ 1 จัดทำแผนที่ของการโต้ตอบการทำงานระหว่าง Kubernetes และเฟรมเวิร์ก Java ทั่วไปที่นักพัฒนา Spring ใช้

ตารางที่ 1. แผนผังการโต้ตอบการทำงานระหว่างเฟรมเวิร์ก Java และ Kubernetes

การทำงาน
รองเท้าบูทสปริงแบบดั้งเดิม
Kubernetes

การค้นพบบริการ
ยูเร
DNS

องค์ประกอบ
การกำหนดค่าสปริงคลาวด์
กำหนดค่าแผนที่/ความลับ

โหลดบาลานซ์
ริบบิ้น (ฝั่งไคลเอ็นต์)
บริการ ตัวควบคุมการจำลอง (ฝั่งเซิร์ฟเวอร์)

รวบรวมและรันโค้ดจากตัวอย่าง

ในบทความนี้เราอ้างถึง โครงการตัวอย่างโดยที่ Spring และ MicroProfile API และแม้แต่คลาส Java เดียวกันถูกนำมาใช้ร่วมกัน รหัสในตัวอย่างนี้สามารถคอมไพล์และรันได้จากบรรทัดคำสั่ง โปรดดูรายละเอียดที่ไฟล์ README.md

Spring Framework API

การฉีดพึ่งพา

Quarkus รองรับช่วงของ API บริบทและการพึ่งพาการฉีด (CDI) และ API ของ Spring Dependency Injection (Spring DI) หากคุณกำลังทำงานกับ MicroProfile Java EE และ Jakarta EEแสดงว่าคุณคุ้นเคยกับ CDI เป็นอย่างดีแล้ว ในทางกลับกัน นักพัฒนา Spring สามารถใช้ Quarkus Extension สำหรับ Spring DI API เพื่อให้เข้ากันได้กับ Spring DI ตัวอย่างของการใช้ Spring DI API ที่รองรับแสดงไว้ในตารางที่ 2

В โครงการจากตัวอย่างของเรา ใช้ทั้ง CDI และ Spring Dependency Injection สำหรับข้อมูลเพิ่มเติมและตัวอย่างในหัวข้อนี้ โปรดดูคู่มือ Quarkus ที่เรียกว่า สปริง DI ไกด์.

ตารางที่ 2. ตัวอย่างการใช้ Spring DI API ที่รองรับ

คุณสมบัติสปริง DI ที่รองรับ
ตัวอย่าง

คอนสตรัคอินเจ็คชั่น

public PersonSpringController(
   PersonSpringRepository personRepository,  // injected      
   PersonSpringMPService personService) {    // injected
      this.personRepository = personRepository;
      this.personService = personService;
}

การฉีดภาคสนาม
อัตโนมัติ
ความคุ้มค่า

@Autowired
@RestClient
SalutationRestClient salutationRestClient;

@Value("${fallbackSalutation}")
String fallbackSalutation;

ถั่ว
@ คอนเฟริม

@Configuration
public class AppConfiguration {
   @Bean(name = "capitalizeFunction")
   public StringFunction capitalizer() {
      return String::toUpperCase;
   }
}

ตัวแทน

@Component("noopFunction")
public class NoOpSingleStringFunction implements StringFunction {
   @Override
   public String apply(String s) {
      return s;
   }
}

Service

@Service
public class MessageProducer {
   @Value("${greeting.message}")
   String message;

   public String getPrefix() {
      return message;
   }
}

กรอบงานเว็บ

ผู้ใช้ MicroProfile จะชื่นชอบที่ Quarkus รองรับ JAX-RS, MicroProfile Rest Client, JSON-P และ JSON-B เป็นรูปแบบการเขียนโปรแกรมเว็บหลัก นักพัฒนา Spring จะพอใจกับการสนับสนุนล่าสุดของ Quarkus สำหรับ Spring Web API โดยเฉพาะอินเทอร์เฟซ REST เช่นเดียวกับ Spring DI เป้าหมายหลักของการสนับสนุน Spring Web API คือการทำให้นักพัฒนา Spring สามารถใช้ Spring Web API ร่วมกับ MicroProfile API ตัวอย่างวิธีใช้ Spring Web API ที่รองรับมีอยู่ในตารางที่ 3 และข้อมูลเพิ่มเติมและตัวอย่างในหัวข้อนี้สามารถพบได้ในบทช่วยสอน Quarkus ชื่อ คู่มือเว็บสปริง.

ตารางที่ 3. ตัวอย่างการใช้ Spring Web API ที่รองรับ

คุณสมบัติเว็บสปริงที่รองรับ
ตัวอย่าง

@RestController
@RequestMapping

@RestController
@RequestMapping("/person")
public class PersonSpringController {
   ...
   ...
   ...
}

@GetMapping
@โพสต์แมป
@PutMapping
@DeleteMapping
@PatchMapping
@RequestParam
@RequestHeader
@เมทริกซ์ตัวแปร
@PathVariable
@CookieValue
@RequestBody
@สถานะการตอบสนอง
@ExceptionHandler
@RestControllerAdvice (บางส่วน)

@GetMapping(path = "/greet/{id}",
   produces = "text/plain")
   public String greetPerson(
   @PathVariable(name = "id") long id) {
   ...
   ...
   ...
}

สปริงข้อมูล JPA

ผู้ใช้ MicroProfile จะประทับใจที่ Quarkus รองรับ JPA โดยใช้ Hibernate ORM นอกจากนี้ยังมีข่าวดีสำหรับนักพัฒนา Spring: Quarkus รองรับคำอธิบายประกอบและประเภท JPA ของ Spring Data ทั่วไป ตัวอย่างของการใช้ Spring Data JPA API ที่รองรับแสดงไว้ในตารางที่ 4
В โครงการจากตัวอย่างของเรา มีการใช้ Spring Data JPA API และมีข้อมูลเพิ่มเติมอยู่ในบทช่วยสอน Quarkus ที่เรียกว่า คู่มือ JPA ของ Spring Data.

ตารางที่ 4. ตัวอย่างการใช้ Spring Data JPA API ที่รองรับ

รองรับคุณสมบัติ Spring Data JPA
ตัวอย่าง

CrudRepository

public interface PersonRepository
         extends JpaRepository,
                 PersonFragment {
   ...
}

กรุ
JpaRepository
PagingAndSortingRepository

public class PersonRepository extends 

    Repository {

    Person save(Person entity);

    Optional findById(Person entity);
}

ชิ้นส่วนพื้นที่เก็บข้อมูล

public interface PersonRepository
         extends JpaRepository,
                 PersonFragment {
   ...
}

วิธีการสืบค้นที่ได้รับมา

public interface PersonRepository extends CrudRepository {

    List findByName(String name);
    
    Person findByNameBySsn(String ssn);
    
    Optional 
       findByNameBySsnIgnoreCase(String ssn);

    Boolean existsBookByYearOfBirthBetween(
            Integer start, Integer end);
}

แบบสอบถามที่ผู้ใช้กำหนด

public interface MovieRepository
         extends CrudRepository {

    Movie findFirstByOrderByDurationDesc();

    @Query("select m from Movie m where m.rating = ?1")
    Iterator findByRating(String rating);

    @Query("from Movie where title = ?1")
    Movie findByTitle(String title);
}

MicroProfile API

ความอดทนต่อความผิดพลาด

โครงสร้างความทนทานต่อข้อผิดพลาดมีความสำคัญมากในการป้องกันความล้มเหลวแบบเรียงซ้อนและการสร้างสถาปัตยกรรมไมโครเซอร์วิสที่เชื่อถือได้ นักพัฒนา Spring ใช้เซอร์กิตเบรกเกอร์เพื่อความทนทานต่อข้อผิดพลาดมาหลายปีแล้ว ฮิททริกซ์. อย่างไรก็ตาม Hystrix ไม่ได้รับการอัปเดตมาเป็นเวลานานแล้ว แต่ Fault Tolerance ของ MicroProfile กำลังพัฒนาอย่างแข็งขันและมีการใช้การผลิตเป็นเวลาหลายปี ดังนั้น เพื่อปรับปรุงความน่าเชื่อถือของบริการใน Quarkus ขอแนะนำให้ใช้ MicroProfile Fault Tolerance APIs ตัวอย่างที่ใช้ในตารางที่ 5 สำหรับข้อมูลเพิ่มเติมเกี่ยวกับสิ่งนี้ โปรดดูคู่มือ Quarkus คู่มือการยอมรับข้อผิดพลาด.

ตารางที่ 5. ตัวอย่างการใช้ MicroProfile Fault Tolerance API ที่รองรับ

คุณสมบัติความทนทานต่อข้อผิดพลาดของ MicroProfile
ลักษณะ
ตัวอย่าง

@อะซิงโครนัส

ดำเนินการตรรกะในเธรดแยกต่างหาก

@Asynchronous
@Retry
public Future<String> getSalutation() {
   ...
   return future;
}

@กั้นหัว

จำกัดจำนวนคำขอพร้อมกัน

@Bulkhead(5)
public void fiveConcurrent() {
   makeRemoteCall(); //...
}

@เบรกเกอร์

การจัดการความล้มเหลวอย่างชาญฉลาดและการกู้คืนจากความล้มเหลว

@CircuitBreaker(delay=500   // milliseconds
   failureRatio = .75,
   requestVolumeThreshold = 20,
   successThreshold = 5)
@Fallback(fallbackMethod = "fallback")
public String getSalutation() {
   makeRemoteCall(); //...
}

@รั้งท้าย

การเรียกตรรกะทางเลือกในกรณีที่เกิดความล้มเหลว

@Timeout(500) // milliseconds
@Fallback(fallbackMethod = "fallback")
public String getSalutation() {
   makeRemoteCall(); //...
}

public String fallback() {
   return "hello";
}

ลองอีกครั้ง

ลองอีกครั้งเมื่อคำขอล้มเหลว

@Retry(maxRetries=3)
public String getSalutation() {
   makeRemoteCall(); //...
}

การหยุดพักชั่วคราว

หมดเวลาการควบคุมความล้มเหลว

@Timeout(value = 500 )   // milliseconds
@Fallback(fallbackMethod = "fallback")
public String getSalutation() {
   makeRemoteCall(); //...
}

บริการตรวจสุขภาพ (Service Health)

แพลตฟอร์ม Kubernetes ตรวจสอบความสมบูรณ์ของคอนเทนเนอร์โดยใช้บริการพิเศษ เพื่อให้แพลตฟอร์มพื้นฐานสามารถตรวจสอบบริการได้ โดยทั่วไปนักพัฒนา Spring จะใช้ HealthIndicator และ Spring Boot Actuator แบบกำหนดเอง ใน Quarkus สามารถทำได้โดยใช้ MicroProfile Health ซึ่งตามค่าเริ่มต้นจะทำการตรวจสอบความสด แต่สามารถกำหนดค่าให้ตรวจสอบความสดและความพร้อมไปพร้อมกันได้ ตัวอย่างวิธีใช้ MicroProfile Health API ที่รองรับมีอยู่ในตารางที่ 6 และข้อมูลเพิ่มเติมอยู่ในคู่มือ Quarkus คู่มือสุขภาพ.

ตารางที่ 6: ตัวอย่างการใช้งาน MicroProfile Health API ที่รองรับ

คุณสมบัติสุขภาพ MicroProfile
ลักษณะ
ตัวอย่าง

@ความมีชีวิตชีวา

แพลตฟอร์มรีบูตแอปพลิเคชันคอนเทนเนอร์ที่ล้มเหลว
ปลายทาง:
โฮสต์:8080/สุขภาพ/สด

@Liveness
public class MyHC implements HealthCheck {
  public HealthCheckResponse call() {

   ...
   return HealthCheckResponse
     .named("myHCProbe")
     .status(ready ? true:false)
     .withData("mydata", data)
     .build();  
}

@ความพร้อม

แพลตฟอร์มจะไม่ส่งทราฟฟิกไปยังแอปพลิเคชันที่มีคอนเทนเนอร์หากยังไม่พร้อม
ปลายทาง:
โฮสต์:8080/สุขภาพ/พร้อม

@Readiness
public class MyHC implements HealthCheck {
  public HealthCheckResponse call() {

   ...
   return HealthCheckResponse
     .named("myHCProbe")
     .status(live ? true:false)
     .withData("mydata", data)
     .build();  
}

เมตริก

แอปพลิเคชันมีหน่วยวัดสำหรับวัตถุประสงค์ในการปฏิบัติงาน (เพื่อติดตาม SLA ประสิทธิภาพ) หรือวัตถุประสงค์ที่ไม่ใช่การปฏิบัติงาน (SLA ธุรกิจ) นักพัฒนา Spring จัดเตรียมหน่วยวัดโดยใช้ Spring Boot Actuator และ Micrometer ในทางกลับกัน Quarkus ใช้ MicroProfile Metrics เพื่อจัดเตรียมตัวชี้วัดพื้นฐาน (JVM และระบบปฏิบัติการ) ตัวชี้วัดผู้จำหน่าย (Quarkus) และตัวชี้วัดการใช้งาน MicroProfile Metrics กำหนดให้การใช้งานรองรับรูปแบบเอาต์พุต JSON และ OpenMetrics (Prometheus) ตัวอย่างของการใช้ MicroProfile Metrics API แสดงไว้ในตารางที่ 7

В โครงการจากตัวอย่างของเรา MicroProfile Metrics ใช้เพื่อจัดเตรียมการวัดการใช้งาน สำหรับข้อมูลเพิ่มเติม โปรดดูคู่มือ Quarkus คู่มือเมตริก.

ตารางที่ 7. ตัวอย่างการใช้ MicroProfile Metrics API

คุณสมบัติตัวชี้วัด MicroProfile
ลักษณะ
ตัวอย่าง

@นับแล้ว

หมายถึงตัวนับที่นับจำนวนครั้งที่วัตถุที่มีคำอธิบายประกอบถูกเรียก

@Counted(name = "fallbackCounter", 
  displayName = "Fallback Counter", 
  description = "Fallback Counter")
public String salutationFallback() {
   return fallbackSalutation;
}

@ConcurrentGauge

หมายถึงเกจที่นับจำนวนการเรียกพร้อมกันไปยังอ็อบเจ็กต์ที่มีคำอธิบายประกอบ

@ConcurrentGuage(
  name = "fallbackConcurrentGauge", 
  displayName="Fallback Concurrent", 
  description="Fallback Concurrent")
public String salutationFallback() {
   return fallbackSalutation;
}

@วัด

หมายถึงเซ็นเซอร์เกจที่ใช้วัดค่าของวัตถุที่มีคำอธิบายประกอบ

@Metered(name = "FallbackGauge",
   displayName="Fallback Gauge",
   description="Fallback frequency")
public String salutationFallback() {
   return fallbackSalutation;
}

@วัดแล้ว

หมายถึงเซ็นเซอร์มิเตอร์ที่ตรวจสอบความถี่การโทรของวัตถุที่มีคำอธิบายประกอบ

@Metered(name = "MeteredFallback",
   displayName="Metered Fallback",
   description="Fallback frequency")
public String salutationFallback() {
   return fallbackSalutation;
}

เมตริก

คำอธิบายประกอบที่มีข้อมูลเกี่ยวกับข้อมูลเมตาเมื่อได้รับคำขอให้ป้อนหรือสร้างเมตริก

@Metric
@Metered(name = "MeteredFallback",
   displayName="Metered Fallback",
   description="Fallback frequency")
public String salutationFallback() {
   return fallbackSalutation;
}

หมดเวลา

ระบุตัวจับเวลาที่ติดตามระยะเวลาของวัตถุที่มีคำอธิบายประกอบ

@Timed(name = "TimedFallback",
   displayName="Timed Fallback",
   description="Fallback delay")
public String salutationFallback() {
   return fallbackSalutation;
}

จุดสิ้นสุดของเมตริก

ตัวชี้วัดการใช้งาน localhost:8080/เมตริก/แอปพลิเคชัน
ตัวชี้วัดพื้นฐาน localhost:8080/เมตริก/ฐาน
ตัวชี้วัดผู้ขาย localhost:8080/เมตริก/ผู้ขาย
เมตริกทั้งหมด localhost:8080/เมตริก

ไคลเอนต์ส่วนที่เหลือ MicroProfile

ไมโครเซอร์วิสมักจัดเตรียมตำแหน่งข้อมูล RESTful ซึ่งต้องใช้ API ไคลเอ็นต์ที่เกี่ยวข้องในการทำงานด้วย หากต้องการใช้ตำแหน่งข้อมูล RESTful โดยทั่วไปนักพัฒนา Spring จะใช้ RestTemplate Quarkus นำเสนอ MicroProfile Rest Client API เพื่อแก้ไขปัญหานี้ ตัวอย่างการใช้งานแสดงไว้ในตารางที่ 8

В โครงการจากตัวอย่างของเรา การใช้จุดสิ้นสุด RESTful ทำได้โดยใช้ MicroProfile Rest Client ข้อมูลเพิ่มเติมและตัวอย่างเกี่ยวกับหัวข้อนี้สามารถพบได้ในคู่มือ Quarkus คู่มือลูกค้าส่วนที่เหลือ.

ตารางที่ 8. ตัวอย่างการใช้ MicroProfile Rest Client API

คุณสมบัติไคลเอนต์ MicroProfile Rest
ลักษณะ
ตัวอย่าง

@RegisterRestClient

ลงทะเบียนอินเทอร์เฟซ Java ที่พิมพ์เป็นไคลเอ็นต์ REST

@RegisterRestClient
@Path("/")
public interface MyRestClient {
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getSalutation();
}

@RestClient

ทำเครื่องหมายการใช้งานอินสแตนซ์ของอินเทอร์เฟซไคลเอนต์ REST ที่พิมพ์

@Autowired // or @Inject
@RestClient
MyRestClient restClient;

การภาวนา

เรียกจุดสิ้นสุด REST

System.out.println(
   restClient.getSalutation());

mp-rest/url.mp

ระบุจุดสิ้นสุด REST

application.properties:
org.example.MyRestClient/mp-rest/url=
   http://localhost:8081/myendpoint

ผลของการ

ในบล็อกนี้ ซึ่งมุ่งเป้าไปที่นักพัฒนา Spring เป็นหลัก เราได้ดูวิธีใช้ Spring API กับ MicroProfile API ใน Quarkus เพื่อพัฒนาไมโครเซอร์วิส Java แล้วคอมไพล์เป็นโค้ดไบนารีดั้งเดิมที่ช่วยประหยัด RAM หลายร้อยเมกะไบต์และเปิดตัวใน เรื่องของมิลลิวินาที

ตามที่คุณเข้าใจแล้ว ข้อมูลเพิ่มเติมเกี่ยวกับการรองรับ Spring และ MicroProfile API รวมถึงข้อมูลที่เป็นประโยชน์อื่นๆ อีกมากมายสามารถพบได้ใน คู่มือควาร์ก.

ที่มา: will.com

เพิ่มความคิดเห็น