รูปแบบสำหรับการจัดการการทำงานเป็นกลุ่มในบริการเว็บ REST หรือไม่?


170

รูปแบบการออกแบบที่พิสูจน์แล้วใดมีอยู่สำหรับการดำเนินการแบทช์กับทรัพยากรภายในบริการเว็บสไตล์ REST

ฉันพยายามที่จะสร้างสมดุลระหว่างอุดมคติและความเป็นจริงในแง่ของประสิทธิภาพและความมั่นคง เรามี API ทันทีที่การดำเนินการทั้งหมดดึงจากรายการทรัพยากร (เช่น: GET / ผู้ใช้) หรือในอินสแตนซ์เดียว (PUT / ผู้ใช้ / 1, DELETE / ผู้ใช้ / 22 ฯลฯ )

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

ใน API สไตล์ RPC คุณสามารถมีวิธีได้ดังนี้

/mail.do?method=markAsRead&messageIds=1,2,3,4... etc. 

REST เทียบเท่าที่นี่คืออะไร หรือว่าตกลงเพื่อตกลงกันเดี๋ยวนี้แล้ว มันทำลายการออกแบบเพื่อเพิ่มในการดำเนินการบางอย่างที่มันช่วยเพิ่มประสิทธิภาพการทำงานจริง ๆ หรือไม่? ลูกค้าในทุกกรณีในขณะนี้คือเว็บเบราว์เซอร์ (แอปพลิเคชันจาวาสคริปต์ที่ฝั่งไคลเอ็นต์)

คำตอบ:


77

รูปแบบ RESTful แบบง่ายสำหรับแบตช์คือการใช้ประโยชน์จากรีซอร์สคอลเล็กชัน ตัวอย่างเช่นหากต้องการลบหลายข้อความพร้อมกัน

DELETE /mail?&id=0&id=1&id=2

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

POST /mail?markAsRead=true
POSTDATA: ids=[0,1,2]

โดยทั่วไปคุณกำลังอัพเดตรายการเมลที่ทำเครื่องหมายว่าอ่านแล้ว

นอกจากนี้คุณยังสามารถใช้สิ่งนี้เพื่อกำหนดหลายรายการให้กับหมวดหมู่เดียวกัน

POST /mail?category=junk
POSTDATA: ids=[0,1,2]

เห็นได้ชัดว่ามีความซับซ้อนมากขึ้นในการอัปเดตบางส่วนในรูปแบบของ iTunes (เช่นศิลปิน + albumTitle แต่ไม่ใช่ trackTitle) การเปรียบเทียบถังเริ่มสลาย

POST /mail?markAsRead=true&category=junk
POSTDATA: ids=[0,1,2]

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

POST /mail/0/markAsRead
POSTDATA: true

หรือคุณสามารถใช้ทรัพยากรที่กำหนดพารามิเตอร์ได้ นี่เป็นเรื่องธรรมดาน้อยกว่าในรูปแบบ REST แต่ได้รับอนุญาตในข้อกำหนด URI และ HTTP เครื่องหมายอัฒภาคแบ่งพารามิเตอร์ตามแนวนอนภายในทรัพยากร

อัปเดตหลายคุณลักษณะหลายทรัพยากร:

POST /mail/0;1;2/markAsRead;category
POSTDATA: markAsRead=true,category=junk

อัปเดตหลาย ๆ ทรัพยากรเพียงหนึ่งแอตทริบิวต์:

POST /mail/0;1;2/markAsRead
POSTDATA: true

อัปเดตหลายแอตทริบิวต์เพียงหนึ่งทรัพยากร:

POST /mail/0/markAsRead;category
POSTDATA: markAsRead=true,category=junk

ความคิดสร้างสรรค์สงบอุดม


1
อาจมีคนโต้แย้งว่าการลบของคุณควรเป็นโพสต์จริงๆเพราะมันไม่ได้ทำลายทรัพยากรนั้นจริงๆ
Chris Nicola

6
มันไม่จำเป็น POST เป็นวิธีการรูปแบบจากโรงงานซึ่งมีความชัดเจนและชัดเจนน้อยกว่า PUT / DELETE / GET ความคาดหวังเพียงอย่างเดียวคือเซิร์ฟเวอร์จะตัดสินใจว่าจะทำอย่างไรเนื่องจาก POST โพสต์เป็นสิ่งที่มันเคยเป็นเสมอฉันส่งข้อมูลแบบฟอร์มและเซิร์ฟเวอร์ทำอะไรบางอย่าง (หวังว่าจะได้รับ) และให้ข้อบ่งชี้ถึงผลลัพธ์ เราไม่จำเป็นต้องสร้างทรัพยากรด้วย POST เรามักจะเลือก ฉันสามารถสร้างทรัพยากรด้วย PUT ได้อย่างง่ายดายฉันเพียงแค่ต้องกำหนด URL ทรัพยากรเป็นผู้ส่ง (มักจะไม่เหมาะ)
Chris Nicola

1
@nishant ในกรณีนี้คุณอาจไม่จำเป็นต้องอ้างอิงหลายแหล่งข้อมูลใน URI แต่เพียงส่งผ่าน tuples ด้วยการอ้างอิง / ค่าต่างๆในเนื้อหาของคำขอ เช่น POST / mail / markAsRead, BODY: i_0_id = 0 & i_0_value = true & i_1_id = 1 & i_1_value = false & i_2_id = 2 & i_2_value = จริง
อเล็กซ์

3
อัฒภาคสงวนไว้สำหรับจุดประสงค์นี้
อเล็กซ์

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

25

ไม่เลย - ฉันคิดว่า REST ที่เทียบเท่าคือ (หรืออย่างน้อยหนึ่งวิธีแก้ปัญหา) เกือบจะแน่นอน - อินเตอร์เฟสพิเศษที่ออกแบบมารองรับการทำงานที่ลูกค้าต้องการ

ฉันนึกถึงรูปแบบที่กล่าวถึงในหนังสือAjax in Actionของ Crane และ Pascarello (เป็นหนังสือที่ยอดเยี่ยมมาก - แนะนำอย่างยิ่ง) ซึ่งพวกเขาแสดงให้เห็นถึงการใช้งานCommandQueueเรียงลำดับวัตถุซึ่งมีหน้าที่จัดคิวคำขอเป็นแบทช์และ จากนั้นโพสต์ไว้ในเซิร์ฟเวอร์เป็นระยะ

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

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


อัปเดต : Aha! ฉันพบ snip จากหนังสือออนไลน์เล่มนั้นมากพร้อมด้วยตัวอย่างโค้ด (แม้ว่าฉันยังแนะนำให้เลือกหนังสือจริง!) ดูที่นี่เริ่มต้นด้วยหัวข้อ 5.5.3:

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

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

ต่อไปนี้เป็นฟังก์ชันที่เกี่ยวข้องสองประการ - หนึ่งหน้าที่รับผิดชอบในการเพิ่มคำสั่งในคิว ( addCommand) และอีกหนึ่งหน้าที่รับผิดชอบในการทำให้เป็นอันดับแล้วส่งไปยังเซิร์ฟเวอร์ ( fireRequest):

CommandQueue.prototype.addCommand = function(command)
{ 
    if (this.isCommand(command))
    {
        this.queue.append(command,true);
    }
}

CommandQueue.prototype.fireRequest = function()
{
    if (this.queued.length == 0)
    { 
        return; 
    }

    var data="data=";

    for (var i = 0; i < this.queued.length; i++)
    { 
        var cmd = this.queued[i]; 
        if (this.isCommand(cmd))
        {
            data += cmd.toRequestString(); 
            this.sent[cmd.id] = cmd;

            // ... and then send the contents of data in a POST request
        }
    }
}

นั่นควรจะทำให้คุณไป โชคดี!


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

อืมโอเค - ฉันคิดว่าคุณต้องการที่จะทำการดำเนินการกับวัตถุจำนวนมาก (บนเซิร์ฟเวอร์) โดยวิธีการร้องขอที่มีน้ำหนักเบา ฉันเข้าใจผิดหรือเปล่า?
Christian Nunciato

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

ที่จริงมันแบตช์พวกเขาแล้วส่งพวกเขาทั้งหมดในครั้งเดียว: สำหรับลูปใน fireRequest () เป็นหลักรวบรวมคำสั่งที่โดดเด่นทั้งหมดอนุกรมพวกเขาเป็นสตริง (ด้วย. toRequestString () เช่น "method = markAsRead & messageIds = 1,2,3 , 4 ") กำหนดสตริงนั้นให้กับ" data "และ POSTs data ให้กับเซิร์ฟเวอร์
Christian Nunciato

20

ในขณะที่ฉันคิดว่า @Alex อยู่ในเส้นทางที่ถูกต้องฉันคิดว่ามันควรจะตรงกันข้ามกับสิ่งที่แนะนำ

URL มีผล "ทรัพยากรที่เรากำหนดเป้าหมาย" จึง:

    [GET] mail/1

หมายถึงรับบันทึกจากจดหมายที่มี id 1 และ

    [PATCH] mail/1 data: mail[markAsRead]=true

หมายถึงการแก้ไขบันทึกอีเมลที่มี id 1 การสืบค้นเป็น "ตัวกรอง" การกรองข้อมูลที่ส่งคืนจาก URL

    [GET] mail?markAsRead=true

ดังนั้นที่นี่เราขอจดหมายทั้งหมดที่ทำเครื่องหมายว่าอ่านแล้ว ดังนั้นเพื่อ [PATCH] ไปยังเส้นทางนี้จะพูดว่า "แก้ไขบันทึกที่ทำเครื่องหมายไว้แล้วว่าเป็นจริง" ... ซึ่งไม่ใช่สิ่งที่เราพยายามจะบรรลุ

ดังนั้นวิธีการแบทช์ต่อไปนี้ความคิดที่ควรจะเป็น:

    [PATCH] mail/?id=1,2,3 <the records we are targeting> data: mail[markAsRead]=true

แน่นอนฉันไม่ได้บอกว่านี่คือ REST จริง (ซึ่งไม่อนุญาตให้มีการจัดการเร็กคอร์ดแบทช์) แต่จะเป็นไปตามตรรกะที่มีอยู่แล้วและใช้งานโดย REST


คำตอบที่น่าสนใจ! สำหรับตัวอย่างสุดท้ายของคุณมันจะไม่สอดคล้องกับ[GET]รูปแบบที่ต้องทำ[PATCH] mail?markAsRead=true data: [{"id": 1}, {"id": 2}, {"id": 3}](หรือแม้แต่เพียงdata: {"ids": [1,2,3]}) ประโยชน์อีกประการหนึ่งของแนวทางสำรองนี้คือคุณจะไม่พบข้อผิดพลาด "414 คำขอ URI นานเกินไป" หากคุณอัปเดตทรัพยากรนับแสนในคอลเลกชัน
rinogo

@rinogo - ไม่จริง นี่คือจุดที่ฉันทำ การสืบค้นเป็นตัวกรองสำหรับบันทึกที่เราต้องการดำเนินการ (เช่น [GET] mail / 1 ได้รับบันทึกจดหมายที่มี id 1 ขณะที่ [GET] mail? markasRead = true ส่งคืนจดหมายโดยที่ markAsRead เป็นจริงอยู่แล้ว) มันไม่มีเหตุผลที่จะทำการแก้ไขไปยัง URL เดียวกันนั้น (เช่น "แก้ไขระเบียนที่ markAsRead = true") เมื่อในความเป็นจริงเราต้องการที่จะแก้ไขบันทึกเฉพาะกับ id 1,2,3, ไม่คำนึงถึงสถานะปัจจุบันของสนามเครื่องหมายเป็นอ่าน ดังนั้นวิธีที่ฉันอธิบาย ยอมรับว่ามีปัญหากับการอัพเดทบันทึกจำนวนมาก ฉันจะสร้างจุดปลายคู่ที่แน่นน้อยกว่า
fezfox

11

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

สำหรับการลบส่งต่อไปนี้เป็นเซิร์ฟเวอร์ไม่จำเป็นต้องรู้อะไรเกี่ยวกับสถานะของวัตถุก่อนที่จะลบเกิดขึ้น

DELETE /emails
POSTDATA: [{id:1},{id:2}]

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

ตัวอย่างเมื่อส่งคำตอบเพื่ออัปเดตสถานะ "อ่าน" และ "เก็บถาวร" ของอีเมลสองฉบับแยกกันคุณจะต้องส่งข้อความต่อไปนี้:

PUT /emails
POSTDATA: [
            {
              id:1,
              to:"someone@bratwurst.com",
              from:"someguy@frommyville.com",
              subject:"Try this recipe!",
              text:"1LB Pork Sausage, 1 Onion, 1T Black Pepper, 1t Salt, 1t Mustard Powder",
              read:true,
              archived:true,
              importance:2,
              labels:["Someone","Mustard"]
            },
            {
              id:2,
              to:"someone@bratwurst.com",
              from:"someguy@frommyville.com",
              subject:"Try this recipe (With Fix)",
              text:"1LB Pork Sausage, 1 Onion, 1T Black Pepper, 1t Salt, 1T Mustard Powder, 1t Garlic Powder",
              read:true,
              archived:false,
              importance:1,
              labels:["Someone","Mustard"]
            }
            ]

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

PUT /email-statuses
POSTDATA: [
            {id:15,read:true,archived:true,importance:2,labels:["Someone","Mustard"]},
            {id:27,read:true,archived:false,importance:1,labels:["Someone","Mustard"]}
          ]

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

PATCH /emails
POSTDATA: [
            {
              id:1,
              read:true,
              archived:true
            },
            {
              id:2,
              read:true,
              archived:false
            }
          ]

ผู้คนระบุว่าควรนำ PATCH มาใช้โดยระบุการเปลี่ยนแปลงที่มี: action (CRUD), path (URL) และการเปลี่ยนแปลงค่า สิ่งนี้อาจถูกพิจารณาว่าเป็นการใช้งานแบบมาตรฐาน แต่ถ้าคุณดู REST API ทั้งหมดมันเป็นการใช้งานที่ไม่ยุ่งยาก นอกจากนี้การดำเนินการดังกล่าวข้างต้นเป็นวิธีการที่GitHub ได้ดำเนินการ PATCH

โดยสรุปแล้วเป็นไปได้ที่จะปฏิบัติตามหลักการ RESTful ด้วยการกระทำแบบแบตช์และยังคงมีประสิทธิภาพที่ยอมรับได้


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

สวัสดี BeniRose ขอบคุณสำหรับการเพิ่มความคิดเห็นฉันมักจะสงสัยว่าคนเห็นโพสต์เหล่านี้บางส่วน มันทำให้ฉันมีความสุขที่ได้เห็นคนอื่นทำ ทรัพยากรที่เกี่ยวข้องกับลักษณะ "ไร้สัญชาติ" ของ REST กำหนดว่าเป็นข้อกังวลกับเซิร์ฟเวอร์โดยไม่ต้องรักษาสถานะระหว่างการร้องขอ เช่นนี้มันไม่ชัดเจนสำหรับฉันในเรื่องที่คุณอธิบายคุณสามารถอธิบายตัวอย่างได้ไหม?
justin.hughey

8

API ไดรฟ์ของ Google มีระบบที่น่าสนใจจริงๆในการแก้ปัญหานี้ ( ดูที่นี่ )

สิ่งที่พวกเขาทำคือการจัดกลุ่มคำขอที่แตกต่างกันในคำขอเดียวโดยContent-Type: multipart/mixedคำขอแต่ละฉบับแยกกันโดยคั่นด้วยตัวกำหนดบางตัว ส่วนหัวและพารามิเตอร์การสืบค้นของชุดคำขอจะได้รับการสืบทอดไปยังคำขอส่วนบุคคล (เช่นAuthorization: Bearer some_token) เว้นแต่ว่าพวกเขาจะถูกแทนที่ในคำขอส่วนบุคคล


ตัวอย่าง : (นำมาจากเอกสารของพวกเขา)

คำขอ:

POST https://www.googleapis.com/batch

Accept-Encoding: gzip
User-Agent: Google-HTTP-Java-Client/1.20.0 (gzip)
Content-Type: multipart/mixed; boundary=END_OF_PART
Content-Length: 963

--END_OF_PART
Content-Length: 337
Content-Type: application/http
content-id: 1
content-transfer-encoding: binary


POST https://www.googleapis.com/drive/v3/files/fileId/permissions?fields=id
Authorization: Bearer authorization_token
Content-Length: 70
Content-Type: application/json; charset=UTF-8


{
  "emailAddress":"example@appsrocks.com",
  "role":"writer",
  "type":"user"
}
--END_OF_PART
Content-Length: 353
Content-Type: application/http
content-id: 2
content-transfer-encoding: binary


POST https://www.googleapis.com/drive/v3/files/fileId/permissions?fields=id&sendNotificationEmail=false
Authorization: Bearer authorization_token
Content-Length: 58
Content-Type: application/json; charset=UTF-8


{
  "domain":"appsrocks.com",
   "role":"reader",
   "type":"domain"
}
--END_OF_PART--

การตอบสนอง:

HTTP/1.1 200 OK
Alt-Svc: quic=":443"; p="1"; ma=604800
Server: GSE
Alternate-Protocol: 443:quic,p=1
X-Frame-Options: SAMEORIGIN
Content-Encoding: gzip
X-XSS-Protection: 1; mode=block
Content-Type: multipart/mixed; boundary=batch_6VIxXCQbJoQ_AATxy_GgFUk
Transfer-Encoding: chunked
X-Content-Type-Options: nosniff
Date: Fri, 13 Nov 2015 19:28:59 GMT
Cache-Control: private, max-age=0
Vary: X-Origin
Vary: Origin
Expires: Fri, 13 Nov 2015 19:28:59 GMT

--batch_6VIxXCQbJoQ_AATxy_GgFUk
Content-Type: application/http
Content-ID: response-1


HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Date: Fri, 13 Nov 2015 19:28:59 GMT
Expires: Fri, 13 Nov 2015 19:28:59 GMT
Cache-Control: private, max-age=0
Content-Length: 35


{
 "id": "12218244892818058021i"
}


--batch_6VIxXCQbJoQ_AATxy_GgFUk
Content-Type: application/http
Content-ID: response-2


HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Date: Fri, 13 Nov 2015 19:28:59 GMT
Expires: Fri, 13 Nov 2015 19:28:59 GMT
Cache-Control: private, max-age=0
Content-Length: 35


{
 "id": "04109509152946699072k"
}


--batch_6VIxXCQbJoQ_AATxy_GgFUk--

1

ฉันจะถูกล่อลวงในการดำเนินการเช่นเดียวกับในตัวอย่างของคุณในการเขียนตัวแยกวิเคราะห์ช่วง

ไม่ต้องกังวลกับการแยกวิเคราะห์ที่สามารถอ่าน "messageIds = 1-3,7-9,11,12-15" ได้ แน่นอนมันจะเพิ่มประสิทธิภาพสำหรับการดำเนินการครอบคลุมข้อความทั้งหมดและสามารถปรับขนาดได้มากขึ้น


การสังเกตที่ดีและการเพิ่มประสิทธิภาพที่ดี แต่คำถามก็คือว่าคำขอแบบนี้อาจจะ "เข้ากันได้" กับแนวคิด REST หรือไม่
Mark Renouf

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

1

โพสต์ยอดเยี่ยม ฉันค้นหาวิธีแก้ปัญหามาสองสามวันแล้ว ฉันมากับวิธีการใช้ผ่านสตริงแบบสอบถามที่มีพวง ID คั่นด้วยเครื่องหมายจุลภาคเช่น:

DELETE /my/uri/to/delete?id=1,2,3,4,5

... จากนั้นส่งผ่านไปยังWHERE INประโยคใน SQL ของฉัน มันใช้งานได้ดี แต่สงสัยว่าคนอื่นคิดอย่างไรกับวิธีนี้


1
ฉันไม่ชอบมันเพราะมันเป็นชนิดที่แนะนำชนิดใหม่สตริงที่คุณใช้เป็นรายการในที่ที่ฉันต้องการแยกมันเป็นภาษาเฉพาะประเภทแทนแล้วฉันสามารถใช้วิธีเดียวกันใน เช่นเดียวกันในหลาย ๆ ส่วนของระบบ
softarn

4
คำเตือนให้ระวังการโจมตีด้วยการฉีด SQL และล้างข้อมูลของคุณและใช้พารามิเตอร์การผูกเสมอเมื่อใช้วิธีการนี้
justin.hughey

2
ขึ้นอยู่กับพฤติกรรมที่ต้องการDELETE /books/delete?id=1,2,3เมื่อไม่มีหนังสือเล่มที่ 3 - ความWHERE INตั้งใจจะเพิกเฉยต่อบันทึกในขณะที่ฉันมักจะคาดหวังว่าDELETE /books/delete?id=3จะ 404 ถ้า 3 ไม่มีอยู่
chbrown

3
ปัญหาอื่นที่คุณอาจพบเมื่อใช้วิธีแก้ไขปัญหานี้คือการ จำกัด จำนวนอักขระที่อนุญาตในสตริง URL หากมีคนตัดสินใจลบ 5,000 รายการเป็นจำนวนมากเบราว์เซอร์อาจปฏิเสธ URL หรือเซิร์ฟเวอร์ HTTP (Apache เป็นต้น) อาจปฏิเสธ กฎทั่วไป (ซึ่งหวังว่าจะมีการเปลี่ยนแปลงด้วยเซิร์ฟเวอร์และซอฟต์แวร์ที่ดีกว่า) ไปด้วยขนาดสูงสุด 2KB คุณสามารถไปถึง 10MB ได้ที่ไหนด้วยร่างกายของ POST stackoverflow.com/questions/2364840/…
justin.hughey

0

จากมุมมองของฉันฉันคิดว่า Facebook มีการใช้งานที่ดีที่สุด

คำขอ HTTP เดียวทำด้วยพารามิเตอร์ชุดและหนึ่งสำหรับโทเค็น

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

ข้อมูลเพิ่มเติมได้ที่: Facebook batch API

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