JavaRush /จาวาบล็อก /Random-TH /คำแนะนำเกี่ยวกับ Java Microservices ส่วนที่ 3: คำถามทั่วไ...

คำแนะนำเกี่ยวกับ Java Microservices ส่วนที่ 3: คำถามทั่วไป

เผยแพร่ในกลุ่ม
การแปลและการปรับJava Microservices: A Practical Guide ส่วนก่อนหน้าของคำแนะนำ: มาดูปัญหาโดยธรรมชาติของไมโครเซอร์วิสใน Java โดยเริ่มจากสิ่งที่เป็นนามธรรมและลงท้ายด้วยไลบรารีที่เป็นรูปธรรม คำแนะนำเกี่ยวกับ Java Microservices  ส่วนที่ 3: คำถามทั่วไป - 1

จะทำให้ Java microservice มีความยืดหยุ่นได้อย่างไร

โปรดจำไว้ว่าเมื่อคุณสร้างไมโครเซอร์วิส คุณจะต้องแลกเปลี่ยนการเรียกเมธอด JVM สำหรับการเรียก HTTP แบบซิงโครนัสหรือการส่งข้อความแบบอะซิงโครนัส แม้ว่าการเรียกเมธอดส่วนใหญ่จะรับประกันว่าจะเสร็จสมบูรณ์ (ยกเว้นการปิดระบบ JVM โดยไม่คาดคิด) การเรียกผ่านเครือข่ายก็ไม่น่าเชื่อถือตามค่าเริ่มต้น อาจใช้งานได้ แต่อาจไม่ทำงานด้วยเหตุผลหลายประการ เช่น เครือข่ายโอเวอร์โหลด มีการนำกฎไฟร์วอลล์ใหม่ไปใช้ และอื่นๆ หากต้องการดูว่าสิ่งนี้สร้างความแตกต่างได้อย่างไร มาดูตัวอย่าง BillingService กัน

รูปแบบความยืดหยุ่น HTTP/REST

สมมติว่าลูกค้าสามารถซื้อ eBook บนเว็บไซต์ของบริษัทของคุณได้ ในการดำเนินการนี้ คุณเพิ่งใช้ไมโครเซอร์วิสการเรียกเก็บเงินที่สามารถโทรหาร้านค้าออนไลน์ของคุณเพื่อสร้างใบแจ้งหนี้ PDF จริงได้ สำหรับตอนนี้ เราจะทำการเรียกนี้พร้อมกันผ่าน HTTP (แม้ว่าจะเหมาะสมกว่าที่จะเรียกใช้บริการนี้แบบอะซิงโครนัส เนื่องจากการสร้าง PDF ไม่จำเป็นต้องเกิดขึ้นทันทีจากมุมมองของผู้ใช้ เราจะใช้ตัวอย่างเดียวกันในครั้งต่อไป และดูความแตกต่าง)
@Service
class BillingService {

    @Autowired
    private HttpClient client;

     public void bill(User user, Plan plan) {
        Invoice invoice = createInvoice(user, plan);
        httpClient.send(invoiceRequest(user.getEmail(), invoice), responseHandler());
        // ...
    }
}
โดยสรุป นี่คือผลลัพธ์ที่เป็นไปได้สามประการของการเรียก HTTP นี้
  • ตกลง: โทรสำเร็จ สร้างบัญชีสำเร็จแล้ว
  • ล่าช้า: การโทรผ่านไปแล้ว แต่ใช้เวลานานเกินไปในการโทรให้เสร็จสิ้น
  • ข้อผิดพลาด. การโทรล้มเหลว คุณอาจส่งคำขอที่เข้ากันไม่ได้ หรือระบบอาจไม่ทำงาน
โปรแกรมใดๆ ก็ตามถูกคาดหวังให้จัดการกับสถานการณ์ข้อผิดพลาด ไม่ใช่แค่กรณีที่ประสบความสำเร็จเท่านั้น เช่นเดียวกับไมโครเซอร์วิส แม้ว่าคุณจะต้องใช้ความพยายามเป็นพิเศษเพื่อให้แน่ใจว่า API เวอร์ชันที่ใช้งานทั้งหมดจะเข้ากันได้ เมื่อคุณเริ่มใช้งานและเผยแพร่ไมโครเซอร์วิสแต่ละรายการ คำแนะนำเกี่ยวกับ Java Microservices  ส่วนที่ 3: คำถามทั่วไป - 2กรณีที่น่าสนใจที่ต้องพิจารณาคือกรณีความล่าช้า ตัวอย่างเช่น ฮาร์ดไดรฟ์ไมโครเซอร์วิสของผู้ตอบกลับเต็ม และแทนที่จะใช้เวลา 50 มิลลิวินาที กลับใช้เวลา 10 วินาทีในการตอบสนอง จะน่าสนใจยิ่งขึ้นไปอีกเมื่อคุณประสบกับภาระงานบางอย่างจนการไม่ตอบสนองของ BillingService ของคุณเริ่มกระจายผ่านระบบของคุณ เพื่อเป็นตัวอย่าง ลองจินตนาการถึงห้องครัวที่ค่อยๆ เริ่มสร้าง "กลุ่ม" ของพนักงานเสิร์ฟในร้านอาหารทั้งหมด เห็นได้ชัดว่าส่วนนี้ไม่สามารถให้ภาพรวมโดยละเอียดของหัวข้อความยืดหยุ่นของไมโครเซอร์วิสได้ แต่เป็นส่วนเตือนให้นักพัฒนาทราบว่าจริงๆ แล้วนี่คือสิ่งที่จำเป็นต้องได้รับการแก้ไขและไม่ควรเพิกเฉยก่อนการเปิดตัวครั้งแรกของคุณ (ซึ่งจากประสบการณ์แล้ว เกิดขึ้นบ่อยกว่านั้น) ไม่ใช่) ดังต่อไปนี้) ไลบรารียอดนิยมที่ช่วยให้คุณคิดถึงเวลาแฝงและความทนทานต่อข้อผิดพลาดคือ Hystrix ของ Netflix ใช้เอกสารประกอบเพื่อเจาะลึกหัวข้อนี้

รูปแบบความยืดหยุ่นในการรับส่งข้อความ

มาดูการสื่อสารแบบอะซิงโครนัสให้ละเอียดยิ่งขึ้น โปรแกรม BillingService ของเราอาจมีหน้าตาแบบนี้ โดยสมมติว่าเราใช้ Spring และ RabbitMQ สำหรับการส่งข้อความ ในการสร้างบัญชี ตอนนี้เราได้ส่งข้อความไปยังนายหน้าข้อความ RabbitMQ ของเรา ซึ่งมีผู้ปฏิบัติงานหลายคนรอข้อความใหม่ ผู้ปฏิบัติงานเหล่านี้สร้างใบแจ้งหนี้ PDF และส่งไปยังผู้ใช้ที่เหมาะสม
@Service
class BillingService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

     public void bill(User user, Plan plan) {
        Invoice invoice = createInvoice(user, plan);
        // преобразует счет, например, в json и использует его How тело messages
        rabbitTemplate.convertAndSend(exchange, routingkey, invoice);
        // ...
    }
}
ข้อผิดพลาดที่อาจเกิดขึ้นดูแตกต่างออกไปเล็กน้อยในขณะนี้ เนื่องจากคุณจะไม่ได้รับการตอบสนองตกลงหรือข้อผิดพลาดในทันทีเหมือนกับที่คุณทำกับการเชื่อมต่อ HTTP แบบซิงโครนัสอีกต่อไป แต่เราอาจมีสถานการณ์ที่เป็นไปได้สามสถานการณ์ที่อาจผิดพลาด ซึ่งอาจก่อให้เกิดคำถามต่อไปนี้:
  1. พนักงานส่งและใช้ข้อความของฉันหรือไม่ หรือมันหายไป? (ผู้ใช้ไม่ได้รับใบแจ้งหนี้)
  2. ข้อความของฉันถูกส่งเพียงครั้งเดียวหรือไม่? หรือจัดส่งมากกว่าหนึ่งครั้งและดำเนินการเพียงครั้งเดียว? (ผู้ใช้จะได้รับใบแจ้งหนี้หลายใบ)
  3. การกำหนดค่า: จาก "ฉันใช้คีย์/ชื่อเส้นทางที่ถูกต้องสำหรับการแลกเปลี่ยน" เป็น "ตัวรับส่งข้อความของฉันได้รับการกำหนดค่าและบำรุงรักษาอย่างถูกต้องหรือคิวเต็มหรือไม่" (ผู้ใช้ไม่ได้รับใบแจ้งหนี้)
คำอธิบายโดยละเอียดของรูปแบบความสามารถในการฟื้นตัวของไมโครเซอร์วิสแบบอะซิงโครนัสแต่ละรายการอยู่นอกเหนือขอบเขตของคู่มือนี้ แต่มีป้ายบอกทางถูก นอกจากนี้พวกเขาจะต้องพึ่งพาเทคโนโลยีการส่งข้อความ ตัวอย่าง:
  • หากคุณกำลังใช้งาน JMS เช่น ActiveMQ คุณสามารถแลกเปลี่ยนความเร็วเพื่อรับประกันคอมมิตแบบสองเฟส (XA)
  • หากคุณใช้ RabbitMQ โปรดอ่านบทช่วยสอนนี้ก่อน จากนั้นจึงคิดอย่างรอบคอบเกี่ยวกับการยืนยัน การยอมรับข้อผิดพลาด และความน่าเชื่อถือของข้อความโดยทั่วไป
  • บางทีอาจมีบางคนมีความเชี่ยวชาญในการกำหนดค่าเซิร์ฟเวอร์ Active หรือ RabbitMQ โดยเฉพาะอย่างยิ่งเมื่อใช้ร่วมกับการทำคลัสเตอร์และ Docker (ใครก็ได้ ;))

เฟรมเวิร์กใดจะเป็นทางออกที่ดีที่สุดสำหรับไมโครเซอร์วิส Java

ในอีกด้านหนึ่งคุณสามารถติดตั้งตัวเลือกยอดนิยมเช่นSpring Boot . ทำให้การสร้างไฟล์ .jar เป็นเรื่องง่ายมาก มาพร้อมกับเว็บเซิร์ฟเวอร์ในตัว เช่น Tomcat หรือ Jetty และสามารถทำงานได้อย่างรวดเร็วและทุกที่ เหมาะสำหรับการสร้างแอปพลิเคชันไมโครเซอร์วิส เมื่อเร็ว ๆ นี้ เฟรมเวิร์กไมโครเซอร์วิสพิเศษคู่หนึ่งKubernetesหรือGraalVMปรากฏขึ้น โดยได้รับแรงบันดาลใจบางส่วนจากการเขียนโปรแกรมแบบโต้ตอบ นี่คือคู่แข่งที่น่าสนใจบางส่วน: Quarkus , Micronaut , Vert.x , Helidon . ท้ายที่สุด คุณจะต้องเลือกเอง แต่เราสามารถให้คำแนะนำสองสามข้อที่อาจไม่ได้มาตรฐานอย่างสมบูรณ์ ยกเว้น Spring Boot เฟรมเวิร์กไมโครเซอร์วิสทั้งหมดมักจะวางตลาดอย่างรวดเร็วอย่างไม่น่าเชื่อ โดยเริ่มต้นแทบจะในทันที , พื้นที่หน่วยความจำเหลือน้อย และความสามารถในการขยายขนาดจนถึงระดับอนันต์ สื่อการตลาดมักมีกราฟิกที่น่าประทับใจซึ่งอวดแพลตฟอร์มที่อยู่ถัดจาก Spring Boot ยักษ์ใหญ่หรือต่อกัน ตามทฤษฎีแล้ว สิ่งนี้จะช่วยประหยัดความกังวลของนักพัฒนาที่สนับสนุนโปรเจ็กต์รุ่นเก่า ซึ่งบางครั้งอาจใช้เวลาโหลดหลายนาที หรือนักพัฒนาที่ทำงานบนคลาวด์ที่ต้องการเริ่ม/หยุดคอนเทนเนอร์ขนาดเล็กให้ได้มากที่สุดตามที่ต้องการภายใน 50 มิลลิวินาที คำแนะนำเกี่ยวกับ Java Microservices  ส่วนที่ 3: คำถามทั่วไป - 3อย่างไรก็ตาม ปัญหาคือเวลาเริ่มต้นใช้งาน Bare Metal (เทียม) และเวลาปรับใช้ซ้ำแทบจะไม่มีส่วนช่วยให้โครงการประสบความสำเร็จโดยรวมเลย อย่างน้อยสิ่งเหล่านี้มีอิทธิพลน้อยกว่าโครงสร้างพื้นฐานเฟรมเวิร์กที่แข็งแกร่ง เอกสารที่แข็งแกร่ง ชุมชน และทักษะนักพัฒนาที่แข็งแกร่ง ดังนั้นจึงควรพิจารณาด้วยวิธีนี้ดีกว่า: ถ้าจนถึงตอนนี้:
  • คุณปล่อยให้ ORM ของคุณทำงานอย่างแพร่หลาย โดยสร้างการสืบค้นหลายร้อยรายการสำหรับเวิร์กโฟลว์ง่ายๆ
  • คุณต้องมีกิกะไบต์ไม่สิ้นสุดเพื่อใช้งานเสาหินที่ซับซ้อนปานกลาง
  • คุณมีโค้ดมากมายและมีความซับซ้อนสูงมาก (เราไม่ได้พูดถึงการเริ่มต้นที่ช้าอย่างไฮเบอร์เนตในตอนนี้) ซึ่งแอปพลิเคชันของคุณใช้เวลาโหลดหลายนาที
หากเป็นกรณีนี้ การเพิ่มปัญหา mycoservice เพิ่มเติม (ความยืดหยุ่นของเครือข่าย การส่งข้อความ DevOps โครงสร้างพื้นฐาน) จะมีผลกระทบต่อโปรเจ็กต์ของคุณมากกว่าการโหลด Hello, world ที่ว่างเปล่า และสำหรับการปรับใช้ใหม่อย่างต่อเนื่องในระหว่างการพัฒนา คุณ อาจได้โซลูชัน เช่นJRebelหรือDCEVM ใช้เวลาสักครู่เพื่ออ้างคำพูดของSimon Brown อีกครั้ง : “ หากผู้คนไม่สามารถสร้างเสาหิน (รวดเร็วและมีประสิทธิภาพ) ได้ พวกเขาจะพบกับความยากลำบากในการสร้างไมโครเซอร์วิส (รวดเร็วและมีประสิทธิภาพ) โดยไม่คำนึงถึงโครงสร้าง ” ดังนั้นเลือกเฟรมเวิร์กของคุณอย่างชาญฉลาด

ไลบรารีใดดีที่สุดสำหรับการโทร Java REST แบบซิงโครนัส

ในด้านเทคนิคระดับต่ำ คุณจะพบหนึ่งในไลบรารีไคลเอ็นต์ HTTP ต่อไปนี้: HttpClient ดั้งเดิมของ Java (ตั้งแต่ Java 11), HttpClient ของ ApacheหรือOkHttp โปรดทราบว่าฉันพูดว่า "อาจจะ" ที่นี่เพราะมีตัวเลือกอื่น ๆ ตั้งแต่ไคลเอนต์ JAX-RS เก่าที่ดีไปจนถึง ไคลเอนต์ WebSocketสมัยใหม่ ไม่ว่าในกรณีใด แนวโน้มคือการสร้างไคลเอนต์ HTTP โดยไม่ต้องเล่นซอกับการโทร HTTP ด้วยตัวเอง ในการทำเช่นนี้ คุณต้องดู โปรเจ็กต์ OpenFeignและเอกสารประกอบของโปรเจ็กต์เป็นจุดเริ่มต้นสำหรับการอ่านเพิ่มเติม

โบรกเกอร์ที่ดีที่สุดสำหรับการส่งข้อความ Java แบบอะซิงโครนัสคืออะไร

เป็นไปได้มากว่าคุณ จะ พบกับActiveMQ (Classic หรือ Artemis) ยอดนิยม , RabbitMQหรือKafka
  • ActiveMQ และ RabbitMQ เป็นโบรกเกอร์ข้อความแบบดั้งเดิมที่ครบครัน พวกเขาเกี่ยวข้องกับการมีปฏิสัมพันธ์ของ "โบรกเกอร์ที่ชาญฉลาด" และ "ผู้ใช้ที่โง่เขลา"
  • ในอดีต ActiveMQ มีประโยชน์ในการอินไลน์ที่ง่ายดาย (สำหรับการทดสอบ) ซึ่งสามารถบรรเทาได้ด้วยการตั้งค่า RabbitMQ/Docker/TestContainer
  • Kafka ไม่สามารถเรียกได้ว่าเป็นนายหน้า “อัจฉริยะ” แบบดั้งเดิมได้ แต่เป็นที่เก็บข้อความที่ค่อนข้าง "โง่" (ไฟล์บันทึก) ที่ต้องใช้ผู้บริโภคที่ชาญฉลาดในการประมวลผล
เพื่อให้เข้าใจได้ดีขึ้นว่าเมื่อใดควรใช้ RabbitMQ (หรือตัวรับส่งข้อความแบบเดิมโดยทั่วไป) หรือ Kafka โปรดดูที่โพสต์ Pivotal นี้เป็นจุดเริ่มต้น โดยทั่วไป เมื่อเลือกนายหน้ารับส่งข้อความ พยายามเพิกเฉยต่อเหตุผลด้านประสิทธิภาพการทำงานที่ปลอมแปลง มีบางครั้งที่ทีมและชุมชนออนไลน์จะถกเถียงกันอยู่ตลอดเวลาว่า RabbitMQ นั้นเร็วแค่ไหนและ ActiveMQ นั้นช้าแค่ไหน ขณะนี้มีข้อโต้แย้งเดียวกันเกี่ยวกับ RabbitMQ พวกเขาบอกว่ามันทำงานช้าด้วย 20-30,000 ข้อความต่อวินาที Kafka บันทึกข้อความได้ 100,000 ข้อความต่อวินาที พูดตรงๆ การเปรียบเทียบแบบนี้ก็เหมือนกับการเปรียบเทียบความอบอุ่นกับความนุ่มนวล นอกจากนี้ ในทั้งสองกรณี ค่าปริมาณงานอาจอยู่ในช่วงต่ำถึงกลาง เช่น Alibaba Group อย่างไรก็ตาม คุณไม่น่าจะพบกับโปรเจ็กต์ขนาดนี้ (ล้านข้อความต่อนาที) ในความเป็นจริง พวกมันมีอยู่จริงและคงจะมีปัญหา แตกต่างจากโครงการธุรกิจ Java “ทั่วไป” อีก 99% ดังนั้นอย่าไปสนใจเรื่องแฟชั่นและกระแสเกินเลย เลือกอย่างชาญฉลาด

ฉันสามารถใช้ไลบรารีใดเพื่อทดสอบไมโครเซอร์วิสได้

มันขึ้นอยู่กับสแต็คของคุณ หากคุณมีการปรับใช้ระบบนิเวศของ Spring ก็ควรใช้เครื่องมือเฉพาะของเฟรมเวิร์ก หาก JavaEE เป็นสิ่งที่คล้ายกับArquillian มันอาจจะคุ้มค่าที่จะดู Docker และ ไลบรารี Testcontainers ที่ดีจริงๆ ซึ่งช่วยให้ตั้งค่าฐานข้อมูล Oracle ได้อย่างง่ายดายและรวดเร็วสำหรับการพัฒนาในพื้นที่หรือการทดสอบการรวมระบบ สำหรับการทดสอบจำลองเซิร์ฟเวอร์ HTTP ทั้งหมด โปรดดูที่Wiremock หากต้องการทดสอบการส่งข้อความแบบอะซิงโครนัส ให้ลองใช้ ActiveMQ หรือ RabbitMQ จากนั้นเขียนการทดสอบโดยใช้Awaitility DSL นอกจากนี้ เครื่องมือตามปกติทั้งหมดของคุณยังถูกนำมาใช้- Junit , TestNGสำหรับAssertJและMockito โปรดทราบว่านี่ไม่ใช่รายการทั้งหมด หากคุณไม่พบเครื่องมือที่คุณชื่นชอบที่นี่ โปรดโพสต์ไว้ในส่วนความคิดเห็น

จะเปิดใช้งานการบันทึกสำหรับไมโครเซอร์วิส Java ทั้งหมดได้อย่างไร

การบันทึกในกรณีของไมโครเซอร์วิสเป็นหัวข้อที่น่าสนใจและค่อนข้างซับซ้อน แทนที่จะมีไฟล์บันทึกเพียงไฟล์เดียวที่คุณสามารถจัดการโดยใช้คำสั่ง less หรือ grep ได้ ตอนนี้คุณมีไฟล์บันทึก n ไฟล์แล้ว และคุณต้องการไม่ให้ไฟล์เหล่านั้นกระจัดกระจายเกินไป บทความนี้จะอธิบายคุณลักษณะของระบบนิเวศการตัดไม้ไว้อย่างดี(เป็นภาษาอังกฤษ) อย่าลืมอ่านและให้ความสนใจกับส่วนการบันทึกแบบรวมศูนย์จากมุมมองของไมโครเซอร์วิส ในทางปฏิบัติ คุณจะพบกับแนวทางที่แตกต่างกัน: ผู้ดูแลระบบจะเขียนสคริปต์บางตัวที่รวบรวมและรวมไฟล์บันทึกจากเซิร์ฟเวอร์ต่างๆ ให้เป็นไฟล์บันทึกเดียว และนำไปไว้ในเซิร์ฟเวอร์ FTP เพื่อดาวน์โหลด การเรียกใช้ชุดค่าผสม cat/grep/unig/sort ในเซสชัน SSH แบบขนาน นี่คือสิ่งที่ Amazon AWS ทำ และคุณสามารถแจ้งให้ผู้จัดการของคุณทราบได้ ใช้เครื่องมือเช่นGraylogหรือELK Stack (Elasticsearch, Logstash, Kibana)

ไมโครเซอร์วิสของฉันค้นหาซึ่งกันและกันได้อย่างไร

จนถึงขณะนี้ เราได้สันนิษฐานว่าไมโครเซอร์วิสของเรารู้จักกันและรู้ IPS ที่เกี่ยวข้อง พูดคุยเกี่ยวกับการกำหนดค่าแบบคงที่ ดังนั้น กลุ่มธนาคารขนาดใหญ่ของเรา [ip = 192.168.200.1] รู้ว่าจำเป็นต้องสื่อสารกับเซิร์ฟเวอร์ความเสี่ยง [ip = 192.168.200.2] ซึ่งได้รับการฮาร์ดโค้ดไว้ในไฟล์คุณสมบัติ อย่างไรก็ตาม คุณสามารถทำให้สิ่งต่างๆ มีชีวิตชีวามากขึ้นได้:
  • ใช้เซิร์ฟเวอร์การกำหนดค่าบนคลาวด์ซึ่งไมโครเซอร์วิสทั้งหมดดึงการกำหนดค่าของตนแทนที่จะปรับใช้ไฟล์ application.properties บนไมโครเซอร์วิสของตน
  • เนื่องจากอินสแตนซ์บริการของคุณสามารถเปลี่ยนตำแหน่งแบบไดนามิกได้ จึงคุ้มค่าที่จะดูบริการที่รู้ว่าบริการของคุณอยู่ที่ไหน IP ของพวกเขาคืออะไร และวิธีกำหนดเส้นทาง
  • เมื่อทุกอย่างเป็นแบบไดนามิก ปัญหาใหม่ๆ ก็เกิดขึ้น เช่น การเลือกตั้งผู้นำโดยอัตโนมัติ ใครคือผู้เชี่ยวชาญที่ทำงานบางอย่างเพื่อไม่ให้ประมวลผลซ้ำสองครั้ง เป็นต้น ใครจะมาแทนที่ผู้นำเมื่อเขาล้มเหลว? การเปลี่ยนทดแทนเกิดขึ้นบนพื้นฐานใด?
โดยทั่วไป นี่คือสิ่งที่เรียกว่า microservice orchestration และเป็นอีกหนึ่งหัวข้อที่ไม่มีที่สิ้นสุด ห้องสมุดอย่างEurekaหรือZookeeperพยายาม "แก้ไข" ปัญหาเหล่านี้โดยแสดงว่ามีบริการใดบ้าง ในทางกลับกัน พวกมันทำให้เกิดความซับซ้อนเพิ่มเติม ถามใครก็ตามที่เคยติดตั้ง ZooKeeper

จะจัดระเบียบการอนุญาตและการรับรองความถูกต้องโดยใช้ Java microservices ได้อย่างไร

หัวข้อนี้ก็คุ้มค่ากับเรื่องราวที่แยกจากกัน อีกครั้ง ตัวเลือกมีตั้งแต่การตรวจสอบสิทธิ์ HTTPS พื้นฐานแบบฮาร์ดโค้ดพร้อมเฟรมเวิร์กความปลอดภัยที่กำหนดเอง ไปจนถึงการเรียกใช้การติดตั้ง Oauth2 ด้วยเซิร์ฟเวอร์การอนุญาตของตัวเอง

ฉันจะแน่ใจได้อย่างไรว่าสภาพแวดล้อมทั้งหมดของฉันเหมือนกัน

สิ่งที่เป็นจริงสำหรับการปรับใช้โดยไม่มีไมโครเซอร์วิสก็เป็นจริงเช่นกันสำหรับการปรับใช้ด้วยไมโครเซอร์วิส ลองใช้ Docker/Testcontainers และ Scripting/Ansible ร่วมกัน

ไม่มีคำถาม: สั้น ๆ เกี่ยวกับ YAML

ขอหลีกหนีจากไลบรารีและปัญหาที่เกี่ยวข้องสักครู่แล้วมาดู Yaml กันแบบคร่าวๆ รูปแบบไฟล์นี้ใช้โดยพฤตินัยเป็นรูปแบบสำหรับ "การเขียนการกำหนดค่าเป็นโค้ด" มันยังถูกใช้โดยเครื่องมือง่ายๆ เช่น Ansible และยักษ์ใหญ่อย่าง Kubernetes หากต้องการสัมผัสกับความเจ็บปวดจากการเยื้อง YAML ให้ลองเขียนไฟล์ Ansible แบบง่ายและดูว่าคุณต้องแก้ไขไฟล์มากน้อยเพียงใดจึงจะทำงานได้ตามที่คาดไว้ และแม้ว่ารูปแบบจะได้รับการสนับสนุนจาก IDE หลัก ๆ ทั้งหมดก็ตาม! หลังจากนั้นกลับมาอ่านคู่มือนี้ให้จบ
Yaml:
  - is:
    - so
    - great

แล้วธุรกรรมแบบกระจายล่ะ? การทดสอบประสิทธิภาพ? หัวข้ออื่น ๆ ?

สักวันหนึ่งในคู่มือฉบับต่อๆ ไป สำหรับตอนนี้นั่นคือทั้งหมดที่ อยู่กับเรา!

ปัญหาเชิงแนวคิดกับไมโครเซอร์วิส

นอกจากปัญหาเฉพาะของไมโครเซอร์วิสใน Java แล้ว ยังมีปัญหาอื่นๆ อีก เช่น ที่ปรากฏในโปรเจ็กต์ไมโครเซอร์วิสใดๆ ส่วนใหญ่เกี่ยวข้องกับองค์กร ทีม และฝ่ายบริหาร

ส่วนหน้าและส่วนหลังไม่ตรงกัน

ความไม่ตรงกันของส่วนหน้าและส่วนหลังเป็นปัญหาที่พบบ่อยมากในโปรเจ็กต์ไมโครเซอร์วิสจำนวนมาก มันหมายความว่าอะไร? เฉพาะในเสาหินเก่าที่ดีเท่านั้น นักพัฒนาเว็บอินเตอร์เฟสมีแหล่งข้อมูลเฉพาะแหล่งเดียวในการรับข้อมูล ในโครงการไมโครเซอร์วิส นักพัฒนาส่วนหน้าก็ไม่มีแหล่งข้อมูลที่จะรับข้อมูล ลองจินตนาการว่าคุณกำลังสร้างโปรเจ็กต์ไมโครเซอร์วิส IoT (Internet of Things) ใน Java สมมติว่าคุณจัดการเครื่องจักรจีโอเดติกและเตาเผาอุตสาหกรรมทั่วยุโรป และเตาอบเหล่านี้จะส่งข้อมูลอัปเดตเกี่ยวกับอุณหภูมิและสิ่งที่คล้ายกันถึงคุณเป็นประจำ ไม่ช้าก็เร็ว คุณอาจต้องการค้นหาเตาอบใน UI ผู้ดูแลระบบ อาจใช้ไมโครเซอร์วิส "การค้นหาเตา" ขึ้นอยู่กับว่าแบ็กเอนด์คู่หูของคุณใช้ กฎหมาย การออกแบบที่ขับเคลื่อนด้วยโดเมนหรือไมโครเซอร์วิสอย่างเคร่งครัดเพียงใด ไมโครเซอร์วิส “ค้นหาเตาอบ” อาจส่งคืนเฉพาะ ID ของเตาอบเท่านั้น ไม่ใช่ข้อมูลอื่นๆ เช่น ประเภท รุ่น หรือตำแหน่ง ในการดำเนินการนี้ นักพัฒนาส่วนหน้าจะต้องทำการเรียกเพิ่มเติมหนึ่งครั้งหรือหลายครั้ง (ขึ้นอยู่กับการใช้งานเพจ) ในไมโครเซอร์วิส “รับข้อมูล Furnace” ด้วย ID ที่พวกเขาได้รับจากไมโครเซอร์วิสแรก คำแนะนำเกี่ยวกับ Java Microservices  ส่วนที่ 3: คำถามทั่วไป - 4และถึงแม้ว่านี่จะเป็นเพียงตัวอย่างง่ายๆ แม้ว่าจะนำมาจากโครงการจริง (!) แต่ก็แสดงให้เห็นถึงปัญหาต่อไปนี้: ซูเปอร์มาร์เก็ตได้รับความนิยมอย่างมาก นั่นเป็นเพราะว่าคุณไม่จำเป็นต้องเดินทางไปซื้อผัก น้ำมะนาว พิซซ่าแช่แข็ง และกระดาษชำระถึง 10 แห่ง ให้คุณไปที่เดียวแทน ง่าย และเร็วขึ้น เช่นเดียวกับนักพัฒนาส่วนหน้าและไมโครเซอร์วิส

ความคาดหวังของฝ่ายบริหาร

ฝ่ายบริหารมีความรู้สึกเข้าใจผิดว่าตอนนี้พวกเขาจำเป็นต้องจ้างนักพัฒนาจำนวนไม่สิ้นสุดสำหรับโปรเจ็กต์ (ที่ครอบคลุม) เนื่องจากนักพัฒนาสามารถทำงานได้อย่างอิสระโดยแยกจากกันโดยแต่ละคนบนไมโครเซอร์วิสของตนเอง จำเป็นต้องมีการผสานรวมเพียงเล็กน้อยในตอนท้ายสุด (ก่อนเปิดตัวไม่นาน) คำแนะนำเกี่ยวกับ Java Microservices  ส่วนที่ 3: คำถามทั่วไป - 5ที่จริงแล้วแนวทางนี้เป็นปัญหาอย่างมาก ในย่อหน้าต่อไปนี้ เราจะพยายามอธิบายว่าทำไม

“ชิ้นเล็ก” ไม่ได้เท่ากับ “ชิ้นที่ดีกว่า”

มันจะเป็นความผิดพลาดครั้งใหญ่ที่จะสรุปว่าโค้ดที่แบ่งออกเป็น 20 ส่วนจะต้องมีคุณภาพสูงกว่าโค้ดทั้งชิ้น แม้ว่าเราจะยึดถือคุณภาพจากมุมมองด้านเทคนิคเพียงอย่างเดียว บริการส่วนบุคคลของเราอาจยังคงเรียกใช้การสืบค้นแบบ Hibernate 400 รายการเพื่อเลือกผู้ใช้จากฐานข้อมูล โดยข้ามเลเยอร์ของโค้ดที่ไม่รองรับ เรากลับมาที่คำพูดของ Simon Brown อีกครั้ง: หากคุณล้มเหลวในการสร้างเสาหินอย่างถูกต้อง การสร้างไมโครเซอร์วิสที่เหมาะสมจะเป็นเรื่องยาก มักจะสายไปมากที่จะพูดถึงความทนทานต่อข้อผิดพลาดในโครงการไมโครเซอร์วิส มากเสียจนบางครั้งมันก็น่ากลัวที่จะเห็นว่าไมโครเซอร์วิสทำงานอย่างไรในโครงการจริง เหตุผลก็คือนักพัฒนา Java ไม่พร้อมที่จะศึกษาความทนทานต่อข้อผิดพลาด ระบบเครือข่าย และหัวข้ออื่นๆ ที่เกี่ยวข้องในระดับที่เหมาะสมเสมอไป “ชิ้นส่วน” นั้นมีขนาดเล็กกว่า แต่ “ชิ้นส่วนทางเทคนิค” นั้นใหญ่กว่า ลองนึกภาพทีมไมโครเซอร์วิสของคุณถูกขอให้เขียนไมโครเซอร์วิสทางเทคนิคสำหรับการเข้าสู่ระบบฐานข้อมูล ในลักษณะนี้:
@Controller
class LoginController {
    // ...
    @PostMapping("/login")
    public boolean login(String username, String password) {
        User user = userDao.findByUserName(username);
        if (user == null) {
            // обработка варианта с несуществующим пользователем
            return false;
        }
        if (!user.getPassword().equals(hashed(password))) {
            // обработка неверного пароля
            return false;
        }
        // 'Ю-ху, залогинorсь!';
        // установите cookies, делайте, что угодно
        return true;
    }
}
ตอนนี้ทีมของคุณอาจตัดสินใจ (และบางทีอาจโน้มน้าวนักธุรกิจด้วยซ้ำ) ว่าทั้งหมดนี้เรียบง่ายและน่าเบื่อเกินไป แทนที่จะเขียนบริการเข้าสู่ระบบ ควรเขียนไมโครเซอร์วิส UserStateChanged ที่มีประโยชน์จริงๆ โดยไม่มีผลกระทบทางธุรกิจที่แท้จริงและเป็นรูปธรรม และเนื่องจากในปัจจุบัน บางคนปฏิบัติต่อ Java เหมือนไดโนเสาร์ มาเขียนไมโครเซอร์วิส UserStateChanged ของเราใน Erlang ที่ทันสมัยกันดีกว่า และลองใช้ต้นไม้สีแดงดำสักแห่งดู เพราะ Steve Yegge เขียนไว้ว่าคุณต้องรู้จักต้นไม้เหล่านี้จากภายในสู่ภายนอกจึงจะสมัครกับ Google ได้ จากมุมมองการบูรณาการ การบำรุงรักษา และการออกแบบโดยรวม สิ่งนี้แย่พอๆ กับการเขียนโค้ดสปาเก็ตตี้หลายชั้นภายในหินใหญ่ก้อนเดียว ตัวอย่างที่ประดิษฐ์และธรรมดา? นี่เป็นเรื่องจริง อย่างไรก็ตามสิ่งนี้สามารถเกิดขึ้นได้ในความเป็นจริง

ชิ้นส่วนน้อยลง - ความเข้าใจน้อยลง

จากนั้น คำถามก็เกิดขึ้นตามธรรมชาติเกี่ยวกับการทำความเข้าใจระบบโดยรวม กระบวนการและขั้นตอนการทำงานของระบบ แต่ในขณะเดียวกัน คุณในฐานะนักพัฒนาจะต้องรับผิดชอบเฉพาะการทำงานกับไมโครเซอร์วิสที่แยกออกมา [95: ล็อกอิน-101: updateUserProfile] มันสอดคล้องกับย่อหน้าก่อนหน้า แต่ขึ้นอยู่กับองค์กรของคุณ ระดับความไว้วางใจและการสื่อสาร สิ่งนี้อาจทำให้เกิดความสับสน การยักไหล่ และตำหนิได้มาก หากมีการเสียหายโดยไม่ได้ตั้งใจในห่วงโซ่ไมโครเซอร์วิส และไม่มีใครที่จะรับผิดชอบอย่างเต็มที่ต่อสิ่งที่เกิดขึ้น และไม่ใช่เรื่องของความไม่ซื่อสัตย์เลย ในความเป็นจริงการเชื่อมต่อส่วนต่าง ๆ และเข้าใจจุดยืนในภาพรวมของโครงการเป็นเรื่องยากมาก

การสื่อสารและการบริการ

ระดับของการสื่อสารและการบริการขึ้นอยู่กับขนาดของบริษัทเป็นอย่างมาก อย่างไรก็ตาม ความสัมพันธ์โดยทั่วไปนั้นชัดเจน ยิ่งมากเท่าไรก็ยิ่งมีปัญหามากขึ้นเท่านั้น
  • ใครเป็นผู้ดำเนินการไมโครเซอร์วิส #47
  • พวกเขาเพิ่งปรับใช้ไมโครเซอร์วิสเวอร์ชันใหม่ที่เข้ากันไม่ได้หรือไม่? เอกสารนี้อยู่ที่ไหน?
  • ฉันต้องพูดคุยกับใครเพื่อขอฟีเจอร์ใหม่
  • ใครจะสนับสนุนไมโครเซอร์วิสนั้นใน Erlang หลังจากที่มีเพียงคนเดียวที่รู้ภาษานี้ออกจากบริษัท
  • ทีมไมโครเซอร์วิสของเราทั้งหมดไม่เพียงทำงานในภาษาการเขียนโปรแกรมที่แตกต่างกัน แต่ยังทำงานในเขตเวลาที่ต่างกันด้วย! เราจะประสานงานทั้งหมดนี้อย่างถูกต้องได้อย่างไร?
คำแนะนำเกี่ยวกับ Java Microservices  ส่วนที่ 3: คำถามทั่วไป - 6ประเด็นหลักก็คือ เช่นเดียวกับ DevOps แนวทางที่เต็มเปี่ยมสำหรับไมโครเซอร์วิสในบริษัทขนาดใหญ่ หรือแม้แต่ในระดับนานาชาติ ก็มาพร้อมกับปัญหาการสื่อสารเพิ่มเติมมากมาย และบริษัทจะต้องเตรียมการเรื่องนี้อย่างจริงจัง

ข้อสรุป

หลังจากอ่านบทความนี้ คุณอาจคิดว่าผู้เขียนเป็นศัตรูตัวฉกาจของไมโครเซอร์วิส สิ่งนี้ไม่เป็นความจริงเลย โดยพื้นฐานแล้วฉันกำลังพยายามเน้นประเด็นที่มีเพียงไม่กี่คนที่ให้ความสนใจในการแข่งขันที่บ้าคลั่งสำหรับเทคโนโลยีใหม่ ๆ

ไมโครเซอร์วิสหรือเสาหิน?

การใช้ไมโครเซอร์วิส Java ทุกที่ทุกเวลาถือเป็นเรื่องสุดขั้ว อีกอันกลายเป็นโมดูล Maven เก่าๆ หลายร้อยโมดูลในหินใหญ่ก้อนเดียว งานของคุณคือค้นหาสมดุลที่เหมาะสม โดยเฉพาะอย่างยิ่งสำหรับโครงการใหม่ ไม่มีอะไรที่จะหยุดคุณจากการใช้แนวทาง "เสาหิน" ที่อนุรักษ์นิยมมากขึ้น และสร้างโมดูล Maven ที่ดีน้อยลง แทนที่จะเริ่มต้นด้วยไมโครเซอร์วิสที่พร้อมใช้งานบนคลาวด์จำนวน 20 ตัว

ไมโครเซอร์วิสสร้างความซับซ้อนเพิ่มเติม

โปรดทราบว่ายิ่งคุณมีไมโครเซอร์วิสมากขึ้นและ DevOps ที่ทรงพลังน้อยกว่าที่คุณมี (ไม่ การเรียกใช้สคริปต์ Ansible สองสามตัวหรือการปรับใช้กับ Heroku จะไม่นับรวม!) ปัญหาที่คุณพบในภายหลังในกระบวนการก็จะยิ่งมากขึ้นเท่านั้น แม้แต่การอ่านเนื้อหาในส่วนท้ายของคู่มือนี้สำหรับคำถามทั่วไปเกี่ยวกับไมโครเซอร์วิส Java ก็ยังถือเป็นงานที่น่าเบื่อทีเดียว คิดให้หนักเกี่ยวกับการนำโซลูชันไปใช้กับความท้าทายด้านโครงสร้างพื้นฐานทั้งหมดเหล่านี้ แล้วคุณจะรู้ได้ทันทีว่ามันไม่ได้เกี่ยวกับการเขียนโปรแกรมทางธุรกิจอีกต่อไป (สิ่งที่คุณได้รับค่าตอบแทนให้ทำ) แต่เป็นการล็อคเทคโนโลยีเข้ากับเทคโนโลยีที่มากขึ้น Shiva Prasad Reddy สรุปได้อย่างสมบูรณ์แบบในบล็อกของเขา : “คุณไม่รู้หรอกว่ามันแย่แค่ไหนเมื่อทีมใช้เวลา 70% ดิ้นรนกับโครงสร้างพื้นฐานที่ทันสมัยนี้ และเหลือเวลาเพียง 30% เท่านั้นในการทำตรรกะทางธุรกิจที่แท้จริง ศิวะ ปราสาดเรดดี้

มันคุ้มไหมที่จะสร้างไมโครเซอร์วิส Java?

เพื่อตอบคำถามนี้ ฉันอยากจะจบบทความนี้ด้วยทีเซอร์ที่เหมือนสัมภาษณ์ของ Google ที่หน้าด้านมาก หากคุณรู้คำตอบสำหรับคำถามนี้จากประสบการณ์ แม้ว่าดูเหมือนจะไม่เกี่ยวข้องกับไมโครเซอร์วิส คุณก็อาจจะพร้อมสำหรับแนวทางไมโครเซอร์วิส

สถานการณ์

ลองนึกภาพคุณมี Java Monolith ที่ทำงานโดยลำพังบนเซิร์ฟเวอร์ เฉพาะของ Hetzner ที่เล็กที่สุด เช่นเดียวกับเซิร์ฟเวอร์ฐานข้อมูลของคุณ ซึ่งทำงานบน เครื่อง Hetzner ที่คล้ายกัน ด้วย และสมมติว่า Java monolith ของคุณสามารถจัดการเวิร์กโฟลว์ได้ เช่น การลงทะเบียนผู้ใช้ และคุณไม่ได้สร้างการสืบค้นฐานข้อมูลหลายร้อยรายการต่อเวิร์กโฟลว์ แต่เป็นจำนวนที่สมเหตุสมผลมากกว่า (<10)

คำถาม

Java monolith (พูลการเชื่อมต่อ) ของคุณควรเปิดการเชื่อมต่อฐานข้อมูลจำนวนเท่าใดบนเซิร์ฟเวอร์ฐานข้อมูลของคุณ ทำไมเป็นอย่างนั้น? คุณคิดว่าผู้ใช้งานที่ใช้งานอยู่พร้อมกันจำนวนเท่าใดที่สามารถขยายขนาดได้ (โดยประมาณ)

คำตอบ

ฝากคำตอบสำหรับคำถามเหล่านี้ไว้ในส่วนความคิดเห็น ฉันหวังว่าจะได้คำตอบทั้งหมด คำแนะนำเกี่ยวกับ Java Microservices  ส่วนที่ 3: คำถามทั่วไป - 8ตอนนี้ตัดสินใจแล้ว หากคุณอ่านจนจบเราขอขอบคุณคุณมาก!
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION