วิธีการออกแบบเว็บเซอร์วิสที่ปรับขนาดได้สูงใน Java?


15

ฉันกำลังสร้างบริการบนเว็บบางอย่างที่จะมีผู้ใช้ 2,000 คนพร้อมกัน บริการดังกล่าวให้บริการฟรีและคาดว่าจะได้รับฐานผู้ใช้จำนวนมาก ในอนาคตอาจต้องมีผู้ใช้มากถึง 50,000 คน

มีคำถามอีกสองสามข้อที่แก้ไขปัญหาเช่น - /programming/2567254/building-highly-scalable-web-services

อย่างไรก็ตามความต้องการของฉันแตกต่างจากคำถามข้างต้น

ตัวอย่างเช่น - แอปพลิเคชันของฉันไม่มีส่วนต่อประสานผู้ใช้ดังนั้นรูปภาพ, CSS, javascript จึงไม่เป็นปัญหา มันมีอยู่ใน Java ดังนั้นคำแนะนำเช่นการใช้ HipHop ในการแปล PHP เป็นโค้ดเนทีฟนั้นไร้ประโยชน์

ดังนั้นฉันจึงตัดสินใจถามคำถามแยกต่างหาก

นี่คือการตั้งค่าโครงการของฉัน -

  1. วางตัวบริการบนเว็บโดยใช้ Apache CXF
  2. Hibernate 3.0 (ด้วยการปรับแต่งที่เกี่ยวข้องเช่นการโหลดแบบขี้เกียจและ HQL แบบกำหนดเองสำหรับปรับแต่ง)
  3. Tomcat 6.0
  4. MySql 5.5

อะไรคือวิธีปฏิบัติที่ดีที่สุดในการปฏิบัติตามเพื่อให้แอปพลิเคชันที่ใช้ Java สามารถปรับขนาดได้


หากคุณเปิดเผยบริการ REST การใช้ reverse proxy เช่น Varnish จะช่วยได้มาก ข้อมูลจำเป็นต้องสดเพียงใด คุณแน่ใจหรือว่าต้องการฐานข้อมูลเชิงสัมพันธ์ คุณแบ่งพาร์ติชั่นข้อมูลได้ไหม? ด้วยสแต็คเทคโนโลยีที่คุณกำลังอธิบายฉันจะมุ่งเน้นไปที่การทำให้แน่ใจว่ามีคำขอน้อยที่สุดเท่าที่จะเป็นไปได้ คุณเคยทำสิ่งนี้ในหน่วยความจำด้วยโซลูชันเช่น Hazel cast / Gigaspaces หรือไม่?
ebaxt

@ebaxt ขอบคุณสำหรับคำแนะนำของคุณ Gigaspaces ดูเหมือนจะเป็น opensource แต่นักแสดงสีน้ำตาลแดงดูน่าสนใจ
Kshitiz Sharma

1
@ebaxt "คุณแน่ใจหรือว่าคุณต้องการฐานข้อมูลเชิงสัมพันธ์?" การใช้ nosql จะมีการเปลี่ยนแปลงอย่างมากเกี่ยวกับสถาปัตยกรรมแอปพลิเคชัน เราพยายามรักษาความซับซ้อนให้น้อยที่สุด แม้ว่าต้นทุนไม่ใช่ปัจจัยสำหรับเรา ดังนั้นเราจะยึดมั่นในแนวทางเชิงสัมพันธ์
Kshitiz Sharma

1
คุณสามารถใช้ Postgres, MySQL หรืออะไรก็ได้ โครงสร้างพื้นฐานของคุณเป็นอย่างไร คุณสามารถใช้อาร์เรย์ดิสก์ได้หรือไม่ เซิร์ฟเวอร์โฮสต์อยู่ในสถานที่เดียวกันหรือไม่ คุณสามารถเชื่อมต่อคลัสเตอร์ของคุณด้วยการเต้นของหัวใจและอื่น ๆ ได้หรือไม่? คุณสามารถวางมันลงในซับเน็ตเดียวกันได้หรือไม่?
edze

1
ฉันเป็นโปรแกรมเมอร์ด้วย แต่ถ้าฐานข้อมูลเชิงสัมพันธ์ของคุณเป็นคอขวดคุณจะมีแนวโน้มที่จะจบลงด้วยคำถามนี้ มีฐานข้อมูลในตลาดบางแห่งทำงานได้ดีกว่าในบางสถานการณ์ แต่พวกเขาจะใช้การทำธุรกรรมเริ่มต้นระดับการแยกแตกต่างกันและพร้อมกันในแง่ดีแง่ร้าย VS Concurrency ฯลฯ
edze

คำตอบ:


8

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

คุณควรใช้การแคชที่ระบบของคุณ - พยายามแคชข้อมูลแบบอ่านอย่างเดียวให้มากที่สุดหรือกำหนดกลยุทธ์การแคชตัวอย่างเช่นเรามีสถานการณ์ที่ผู้ใช้เห็น "ข้อมูลเก่า" ตราบใดที่การอัปเดตล่าสุดเกิดขึ้นในชั่วโมงที่ผ่านมา
ฉันจะพิจารณา JBoss Cache หรือInfinispan (ซึ่งเป็นเหมือนโครงสร้างข้อมูลแบบกระจาย) หรือกรอบการแคชที่เป็นที่นิยมอื่น ๆ สำหรับสิ่งนี้
นอกจากนี้ตามที่คุณได้กล่าวถึงคราวฉันคิดว่าคุณทำงานในโมดูล request-respone ลองพิจารณาใช้แคชที่มีอยู่ในขอบเขตของคำขอที่กำหนดนี้สามารถแม้กระทั่ง HashMap เรียบง่ายที่มีความเกี่ยวข้องกับการจัดเก็บในท้องถิ่นด้าย
ความคิดของฉันที่นี่ค่อนข้างคล้ายกับการแคชระดับแรกที่ไฮเบอร์เนต

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

นอกจากนี้คุณต้องเข้าใจผู้ใช้ 2,000 คนพร้อมกัน - หมายความว่าผู้ใช้ 2,000 คนกำลังเข้าถึงเซิร์ฟเวอร์ของคุณในครั้งเดียวหรือพวกเขากำลังใช้ระบบของคุณหรือไม่ แยกความแตกต่างระหว่างกรณีที่ผู้ใช้ 2,000 คนพยายามเปิดซ็อกเก็ตไปยังเซิร์ฟเวอร์ของคุณและกรณีที่มีเพียง 500 และ 1,500 กำลังดูผลลัพธ์โดยป้อนข้อมูลที่ฝั่งไคลเอ็นต์

คุณควรพิจารณาการใช้การทำคลัสเตอร์ - คุณจะต้องจัดการกับปัญหาต่างๆเช่นการทำโหลดบาลานซ์เซสชั่นเหนียว (ซึ่งหมายความว่าโหลดบาลานซ์จะเปลี่ยนเส้นทางการร้องขอไปยังเซิร์ฟเวอร์เดียวกันสำหรับเซสชันเดียวกัน) และอื่น ๆ

หากคุณจำเป็นต้องมีรหัสการประสาน - เลือกกลยุทธ์การประสานอย่างระมัดระวัง ฉันเห็นบางระบบที่ใช้การล็อกแบบง่าย แต่เป็นReaderWriterLockสามารถปรับปรุงสิ่งต่าง ๆ ได้เนื่องจากการเข้าถึงส่วนใหญ่เป็นแบบอ่านอย่างเดียว

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

ที่ผมกล่าวถึงจำศีลก่อน - ฉันจะ reocmmend คุณพิจารณาอย่างรอบคอบใช้มัน - ถ้าคุณจำเป็นต้องดำเนินการจำนวนมากเขียนและน้อยอ่าน Hibernate อาจจะไม่เหมาะสำหรับคุณและคุณควรพิจารณาอาจจะทำงานร่วมกับฤดูใบไม้ผลิ JDBCเป็นเสื้อคลุมมากกว่า JDBC

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

ฉันต้องการระบุว่าที่ผ่านมาฉันจัดการกับระบบ (โหนดเดียว) บน mysql (ส่วนใหญ่เป็นแบบอ่านอย่างเดียวเท่านั้น) ด้วย jboss 4.2.1 และจัดการถึง 2000 พร้อมกัน ผู้ใช้
(ไม่สามารถเข้าถึงได้ทันทีในแง่ของการเปิดซ็อกเก็ต 2000 กับเซิร์ฟเวอร์ของเรา) แต่ใช้ / เรียกดูระบบของเราโดยใช้ JBoss Cache และโหลดแคชล่วงหน้าเพื่อเข้าถึงข้อมูลบางส่วนหรือข้อมูลที่เรารู้ว่าเป็น "ร้อนแรงและเป็นที่นิยม "แต่วิธีแก้ปัญหาของเรานั้นดีสำหรับสถาปัตยกรรมและกระแสของเรา
ดังนั้นอย่างที่ฉันพูดในกรณีนี้ -
มีเคล็ดลับและลูกเล่นมากขึ้น แต่ขึ้นอยู่กับสถาปัตยกรรมของคุณและสิ่งที่คุณต้องมีในระบบของคุณ โชคดี!


ฉันเห็นด้วยยกเว้น procs ที่เก็บไว้อย่าใช้ procs ที่จัดเก็บไว้ และคุณสามารถใช้ hashmap และค่าอะตอมมิกพร้อมกันเพื่อสร้าง threadsafe
NimChimpsky

3

คำถามที่ดี. อาจจะยากที่จะพูดซึ่งเป็นวิธีที่ดีที่สุด แต่จะลองจากประสบการณ์ของฉัน

วิธีที่ดีที่สุดในการปรับขนาดเว็บแอปพลิเคชันที่ใช้ Java คือการเขียนแบบไร้รัฐให้ได้มากที่สุด (ถ้าทำได้) สิ่งนี้ช่วยให้คุณสามารถปรับขนาดแอปพลิเคชั่นในแนวนอนซึ่งคุณสามารถเพิ่มเซิร์ฟเวอร์ Tomcat หากมีผู้ใช้งานพร้อมกันมากกว่า

อย่างไรก็ตามดังที่คุณบันทึกไว้อาจมีปัญหากับการเชื่อมต่อฐานข้อมูล แต่คำถามที่ฉันมีคือคุณจะรับข้อมูลได้อย่างไร เป็นผู้ใช้สร้างขึ้นหรือคุณได้รับข้อมูลจากบุคคลที่สามหรือไม่ สิ่งนี้สำคัญมากเพราะถ้าคุณให้บริการแก่ผู้ใช้ของคุณด้วยข้อมูลที่รวบรวมจากแอปพลิเคชันบุคคลที่สาม (พูด FB, Twitter เป็นต้น) สิ่งที่คุณสามารถติดตามได้คือเขียนไปยังฐานข้อมูลหลักและทำซ้ำข้อมูลไปยังฐานข้อมูลทาส ซึ่งถูกจัดสรรให้กับแต่ละอินสแตนซ์ tomcat จากนั้นเซิร์ฟเวอร์ Tomcat แต่ละตัวจะได้รับจากฐานข้อมูลทาสของตัวเอง

 Are there faster alternatives to Mysql?

คุณสามารถไปที่กลุ่ม MySQL ซึ่งมีที่เก็บข้อมูลในหน่วยความจำ แต่ระวังความจริงที่ว่าแอปพลิเคชันอาจต้องการการเปลี่ยนแปลงบางอย่าง sql joinsจะไม่ได้รับการสนับสนุนอย่างดีในคลัสเตอร์ MySQL แม้ว่าในรุ่นล่าสุดมีการปรับปรุงสำหรับเดียวกัน หากต้นทุนไม่ใช่ปัจจัยคุณสามารถลองใช้ Oracle

โซลูชันแคชจะปรับปรุงประสิทธิภาพอย่างแน่นอน แต่ทุกอย่างขึ้นอยู่กับสถาปัตยกรรมของแอปพลิเคชันทั้งหมด คุณควรระวังเมื่อจะส่งข้อมูลไปยังแคชเมื่อใดจึงจะทำให้สกปรก (ลบออกจากแคช)

เกี่ยวกับการกระจายโหลดในสภาพแวดล้อมหลายเซิร์ฟเวอร์ฉันขอแนะนำให้คุณใช้ load balancer มากกว่าใช้ Apache สำหรับ load balance


"ฉันขอแนะนำให้คุณใช้ load balancer มากกว่าใช้ Apache สำหรับ load balance" คุณจะแนะนำวิธีใด / ซอฟต์แวร์หากไม่ใช่ Apache
Kshitiz Sharma

โดยทั่วไปฉันแนะนำฮาร์ดแวร์ตัวโหลดบาลานซ์ซึ่งผู้ดูแลระบบเครือข่ายของคุณควรสามารถกำหนดค่าได้ หลักสูตรนี้มีค่าใช้จ่ายเพิ่มเติมสำหรับโครงการ ตัวโหลดบาลานซ์นี้จะมี IP ของตัวเอง (หรือที่เรียกว่า IP เสมือนจริง) และโดยทั่วไปคุณจะกำหนด IP นี้ให้กับโดเมนของคุณ เมื่อมีคำขอมาสิ่งนี้จะส่งไปยังเซิร์ฟเวอร์ที่เชื่อมต่ออยู่ทั้งหมดในลักษณะ round robin (รวมถึงอัลกอริทึมอื่น ๆ ที่มี) คุณสามารถใช้ apache เพื่อจุดประสงค์นี้หากฮาร์ดแวร์ไม่ใช่ตัวเลือก แต่ฉันต้องการฮาร์ดแวร์เนื่องจากคุณไม่จำเป็นต้องปรับแต่ง apache สำหรับจุดประสงค์นี้เท่านั้น

เรากำลังใช้เซิร์ฟเวอร์เฉพาะที่มี httpd เพื่อทำสิ่งเดียวกัน ฮาร์ดแวร์ไม่ใช่ปัญหา
Kshitiz Sharma

คุณสามารถใช้ httpd และ mod_cluster ได้ถ้าจำได้ถูกต้อง ผมจะพิจารณาอย่างรอบคอบก่อนที่จะไป "Overkill" การแก้ปัญหาของฮาร์ดแวร์ LB, ก่อนการตรวจสอบและ httpd mod_cluster

@zaske - คุณอาจพูดถูกว่า load balancer ของฮาร์ดแวร์อาจเป็น overkill แต่ในกรณีที่คุณต้องการขยายขนาดทำได้ง่ายโดยเพิ่มเซิร์ฟเวอร์เพิ่มเติม

2

ฉันกำลังตั้งค่าระบบที่คล้ายกัน (ในระดับมืออาชีพ) และนี่คือการออกแบบที่ฉันเลือก:

  • ตัวโหลดบาลานซ์ Nginx สองตัว (ทั้งแอ็คทีฟและทั้งสองล้มเหลวสำหรับอีกตัวหนึ่งซึ่งสมดุลกับ DNS round robin)
  • ฐานข้อมูล MySQL สองฐานข้อมูลในโหมดการจำลองข้อมูลหลัก
  • Tomcat สองอินสแตนซ์เป็นคลัสเตอร์ Tomcat
  • Memcached สองอินสแตนซ์สำหรับทั้งแคชและการแชร์สถานะเซสชันสำหรับคลัสเตอร์ Tomcat

สิ่งนี้จะทำให้เกิดความพร้อมใช้งานสูงและพร้อมใช้งานสูงโซลูชันที่ปรับขนาดได้

ตัวโหลดบาลานซ์ (บนฮาร์ดแวร์ที่เหมาะสม) จะทำการโหลดดุล 1gbit บรรทัดที่อิ่มตัวได้อย่างง่ายดาย นี่เป็นสถานที่ที่เหมาะสำหรับการถ่าย SSL

คุณสามารถบันทึกข้อมูลเซสชั่นของคุณใน memcached ในกรณีที่ Tomcat อินสแตนซ์ล้มเหลวอีกคราว Tomcat สามารถดึงข้อมูลเซสชั่นที่เกี่ยวข้องและลูกค้าจะไม่สังเกตเห็นสิ่งใด อย่าลืมที่จะรวมสิ่งนี้เข้ากับช่วงเหนียวเช่นกัน (เพื่อลดทราฟฟิกเครือข่าย)

การจัดกลุ่ม Tomcat ยังมีตัวเลือกในการแบ่งปันข้อมูลเซสชันระหว่างกลุ่มในแบบเรียลไทม์โดยไม่ต้องใช้ memcached แม้ว่าฉันจะคิดว่าประสิทธิภาพฉลาด แต่การใช้ Memcached จะดีกว่า

หากคุณต้องการพลังงานเพิ่มขึ้นในแอปพลิเคชันเหล่านี้:

  • Nginx: เพิ่ม loadbalancer ให้มากขึ้นถึงแม้ว่าฉันไม่คิดว่ามันจะเป็นคอขวดในไม่ช้า
  • Tomcat: คุณสามารถเพิ่มขนาดของคลัสเตอร์ Tomcat ได้อย่างง่ายดายหรือเพิ่มกลุ่มเพิ่มเติม
  • Mysql: เพิ่มทาสแบบอ่านอย่างเดียวหรือเพิ่มขนาดของคลัสเตอร์ (ขึ้นอยู่กับแอปพลิเคชันของคุณ แต่เนื่องจากคุณเขียนแอปพลิเคชันที่ใช้ REST จึงไม่น่าจะมีปัญหา)
  • Memcached: เพิ่มโหนดมากขึ้น Memcached สเกลค่อนข้างดีฉันเชื่อว่า

ฉันไม่ทราบว่าแอปพลิเคชันของคุณเป็นอย่างไรและแหล่งทรัพยากรขนาดใหญ่เป็นอย่างไร แต่ถ้าคุณเห็นการโหลดฐานข้อมูลสูง (ระหว่างการทดสอบโหลด!) การเพิ่มแคชระหว่างแอปพลิเคชันและฐานข้อมูลจะช่วยปรับปรุงประสิทธิภาพได้อย่างมาก แต่อย่าลืมว่าไม่ใช่ทุกอย่างที่สามารถเข้าถึงได้หากคำสั่งของคุณแตกต่างกันเสมอการแคชจะไม่ช่วยได้ (มาก)

คำแนะนำของฉันคือการดาวน์โหลด VMware Workbench (หรือซอฟต์แวร์ virtualization similair) และพยายามสร้างการตั้งค่าอย่างง่าย ไม่มีการโหลดบาลานซ์หรือทำคลัสเตอร์เพียงพื้นฐานและทำงานจากที่นั่น ทีละหนึ่งเพิ่มคุณสมบัติเพิ่มเติม (สมดุลแคชการจัดกลุ่มและอื่น ๆ ) และให้แน่ใจว่าจะทำวิจัยบางอย่างในแต่ละหัวข้อดังนั้นคุณจะรู้ว่าคุณเลือกที่ถูกต้อง

หากคุณยังคงใช้การทดสอบประสิทธิภาพเดิมต่อไปในระหว่างกระบวนการนี้คุณสามารถดูด้วยตัวคุณเองว่าการใช้Xนั้นดีกว่าการใช้Yในการตั้งค่าของคุณหรือจะมีการแคชผลกระทบอะไรบ้างเป็นต้น

ในที่สุดการตั้งค่าเช่นนี้ขึ้นอยู่กับความต้องการของแอปพลิเคชันและลูกค้าของคุณทุกสิ่งสามารถทำได้หลายวิธีโดยแต่ละจุดมีจุดแข็งและจุดอ่อนของตัวเอง

มีคำถามอื่นอีกไหม?

โชคดี!

เวสลีย์


เฮเซลคาสต์? hazelcast.com
NimChimpsky

คุณใช้เฟรมเวิร์กสำหรับแคชเลเยอร์หรือเพียงแค่แฮ็คแบบแมนนวลจำนวนมากบนเคียวรี SQL หรือไม่?
djechlin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.