วิธีออกแบบเว็บแอปพลิเคชัน ajax แบบผู้ใช้หลายคนให้ปลอดภัยพร้อมกัน


95

ฉันมีหน้าเว็บที่แสดงข้อมูลจำนวนมากจากเซิร์ฟเวอร์ การสื่อสารจะทำผ่าน ajax

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

หากผู้ใช้ B เข้าถึงเพจในเวลาเดียวกันและสร้างออบเจ็กต์ข้อมูลใหม่มันจะบอกเซิร์ฟเวอร์อีกครั้งผ่าน ajax และเซิร์ฟเวอร์จะส่งคืนอ็อบเจ็กต์ใหม่ให้กับผู้ใช้

ในหน้าของ A เรามีข้อมูลที่มีวัตถุที่เปลี่ยนชื่อ และในหน้าของ B เรามีข้อมูลพร้อมวัตถุใหม่ บนเซิร์ฟเวอร์ข้อมูลมีทั้งอ็อบเจ็กต์ที่เปลี่ยนชื่อและอ็อบเจ็กต์ใหม่

ตัวเลือกของฉันมีอะไรบ้างในการทำให้เพจซิงค์กับเซิร์ฟเวอร์เมื่อมีผู้ใช้หลายคนใช้พร้อมกัน

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

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

ค่าหัวแก้ไข:

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

คือการเข้าถึงฟังก์ชันและข้อมูลบนฐานข้อมูลพร้อมกันโดยไม่มีความเสี่ยงต่อข้อมูลหรือความเสียหายของรัฐ


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

การทำให้สถานะไคลเอ็นต์เป็นอนุกรมแล้วบอกเซิร์ฟเวอร์ผ่าน ajax นี่คือสถานะของฉันสิ่งที่ฉันต้องอัปเดตเป็นตัวเลือก แต่ต้องการให้ลูกค้าทราบวิธีอัปเดตข้อมูลใด ๆ และทุกบิตในที่เดียว
Raynos

1
ทางออกที่ดีที่สุดสำหรับการทำงานพร้อมกันของผู้ใช้ไม่ใช่แค่ตัวแปรเดียวหรือไม่ Websockets, comet ฯลฯ
davin

@davin มันอาจจะค่อนข้างดี แต่ฉันไม่คุ้นเคยกับดาวหางและไม่มีเว็บซ็อกเก็ตสำหรับการรองรับข้ามเบราว์เซอร์
Raynos

2
มีแพ็คเกจที่ดีสำหรับการรองรับข้ามเบราว์เซอร์โดยเฉพาะฉันขอแนะนำ socket.io แม้ว่าจะมี jWebSocket และอื่น ๆ อีกมากมาย หากคุณไปทาง socket.io คุณสามารถรวมสารพัดของ node.js ได้ทุกประเภทเช่นเฟรมเวิร์กและเอ็นจิ้นการเทมเพลต (ฝั่งไคลเอ็นต์) เป็นต้น
davin

คำตอบ:


157

ภาพรวม:

  • Intro
  • สถาปัตยกรรมเซิร์ฟเวอร์
  • สถาปัตยกรรมไคลเอนต์
  • อัปเดตกรณี
  • ยอมรับกรณี
  • กรณีความขัดแย้ง
  • ประสิทธิภาพและความสามารถในการปรับขนาด

สวัสดี Raynos

ฉันจะไม่พูดถึงผลิตภัณฑ์ใด ๆ ที่นี่ สิ่งที่คนอื่นกล่าวถึงคือชุดเครื่องมือที่ดีที่จะดูอยู่แล้ว (อาจเพิ่ม node.js ในรายการนั้น)

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

ถ้าฉันอยู่ในรองเท้าของคุณฉันจะพัฒนาสิ่งนี้:

1. ฝั่งเซิร์ฟเวอร์:

  • กำหนดระดับที่เหมาะสมที่คุณจะกำหนดสิ่งที่ฉันเรียกว่า "สิ่งประดิษฐ์อะตอม" (หน้า? วัตถุบนหน้า? ค่าภายในวัตถุ?) สิ่งนี้จะขึ้นอยู่กับเว็บเซิร์ฟเวอร์ฐานข้อมูลและฮาร์ดแวร์การแคชจำนวนผู้ใช้ # วัตถุ ฯลฯ ไม่ใช่เรื่องง่ายที่จะตัดสินใจ

  • สำหรับสิ่งประดิษฐ์อะตอมแต่ละชิ้นมี:

    • Unique-id ทั่วทั้งแอปพลิเคชัน
    • รหัสเวอร์ชันที่เพิ่มขึ้น
    • กลไกการล็อกสำหรับการเข้าถึงการเขียน (อาจจะปิดเสียง)
    • ประวัติขนาดเล็กหรือ "บันทึกการเปลี่ยนแปลง" ภายใน ringbuffer (หน่วยความจำที่ใช้ร่วมกันทำงานได้ดีสำหรับสิ่งเหล่านั้น) คู่คีย์ - ค่าเดียวอาจใช้ได้เช่นกันแม้ว่าจะขยายได้น้อยกว่า ดูhttp://en.wikipedia.org/wiki/Circular_buffer
  • เซิร์ฟเวอร์หรือส่วนประกอบเซิร์ฟเวอร์หลอกที่สามารถส่งการเปลี่ยนแปลงที่เกี่ยวข้องไปยังผู้ใช้ที่เชื่อมต่อได้อย่างมีประสิทธิภาพ Observer-Pattern เป็นเพื่อนของคุณสำหรับสิ่งนี้

2. ฝั่งไคลเอ็นต์:

  • ไคลเอนต์ javascript ที่สามารถมีการเชื่อมต่อ HTTP ที่ใช้งานได้ยาวนานไปยังเซิร์ฟเวอร์ดังกล่าวข้างต้นหรือใช้การสำรวจที่มีน้ำหนักเบา

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

  • คอมโพเนนต์ javascript artifact-committer ที่อาจร้องขอให้เปลี่ยน atomic artifact โดยพยายามรับ mutex lock มันจะตรวจจับว่าสถานะของอาร์ติแฟกต์ถูกเปลี่ยนโดยผู้ใช้รายอื่นก่อนหน้านี้เพียงไม่กี่วินาที (เวลาแฝงของไคลเอนต์จาวาสคริปต์และคอมมิตกระบวนการใน) โดยการเปรียบเทียบอาร์ติแฟกต์เวอร์ชันไคลเอ็นต์ที่รู้จักกับอาร์ติแฟกต์เวอร์ชัน -id ของเซิร์ฟเวอร์ปัจจุบัน

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

แล้วมันจะกลิ้งยังไง ...

กรณีที่ 1: ชนิดของลำดับ - แผนภาพสำหรับการอัปเดต:

  • หน้าเบราว์เซอร์แสดงผล
  • javascript "เห็น" อาร์ติแฟกต์ซึ่งแต่ละรายการมีฟิลด์ค่าอย่างน้อยหนึ่งฟิลด์ไม่ซ้ำกัน - และรหัสเวอร์ชัน
  • ไคลเอ็นต์ javascript เริ่มต้นขอให้ "ดู" ประวัติอาร์ติแฟกต์ที่พบโดยเริ่มจากเวอร์ชันที่พบ (การเปลี่ยนแปลงที่เก่ากว่าไม่น่าสนใจ)
  • กระบวนการเซิร์ฟเวอร์บันทึกคำขอและตรวจสอบและ / หรือส่งประวัติอย่างต่อเนื่อง
  • รายการประวัติอาจมีการแจ้งเตือนง่ายๆ "artifact x has change, client pls request data" ทำให้ไคลเอนต์สามารถสำรวจชุดข้อมูลแบบอิสระหรือแบบเต็ม "artifact x ได้เปลี่ยนเป็นค่า foo"
  • javascript artifact-updater ทำสิ่งที่ทำได้เพื่อดึงค่าใหม่ทันทีที่ทราบว่ามีการอัปเดต ดำเนินการตามคำขอ ajax ใหม่หรือรับการฟีดโดยไคลเอนต์ javascript
  • มีการอัปเดตเนื้อหา DOM ของเพจผู้ใช้จะได้รับแจ้งทางเลือก การดูประวัติยังคงดำเนินต่อไป

กรณีที่ 2: ตอนนี้สำหรับการกระทำ:

  • artifact-committer รู้ค่าใหม่ที่ต้องการจากอินพุตของผู้ใช้และส่งคำขอเปลี่ยนแปลงไปยังเซิร์ฟเวอร์
  • ได้รับ mutex ของเซิร์ฟเวอร์
  • เซิร์ฟเวอร์ได้รับ "เฮ้ฉันรู้สถานะของ artifact x จากเวอร์ชัน 123 ขอฉันตั้งค่าเป็นค่า foo pls"
  • ถ้าอาร์ติแฟกต์เวอร์ชันเซอร์เวอร์ไซด์ x เท่ากัน (ต้องไม่น้อยกว่า) ค่าใหม่จะได้รับการยอมรับรหัสเวอร์ชันใหม่ 124 ถูกสร้างขึ้น
  • ข้อมูลสถานะใหม่ "อัปเดตเป็นเวอร์ชัน 124" และค่าใหม่ที่เป็นทางเลือกจะใส่ไว้ที่จุดเริ่มต้นของ ringbuffer ของ artifact x (การเปลี่ยนแปลง / ประวัติ)
  • เปิดตัว serverside mutex
  • การร้องขอผู้คอมมิชชันอาร์ติแฟกต์ยินดีที่จะได้รับการยืนยันการคอมมิตพร้อมกับรหัสใหม่
  • ในขณะเดียวกันส่วนประกอบของเซิร์ฟเวอร์ serverside จะทำการสำรวจ / ผลักดัน ringbuffers ไปยังไคลเอนต์ที่เชื่อมต่อ ไคลเอนต์ทั้งหมดที่ดูบัฟเฟอร์ของสิ่งประดิษฐ์ x จะได้รับข้อมูลสถานะใหม่และค่าภายในเวลาแฝงปกติ (ดูกรณีที่ 1)

กรณีที่ 3: สำหรับความขัดแย้ง:

  • artifact committer รู้ค่าใหม่ที่ต้องการจากอินพุตของผู้ใช้และส่งคำขอเปลี่ยนแปลงไปยังเซิร์ฟเวอร์
  • ในขณะเดียวกันผู้ใช้รายอื่นอัปเดตอาร์ติแฟกต์เดียวกันสำเร็จ (ดูกรณีที่ 2) แต่เนื่องจากเวลาแฝงต่างๆจึงยังไม่ทราบผู้ใช้รายอื่นของเรา
  • ดังนั้นจึงได้รับ mutex บนเซิร์ฟเวอร์ (หรือรอจนกว่าผู้ใช้ "เร็วกว่า" จะยืนยันการเปลี่ยนแปลง)
  • เซิร์ฟเวอร์ได้รับ "เฮ้ฉันรู้สถานะของ Artifact x จากเวอร์ชัน 123 ให้ฉันตั้งค่าเป็นค่า foo"
  • บน Serverside เวอร์ชันของ artifact x ตอนนี้คือ 124 แล้ว ลูกค้าที่ร้องขอไม่สามารถทราบมูลค่าที่เขาจะเขียนทับได้
  • เห็นได้ชัดว่าเซิร์ฟเวอร์ต้องปฏิเสธคำขอเปลี่ยนแปลง (ไม่นับรวมในลำดับความสำคัญในการเขียนทับการแทรกแซงของพระเจ้า) เผยแพร่ mutex และใจดีพอที่จะส่ง ID เวอร์ชันใหม่และค่าใหม่กลับไปยังไคลเอนต์โดยตรง
  • เมื่อต้องเผชิญกับคำร้องขอการคอมมิตที่ถูกปฏิเสธและค่าที่ผู้ใช้ที่ร้องขอการเปลี่ยนแปลงยังไม่ทราบคอมมิตเตอร์ของจาวาสคริปต์หมายถึงตัวแก้ไขข้อขัดแย้งซึ่งจะแสดงและอธิบายปัญหาให้กับผู้ใช้
  • ผู้ใช้ซึ่งถูกนำเสนอด้วยตัวเลือกบางอย่างโดย JS ตัวแก้ไขข้อขัดแย้งอัจฉริยะได้รับอนุญาตให้พยายามเปลี่ยนค่าอีกครั้ง
  • เมื่อผู้ใช้เลือกค่าที่เขาเห็นว่าถูกต้องกระบวนการจะเริ่มต้นใหม่จากกรณีที่ 2 (หรือกรณีที่ 3 หากมีผู้อื่นเร็วกว่าอีกครั้ง)

คำบางคำเกี่ยวกับประสิทธิภาพและความสามารถในการปรับขนาด

HTTP Polling เทียบกับ HTTP "push"

  • การสำรวจจะสร้างคำขอ 1 ครั้งต่อวินาที 5 ต่อวินาทีอะไรก็ตามที่คุณคิดว่าเป็นเวลาในการตอบสนองที่ยอมรับได้ สิ่งนี้อาจค่อนข้างโหดร้ายกับโครงสร้างพื้นฐานของคุณหากคุณไม่ได้กำหนดค่า (Apache?) และ (php?) ให้ดีพอที่จะเป็นตัวเริ่มต้นที่ "เบา" เป็นที่พึงปรารถนาในการปรับคำขอการสำรวจบนเซิร์ฟเวอร์ให้เหมาะสมเพื่อให้ทำงานได้โดยใช้เวลาน้อยกว่าความยาวของช่วงเวลาการสำรวจ การแบ่งรันไทม์ออกเป็นครึ่งหนึ่งอาจหมายถึงการลดภาระทั้งระบบของคุณได้ถึง 50%
  • ผลักดันผ่านทาง HTTP (webworkers สมมติว่าอยู่ห่างไกลเกินไปที่จะสนับสนุนพวกเขา) จะทำให้คุณต้องมีหนึ่ง Apache / lighthttpd กระบวนการพร้อมใช้งานสำหรับผู้ใช้แต่ละคนตลอดเวลา หน่วยความจำประจำที่สงวนไว้สำหรับแต่ละกระบวนการเหล่านี้และหน่วยความจำทั้งหมดของระบบของคุณจะเป็นขีด จำกัด การปรับขนาดที่แน่นอนที่คุณจะพบ การลดรอยเท้าหน่วยความจำของการเชื่อมต่อจะเป็นสิ่งที่จำเป็นรวมถึงการ จำกัด จำนวน CPU และ I / O ที่ทำงานอย่างต่อเนื่องในแต่ละส่วน (คุณต้องการเวลาพักเครื่อง / ไม่ได้ใช้งานมาก)

การปรับขนาดแบ็กเอนด์

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

มาตราส่วนส่วนหน้า

  • ไม่ว่าคุณกำลังสำรวจหรือได้รับ "การผลักดัน" พยายามรับข้อมูลสำหรับอาร์ติแฟกต์ที่ดูทั้งหมดในขั้นตอนเดียว

การปรับแต่ง "สร้างสรรค์"

  • หากไคลเอ็นต์กำลังสำรวจและผู้ใช้จำนวนมากมักจะดูอาร์ติแฟกต์เดียวกันคุณสามารถลองเผยแพร่ประวัติของอาร์ติแฟกต์เหล่านั้นเป็นไฟล์แบบคงที่โดยอนุญาตให้ apache แคชได้อย่างไรก็ตามจะรีเฟรชบนเซิร์ฟเวอร์เมื่ออาร์ติแฟกต์เปลี่ยนไป สิ่งนี้จะนำ PHP / memcache ออกจากเกมสำหรับคำขอ Lighthttpd มีประสิทธิภาพมากในการให้บริการไฟล์แบบคงที่
  • ใช้เครือข่ายการจัดส่งเนื้อหาเช่น cotendo.com เพื่อพุชประวัติอาร์ติแฟกต์ไปที่นั่น ความหน่วงแฝงจะยิ่งใหญ่ขึ้น แต่ความสามารถในการปรับขยายเป็นความฝัน
  • เขียนเซิร์ฟเวอร์จริง (ไม่ใช้ HTTP) ที่ผู้ใช้เชื่อมต่อโดยใช้ java หรือ flash (?) คุณต้องจัดการกับการให้บริการผู้ใช้จำนวนมากในเธรดเซิร์ฟเวอร์เดียว ปั่นจักรยานผ่านซ็อกเก็ตแบบเปิดทำ (หรือมอบหมาย) งานที่ต้องการ สามารถปรับขนาดผ่านกระบวนการฟอร์กหรือเริ่มเซิร์ฟเวอร์เพิ่มเติม Mutexes จะต้องมีเอกลักษณ์เฉพาะของโลก
  • ขึ้นอยู่กับสถานการณ์การโหลดจัดกลุ่มเซิร์ฟเวอร์ส่วนหน้าและส่วนหน้าของคุณตามช่วงรหัสวัตถุ ซึ่งจะช่วยให้สามารถใช้หน่วยความจำถาวรได้ดีขึ้น (ไม่มีฐานข้อมูลใดที่มีข้อมูลทั้งหมด) และทำให้สามารถปรับขนาดการปิดเสียงได้ จาวาสคริปต์ของคุณต้องรักษาการเชื่อมต่อไปยังเซิร์ฟเวอร์หลายเครื่องในเวลาเดียวกัน

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

คริสตอฟสตราเซน


1
@ChristophStrasen ดูที่เซิร์ฟเวอร์เหตุการณ์เช่น node.js ซึ่งไม่ต้องพึ่งพาเธรดเดียวต่อผู้ใช้ สิ่งนี้ช่วยให้สามารถจัดการกับเทคโนโลยีการผลักดันโดยใช้หน่วยความจำลดลง ฉันคิดว่าเซิร์ฟเวอร์ node.js และการใช้ TCP WebSockets ช่วยในการปรับขนาดได้จริงๆ แม้ว่ามันจะทำลายการปฏิบัติตามข้อกำหนดข้ามเบราว์เซอร์อย่างสมบูรณ์
Raynos

ฉันเห็นด้วยโดยสิ้นเชิงและหวังว่าการเขียนของฉันจะไม่สนับสนุนให้มีการสร้างวงล้อใหม่! แม้ว่าล้อบางรุ่นจะเป็นของใหม่ แต่เพิ่งเริ่มเป็นที่รู้จักและยังไม่ได้รับการอธิบายที่ดีเพียงพอเพื่อให้สถาปนิกซอฟต์แวร์ระดับกลางสามารถตัดสินการประยุกต์ใช้แนวคิดเฉพาะ IMHO Node.js สมควรได้รับหนังสือ "for dummies";) ฉันจะซื้ออย่างแน่นอน
Christoph Strasen

2
+500 คุณเคยท้าทายคนนี้ มันตอบโจทย์มาก
Raynos

1
@luqmaan คำตอบนี้มาจากเดือนกุมภาพันธ์ 2011 เว็บซ็อกเก็ตยังคงเป็นของแปลกใหม่และเปิดตัวเฉพาะใน Chrome ที่ไม่มีคำนำหน้าในช่วงเดือนสิงหาคม แม้ว่า Comet และ socket.io นั้นดี แต่ฉันคิดว่านั่นเป็นเพียงข้อเสนอแนะสำหรับแนวทางที่มีประสิทธิภาพมากขึ้น
Ricardo Tomasi

1
และถ้า Node.js อยู่ไกลจากเขตความสะดวกสบายของคุณ (หรือเขตความสะดวกสบายของทีมปฏิบัติการ แต่ต้องแน่ใจเกี่ยวกับบริบททางธุรกิจของคำถาม) คุณสามารถใช้ Socket.io กับเซิร์ฟเวอร์ที่ใช้ Java ได้ ทั้ง Tomcat และ Jetty รองรับการเชื่อมต่อแบบไม่ใช้เธรดสำหรับการตั้งค่าประเภทเซิร์ฟเวอร์แบบพุช (ดูตัวอย่าง: wiki.eclipse.org/Jetty/Feature/Continuate )
Tomas

13

ฉันรู้ว่านี่เป็นคำถามเก่า แต่ฉันคิดว่าฉันแค่ตีระฆัง

OT (การแปลงการดำเนินงาน)ดูเหมือนจะเหมาะกับความต้องการของคุณสำหรับการแก้ไขผู้ใช้หลายคนพร้อมกันและสอดคล้องกัน เป็นเทคนิคที่ใช้ใน Google เอกสาร (และยังใช้ใน Google Wave):

มีไลบรารีที่ใช้ JS สำหรับการใช้ Operational Transforms - ShareJS ( http://sharejs.org/ ) ซึ่งเขียนโดยสมาชิกจากทีม Google Wave

และถ้าคุณต้องการมีเว็บเฟรมเวิร์ก MVC เต็มรูปแบบ - DerbyJS ( http://derbyjs.com/ ) สร้างขึ้นจาก ShareJS ที่ทำทุกอย่างให้คุณ

มันใช้ BrowserChannel สำหรับการสื่อสารระหว่างเซิร์ฟเวอร์และไคลเอนต์ (และฉันเชื่อว่าการสนับสนุน WebSockets ควรอยู่ในการทำงานซึ่งก่อนหน้านี้มีผ่าน Socket.IO แต่ถูกนำออกเนื่องจากปัญหาของผู้พัฒนากับ Socket.io) เอกสารสำหรับผู้เริ่มต้นคือ เบาบางเล็กน้อยในขณะนี้


5

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


นั่นเป็นจุดที่มีประโยชน์ นอกจากนี้ยังช่วยให้ฉันเข้าใจช่อง "LastEdited" ในฐานข้อมูลของเรามากขึ้นจากจุดออกแบบ
Raynos

ตรง ไซต์นี้ใช้ "heartbeat" ซึ่งหมายถึงระยะเวลา x ทุกครั้งที่ส่งคำขอ AJAX ไปยังเซิร์ฟเวอร์และจะส่งผ่าน ID ของข้อมูลเพื่อตรวจสอบรวมถึงการประทับเวลาที่แก้ไขแล้วสำหรับข้อมูลนั้น สมมติว่าเราอยู่ในคำถาม # 1029 แต่ละคำขอ AJAX เซิร์ฟเวอร์จะดูเฉพาะการประทับเวลาที่แก้ไขสำหรับคำถาม # 1029 หากพบว่าไคลเอ็นต์มีข้อมูลเวอร์ชันเก่ากว่านั้นไคลเอ็นต์จะตอบกลับไปยัง Hearbeat พร้อมสำเนาใหม่ จากนั้นไคลเอนต์สามารถโหลดหน้าซ้ำ (รีเฟรช) หรือแสดงข้อความบางอย่างให้ผู้ใช้เตือนพวกเขาเกี่ยวกับข้อมูลใหม่
Chris Baker

แสตมป์ที่แก้ไขนั้นดีกว่ามากจากนั้นจึงแฮช "ข้อมูล" ปัจจุบันของเราและเปรียบเทียบกับแฮชในอีกด้านหนึ่ง
Raynos

1
โปรดทราบว่าไคลเอนต์และเซิร์ฟเวอร์ต้องสามารถเข้าถึงได้ในเวลาเดียวกันเพื่อหลีกเลี่ยงความไม่สอดคล้องกัน
เล่น

3

คุณต้องใช้เทคนิคการกด (หรือที่เรียกว่า Comet หรือ reverse Ajax) เพื่อเผยแพร่การเปลี่ยนแปลงไปยังผู้ใช้ทันทีที่ทำกับฐานข้อมูล เทคนิคที่ดีที่สุดที่มีอยู่ในปัจจุบันดูเหมือนจะเป็นการสำรวจระยะยาวของ Ajax แต่ทุกเบราว์เซอร์ไม่รองรับดังนั้นคุณต้องมีทางเลือกอื่น โชคดีที่มีวิธีแก้ไขปัญหานี้ให้คุณแล้ว orbited.org และ socket.io ที่กล่าวถึงแล้ว

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

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

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

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

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


2

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

ฉันพบว่าเฟรมเวิร์ก Meteor ทำได้ดี ( http://docs.meteor.com/#reactivity )

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

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


1

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

  • ทุกอย่างอยู่ใน node.js (JavaScript หรือ CoffeeScript) ดังนั้นคุณสามารถแชร์สิ่งต่างๆเช่นการตรวจสอบความถูกต้องระหว่างไคลเอนต์และเซิร์ฟเวอร์
  • ใช้ websockets แต่สามารถถอยกลับสำหรับเบราว์เซอร์รุ่นเก่าได้
  • จะเน้นไปที่การอัปเดตทันทีไปยังออบเจ็กต์ภายในเครื่อง (เช่น UI รู้สึกเร็ว) โดยมีการเปลี่ยนแปลงที่ส่งไปยังเซิร์ฟเวอร์ในพื้นหลัง อนุญาตให้อัปเดตเฉพาะอะตอมเท่านั้นเพื่อให้การอัปเดตแบบผสมง่ายขึ้น การอัปเดตที่ถูกปฏิเสธบนเซิร์ฟเวอร์จะถูกย้อนกลับ
  • เป็นโบนัสจะจัดการการรีโหลดโค้ดสดให้กับคุณและจะรักษาสถานะของผู้ใช้แม้ว่าแอปจะเปลี่ยนแปลงอย่างรุนแรงก็ตาม

Meteor นั้นง่ายพอที่ฉันจะแนะนำให้คุณอย่างน้อยลองดูไอเดียที่จะขโมย


1
ฉันชอบแนวคิดของ Derby และ Meteor สำหรับแอปบางประเภทมาก .. การเป็นเจ้าของเอกสาร / บันทึกและสิทธิ์เป็นเพียงปัญหาในโลกแห่งความจริงสองสามข้อที่ยังไม่สามารถแก้ไขได้ดี นอกจากนี้ยังมาจากโลกของ MS ที่ใช้เวลานานในการทำให้ง่ายมากถึง 80% และใช้เวลากับอีก 20% มากเกินไปฉันลังเลที่จะใช้โซลูชัน PFM (pure f ** king magic)
Tracker1

1

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

มีหลายรูปแบบ Web-based พร้อมกันเป็นซอฟแวร์การทำงานร่วมกัน

มีจำนวนเป็นHTTP ห้องสมุดลูกค้า API สำหรับ etherpad-Liteเป็นโปรแกรมแก้ไขเวลาจริงการทำงานร่วมกัน

Django เรียลไทม์สนามเด็กเล่นนำไปปฏิบัติเป็น app แชทเรียลไทม์ใน Django เรียลไทม์ด้วยเทคโนโลยีต่างๆเช่นSocket.io

ทั้งสอง AppEngine และ AppScale ใช้API AppEngine ช่อง ; ซึ่งแตกต่างจากGoogle Realtime APIซึ่งแสดงโดยกูเกิลไดรฟ์ / เรียลไทม์สนามเด็กเล่น


0

เทคนิคการกดฝั่งเซิร์ฟเวอร์เป็นวิธีที่จะไปที่นี่ ดาวหางคือ (หรือเป็น?)

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

โดยเฉพาะอย่างยิ่งให้ดูการสาธิตนี้โดยผู้เขียนของห้องสมุดซึ่งแสดงให้เห็นเกือบทุกสถานการณ์ที่คุณอธิบาย


นั่นเป็นห้องสมุดที่ยอดเยี่ยมสำหรับการลดปัญหาเกี่ยวกับการสื่อสาร แต่ฉันกำลังมองหาข้อมูลระดับสูงเกี่ยวกับวิธีการออกแบบแอปพลิเคชัน
Raynos

1
โปรดทราบว่า socket.io (และ SignalR) เป็นเฟรมเวิร์กที่ใช้เว็บซ็อกเก็ตเป็นตัวเลือกชั้นหนึ่ง แต่มีทางเลือกที่เข้ากันได้เพื่อใช้เทคนิคอื่น ๆ เช่นดาวหางการโพลแบบยาวซ็อกเก็ตแฟลชและเฟรมถาวร
Tracker1
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.