portaldacalheta.pt
  • หลัก
  • การเพิ่มขึ้นของระยะไกล
  • ผู้คนและทีมงาน
  • การวางแผนและการพยากรณ์
  • การออกแบบ Ux
ส่วนหลัง

การเลือกทางเลือกของ Tech Stack - การขึ้นและลง



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

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



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



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



มีสาเหตุหลายประการที่อยู่เบื้องหลังการตัดสินใจดึงบริการและปรับปรุงกองซ้อน:

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

Table of actions - ตารางฐานข้อมูล



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

ภาพรวมสถาปัตยกรรม

แอพ Chronicles ประกอบด้วยสามส่วนที่สามารถเป็นอิสระมากหรือน้อยและทำงานในคอนเทนเนอร์ Docker แยกกัน



วิธีการจ้างวิศวกรซอฟต์แวร์
  • ผู้บริโภคคาฟคา มีความบางมาก ตาม Karafka คาฟคา ผู้บริโภคข้อความการสร้างรายการ มันจะส่งข้อความที่ได้รับทั้งหมดไปยัง Sidekiq
  • คนงาน Sidekiq เป็นคนงานที่ประมวลผลข้อความ Kafka และสร้างรายการในตารางฐานข้อมูล
  • จุดสิ้นสุดของ GraphQL:
    • จุดสิ้นสุดสาธารณะ แสดง API การค้นหารายการซึ่งใช้สำหรับฟังก์ชันต่างๆของแพลตฟอร์ม (เช่นเพื่อแสดงคำแนะนำเครื่องมือความคิดเห็นบนปุ่มคัดกรองหรือแสดงประวัติการเปลี่ยนแปลงงาน)
    • ปลายทางภายใน ให้ความสามารถในการสร้างกฎแท็กและเทมเพลตจากการย้ายข้อมูล

พงศาวดารใช้เพื่อเชื่อมต่อกับฐานข้อมูลสองฐานข้อมูล:

  • ฐานข้อมูลของตัวเอง (ที่เราจัดเก็บกฎแท็กและเทมเพลต)
  • ฐานข้อมูลแพลตฟอร์ม (ที่ซึ่งเราจัดเก็บการดำเนินการที่ผู้ใช้ดำเนินการและแท็กและการติดแท็ก)

ในขั้นตอนการแยกแอปเราได้ย้ายข้อมูลจากฐานข้อมูลแพลตฟอร์มและปิดการเชื่อมต่อแพลตฟอร์ม



แผนเริ่มต้น

เริ่มแรกเราตัดสินใจที่จะไปกับ ฮานามิ และระบบนิเวศทั้งหมดที่มีให้โดยค่าเริ่มต้น (แบบจำลองฮานามิที่สนับสนุนโดย ROM.rb , dry-rb, hanami-newrelic ฯลฯ ) การปฏิบัติตามวิธีการ 'มาตรฐาน' ในการทำสิ่งต่างๆทำให้เรามีแรงเสียดทานต่ำความเร็วในการใช้งานที่ดีและ 'Googleability' ที่ดีมากสำหรับปัญหาที่เราอาจประสบ นอกจากนี้ระบบนิเวศฮานามิยังเป็นผู้ใหญ่และเป็นที่นิยมและห้องสมุดได้รับการดูแลอย่างรอบคอบโดยสมาชิกที่เคารพนับถือของชุมชน Ruby

ยิ่งไปกว่านั้นระบบส่วนใหญ่ได้ถูกนำไปใช้ในฝั่ง Platform แล้ว (เช่น GraphQL Entry Search endpoint และการดำเนินการ CreateEntry) ดังนั้นเราจึงวางแผนที่จะคัดลอกโค้ดจำนวนมากจาก Platform ไปยัง Chronicles ตามที่เป็นอยู่โดยไม่ทำการเปลี่ยนแปลงใด ๆ นี่เป็นหนึ่งในเหตุผลสำคัญที่เราไม่ได้ใช้ Elixir เนื่องจาก Elixir ไม่ยอมให้ทำเช่นนั้น



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

เมื่อแผนไปทางทิศใต้

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



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

การพึ่งพาที่เข้ากันไม่ได้

การสกัด Chronicles เริ่มต้นในเดือนมิถุนายน 2019 และในตอนนั้น Hanami ไม่สามารถใช้งานร่วมกับอัญมณี dry-rb เวอร์ชันล่าสุดได้ กล่าวคือ Hanami เวอร์ชันล่าสุดในขณะนั้น (1.3.1) รองรับเฉพาะการตรวจสอบความถูกต้องแบบแห้ง 0.12 เท่านั้นและเราต้องการการตรวจสอบความถูกต้องแบบแห้ง 1.0.0 เราวางแผนที่จะใช้สัญญาจากการตรวจสอบความถูกต้องแบบแห้งซึ่งเปิดตัวใน 1.0.0 เท่านั้น

วิธีคอมไพล์ c++11

นอกจากนี้ Kafka 1.2 ยังเข้ากันไม่ได้กับอัญมณีแห้งดังนั้นเราจึงใช้เวอร์ชันที่เก็บของมัน ปัจจุบันเราใช้ 1.3.0.rc1 ซึ่งขึ้นอยู่กับอัญมณีแห้งใหม่ล่าสุด

การพึ่งพาที่ไม่จำเป็น

นอกจากนี้อัญมณีฮานามิยังมีการอ้างอิงมากเกินไปซึ่งเราไม่ได้วางแผนที่จะใช้เช่น hanami-cli, hanami-assets, hanami-mailer, hanami-view และแม้กระทั่ง hanami-controller . นอกจากนี้ดูที่ไฟล์ hanami-model readme เห็นได้ชัดว่ารองรับฐานข้อมูลเดียวโดยค่าเริ่มต้น ในทางกลับกัน ROM.rb ซึ่ง hanami-model ขึ้นอยู่กับรองรับการกำหนดค่าฐานข้อมูลแบบหลายฐานข้อมูลนอกกรอบ

สรุปแล้วฮานามิโดยทั่วไปและ hanami-model โดยเฉพาะดูเหมือนระดับนามธรรมที่ไม่จำเป็น

ดังนั้น 10 วันหลังจากที่เราทำการประชาสัมพันธ์ครั้งแรกที่มีความหมายกับ Chronicles เราจึงแทนที่ฮานามิด้วยซินาตร้าทั้งหมด เราสามารถใช้ Pure Rack ได้เช่นกันเพราะเราไม่ต้องการการกำหนดเส้นทางที่ซับซ้อน (เรามีจุดสิ้นสุด 'แบบคงที่' สี่จุด - ปลายทาง GraphQL สองจุดปลายทาง / ping และอินเทอร์เฟซของเว็บไซด์คิค) แต่เราตัดสินใจที่จะไม่ยอมใครง่ายๆเกินไป Sinatra เหมาะกับเราดี หากคุณต้องการเรียนรู้เพิ่มเติมโปรดดูของเรา บทช่วยสอนซินาตร้าและภาคต่อ .

Dry-schema และ Dry-validation ความเข้าใจผิด

เราใช้เวลาพอสมควรและลองผิดลองถูกมากมายเพื่อหาวิธี 'ปรุงอาหาร' แบบ dry-validation อย่างถูกต้อง

params do required(:url).filled(:string) end params do required(:url).value(:string) end params do optional(:url).value(:string?) end params do optional(:url).filled(Types::String) end params do optional(:url).filled(Types::Coercible::String) end

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

ปัญหาเกี่ยวกับ ROM.rb และ Sequel

ROM.rb และ ภาคต่อ แตกต่างจาก ActiveRecord ไม่แปลกใจเลย แนวคิดเริ่มต้นของเราที่ว่าเราจะสามารถคัดลอกและวางโค้ดส่วนใหญ่จากแพลตฟอร์มล้มเหลว ปัญหาคือส่วนของแพลตฟอร์มนั้นหนักมากดังนั้นเกือบทุกอย่างจะต้องถูกเขียนใหม่ใน ROM / Sequel เราจัดการเพื่อคัดลอกโค้ดเพียงส่วนเล็ก ๆ ซึ่งไม่ขึ้นกับกรอบ ระหว่างทางเราประสบปัญหาที่น่าหงุดหงิดและข้อบกพร่องบางประการ

กรองตามแบบสอบถามย่อย

ตัวอย่างเช่นฉันใช้เวลาหลายชั่วโมงในการหาวิธีสร้างแบบสอบถามย่อยใน ROM.rb / Sequel นี่คือสิ่งที่ฉันจะเขียนโดยไม่ต้องตื่นขึ้นมาใน Rails: scope.where(sequence_code: subquery) แม้ว่าในภาคต่อจะกลายเป็น ไม่ใช่เรื่องง่าย .

def apply_subquery_filter(base_query, params) subquery = as_subquery(build_subquery(params)) base_query.where { Sequel.lit('sequence_code IN ?', subquery) } end # This is a fixed version of https://github.com/rom-rb/rom-sql/blob/6fa344d7022b5cc9ad8e0d026448a32ca5b37f12/lib/rom/sql/relation/reading.rb#L998 # The original version has `unorder` on the subquery. # The fix was merged: https://github.com/rom-rb/rom-sql/pull/342. def as_subquery(relation) attr = relation.schema.to_a[0] subquery = relation.schema.project(attr).call(relation).dataset ROM::SQL::Attribute[attr.type].meta(sql_expr: subquery) end

ดังนั้นแทนที่จะใช้ซับเดียวแบบธรรมดาอย่าง base_query.where(sequence_code: bild_subquery(params)) เราต้องมีโหลบรรทัดที่มีโค้ดที่ไม่สำคัญชิ้นส่วน SQL ดิบและความคิดเห็นหลายบรรทัดเพื่ออธิบายสิ่งที่ทำให้เกิดการขยายตัวที่โชคร้ายนี้

การเชื่อมโยงกับเขตข้อมูลการเข้าร่วมที่ไม่สำคัญ

entry ความสัมพันธ์ (performed_actions ตาราง) มีหลัก id ฟิลด์ อย่างไรก็ตามในการเข้าร่วมกับ *taggings ตารางจะใช้ sequence_code คอลัมน์. ใน ActiveRecord จะแสดงออกค่อนข้างง่าย:

โมเดลวัตถุหน้าคืออะไร
class PerformedAction

เป็นไปได้ที่จะเขียนสิ่งเดียวกันใน ROM ด้วย

module Chronicles::Persistence::Relations::Entries

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

[4] pry(main)> Chronicles::Persistence.relations[:platform][:entries].join(:access_taggings).limit(1).to_a E, [2019-09-05T15:54:16.706292 #20153] ERROR -- : PG::UndefinedFunction: ERROR: operator does not exist: integer = uuid LINE 1: ...ion_access_taggings' ON ('performed_actions'.'id' = 'perform... ^ HINT: No operator matches the given name and argument types. You might need to add explicit type casts.: SELECT FROM 'performed_actions' INNER JOIN 'performed_action_access_taggings' ON ('performed_actions'.'id' = 'performed_action_access_taggings'.'performed_action_sequence_code') ORDER BY 'performed_actions'.'id' LIMIT 1 Sequel::DatabaseError: PG::UndefinedFunction: ERROR: operator does not exist: integer = uuid LINE 1: ...ion_access_taggings' ON ('performed_actions'.'id' = 'perform...

เราโชคดีที่ประเภทของรหัสและ sequence_code แตกต่างกันดังนั้น PG จึงแสดงข้อผิดพลาดประเภท ถ้าประเภทเหมือนกันใครจะรู้ว่าฉันจะใช้เวลาแก้ไขข้อบกพร่องนี้กี่ชั่วโมง

ดังนั้น entries.join(:access_taggings) ไม่ทำงาน จะเกิดอะไรขึ้นถ้าเราระบุเงื่อนไขการเข้าร่วมอย่างชัดเจน? เช่นเดียวกับ entries.join(:access_taggings, performed_action_sequence_code: :sequence_code) ตามที่เอกสารอย่างเป็นทางการแนะนำ

[8] pry(main)> Chronicles::Persistence.relations[:platform][:entries].join(:access_taggings, performed_action_sequence_code: :sequence_code).limit(1).to_a E, [2019-09-05T16:02:16.952972 #20153] ERROR -- : PG::UndefinedTable: ERROR: relation 'access_taggings' does not exist LINE 1: ....'updated_at' FROM 'performed_actions' INNER JOIN 'access_ta... ^: SELECT FROM 'performed_actions' INNER JOIN 'access_taggings' ON ('access_taggings'.'performed_action_sequence_code' = 'performed_actions'.'sequence_code') ORDER BY 'performed_actions'.'id' LIMIT 1 Sequel::DatabaseError: PG::UndefinedTable: ERROR: relation 'access_taggings' does not exist

ตอนนี้มันคิดว่า :access_taggings เป็นชื่อตารางด้วยเหตุผลบางประการ ได้เลยลองสลับกับชื่อตารางจริง

[10] pry(main)> data = Chronicles::Persistence.relations[:platform][:entries].join(:performed_action_access_taggings, performed_action_sequence_code: :sequence_code).limit(1).to_a => [#]

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

การแก้ไขพารามิเตอร์ SQL

มีคุณลักษณะในการค้นหา Chronicles ซึ่งช่วยให้ผู้ใช้สามารถค้นหาโดย payload แบบสอบถามมีลักษณะดังนี้ {operation: :EQ, path: ['flag', 'gid'], value: 'gid://plat/Flag/1'} โดยที่ path เป็นอาร์เรย์ของสตริงเสมอและค่าคือค่า JSON ที่ถูกต้อง

ใน ActiveRecord ดูเหมือนว่า นี้ :

@scope.where('payload -> :path #> :value::jsonb', path: path, value: value.to_json)

ในภาคต่อฉันไม่สามารถแก้ไข :path ได้อย่างถูกต้องดังนั้นฉันจึงต้องหันไปใช้ ที่ :

base_query.where(Sequel.lit('payload #> '{#{path.join(',')}}' = ?::jsonb', value.to_json))

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

Silent Magic ของ ROM-factory

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

[:] ใน python
action1 = RomFactory[:action, app: 'plat', subject_type: 'Job', action: 'deleted'] action2 = RomFactory[:action, app: 'plat', subject_type: 'Job', action: 'updated'] expect(action1.id).not_to eq(action2.id)

ไม่ความคาดหวังไม่ล้มเหลวความคาดหวังนั้นดี

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

RomFactory[:action, app: 'plat', subject_type: 'Job', action_name: 'deleted']

เนื่องจากแอตทริบิวต์ที่พิมพ์ผิดถูกละเว้นจึงกลับไปเป็นค่าเริ่มต้นที่ระบุไว้ในโรงงาน (action_name { 'created' }) และเรามีการละเมิดข้อ จำกัด ที่ไม่ซ้ำกันเนื่องจากเราพยายามสร้างการกระทำที่เหมือนกันสองรายการ เราต้องจัดการกับปัญหานี้หลายครั้งซึ่งพิสูจน์แล้วว่าต้องเสียภาษี

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

การยศาสตร์ทั่วไป

สิ่งนี้กล่าวได้ทั้งหมด:

# ActiveRecord PerformedAction.count _# => 30232445_ # ROM EntryRepository.new.root.count _# => 30232445_

และความแตกต่างนั้นยิ่งใหญ่กว่าในตัวอย่างที่ซับซ้อนมากขึ้น

ส่วนที่ดี

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

ทดสอบความเร็ว

ใช้เวลา 5-10 วินาทีในการรันชุดทดสอบทั้งหมดในเครื่องและนานสำหรับ RuboCop เวลา CI นานกว่ามาก (3-4 นาที) แต่นี่เป็นปัญหาน้อยกว่าเพราะเราสามารถเรียกใช้ทุกอย่างในเครื่องได้ด้วยเหตุนี้สิ่งที่ล้มเหลวใน CI จึงมีโอกาสน้อยกว่ามาก

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

ปรับใช้เวลา

เวลาในการปรับใช้แอป Chronicles ที่แยกออกมาคือเพียงสองนาที ไม่เร็วปานสายฟ้า แต่ก็ยังไม่แย่ เราปรับใช้บ่อยมากดังนั้นแม้แต่การปรับปรุงเล็กน้อยก็สามารถช่วยประหยัดได้มาก

ประสิทธิภาพการใช้งาน

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

แม้จะมีขนาดใหญ่ของบันทึกการดำเนินการ (30 ล้านแถวและเพิ่มขึ้นเรื่อย ๆ ) แต่เวลาตอบกลับโดยเฉลี่ยน้อยกว่า 100 มิลลิวินาที ดูแผนภูมิที่สวยงามนี้:

แผนภูมิประสิทธิภาพของแอปพลิเคชัน

โดยเฉลี่ย 80-90% ของเวลาแอปจะใช้ในฐานข้อมูล นั่นคือสิ่งที่แผนภูมิประสิทธิภาพที่เหมาะสมควรมีลักษณะดังนี้

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

โครงสร้าง

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

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

คำพูดสุดท้าย

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

แม้ว่าเราจะพยายามตัดสินใจอย่างรอบคอบและคำนวณตั้งแต่ต้น - เราเลือกใช้กองซ้อนฮานามิมาตรฐาน - เราต้องพิจารณาสแต็กของเราใหม่ตลอดทางเนื่องจากข้อกำหนดทางเทคนิคที่ไม่ได้มาตรฐานของโครงการ เราลงเอยด้วย Sinatra และสแต็คแบบแห้ง

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

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

ทำความเข้าใจพื้นฐาน

Tech Stack คืออะไร?

Tech Stack คือชุดเครื่องมือภาษาโปรแกรมรูปแบบสถาปัตยกรรมและโปรโตคอลการสื่อสารที่ทีมปฏิบัติตามเมื่อพัฒนาแอปพลิเคชัน

เหตุใดสัดส่วนจึงสำคัญในการออกแบบ

คุณจะเลือกกองเทคโนโลยีสำหรับการพัฒนาเว็บแอปพลิเคชันได้อย่างไร?

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

กองเทคโนโลยีขององค์กรปัจจุบันของคุณคืออะไร?

กลุ่มเทคโนโลยีของเราอาศัย Ruby ที่ส่วนหลังในขณะที่ส่วนหน้าเราใช้ React และ typescript ส่วนหน้าสื่อสารกับส่วนหลังผ่าน GraphQL และบางครั้งโปรโตคอล REST การสื่อสารแบบอะซิงโครนัสของบริการส่วนหลังเกิดขึ้นผ่าน Kafka หรือซิงโครนัสโดยใช้ GraphQL / REST เราใช้ PostgreSQL และ Redis เป็นฐานข้อมูลของเรา

หลักการหลักสามประการของกลยุทธ์การลงทุนในพอร์ตการลงทุน

นักลงทุนและเงินทุน

หลักการหลักสามประการของกลยุทธ์การลงทุนในพอร์ตการลงทุน
บทนำสู่ JavaScript Automation ด้วย Gulp

บทนำสู่ JavaScript Automation ด้วย Gulp

ส่วนหน้าของเว็บ

โพสต์ยอดนิยม
ความจริงเสมือนในอุตสาหกรรมยานยนต์
ความจริงเสมือนในอุตสาหกรรมยานยนต์
วิธีใช้ Bootstrap และสร้าง. NET Projects
วิธีใช้ Bootstrap และสร้าง. NET Projects
วิธีทำความเข้าใจและประเมินการลงทุนในกองทุนอสังหาริมทรัพย์ส่วนบุคคล
วิธีทำความเข้าใจและประเมินการลงทุนในกองทุนอสังหาริมทรัพย์ส่วนบุคคล
4 ไปวิจารณ์ภาษา
4 ไปวิจารณ์ภาษา
ข้อมูลเบื้องต้นเกี่ยวกับ Magento: การนำทางในระบบนิเวศอีคอมเมิร์ซยอดนิยม
ข้อมูลเบื้องต้นเกี่ยวกับ Magento: การนำทางในระบบนิเวศอีคอมเมิร์ซยอดนิยม
 
วีซ่า H-1B: การเดินทางของนักพัฒนา iOS จากฮอนดูรัสไปยัง Silicon Valley
วีซ่า H-1B: การเดินทางของนักพัฒนา iOS จากฮอนดูรัสไปยัง Silicon Valley
ข้อผิดพลาดทั่วไปในการสื่อสารกับลูกค้า: จะไม่ทำให้ลูกค้าของคุณผิดหวังได้อย่างไร
ข้อผิดพลาดทั่วไปในการสื่อสารกับลูกค้า: จะไม่ทำให้ลูกค้าของคุณผิดหวังได้อย่างไร
การออกแบบที่คาดหวัง: วิธีสร้างประสบการณ์ผู้ใช้ที่มีมนต์ขลัง
การออกแบบที่คาดหวัง: วิธีสร้างประสบการณ์ผู้ใช้ที่มีมนต์ขลัง
กราฟิก 3 มิติ: บทช่วยสอน WebGL
กราฟิก 3 มิติ: บทช่วยสอน WebGL
การออกแบบ VUI - Voice User Interface
การออกแบบ VUI - Voice User Interface
โพสต์ยอดนิยม
  • วิธีสร้างภาษาเขียนโค้ดของคุณเอง
  • วิธีที่ดีที่สุดในการเรียนรู้ c++
  • การแสดงผลฝั่งไคลเอ็นต์เทียบกับการแสดงผลฝั่งเซิร์ฟเวอร์
  • การจัดทำงบประมาณทุนเป็นกระบวนการของ
  • อะไรคือความแตกต่างระหว่างเป็น corp และ ac corp
  • บอทที่ไม่ลงรอยกันวิธีใช้
หมวดหมู่
  • การเพิ่มขึ้นของระยะไกล
  • ผู้คนและทีมงาน
  • การวางแผนและการพยากรณ์
  • การออกแบบ Ux
  • © 2022 | สงวนลิขสิทธิ์

    portaldacalheta.pt