የባች መጠይቅ ሂደት ችግሮች እና መፍትሄዎቻቸው (ክፍል 1)

የባች መጠይቅ ሂደት ችግሮች እና መፍትሄዎቻቸው (ክፍል 1)ሁሉም ዘመናዊ የሶፍትዌር ምርቶች ማለት ይቻላል በርካታ አገልግሎቶችን ያቀፉ ናቸው። ብዙ ጊዜ፣ የአገልግሎት ቻናሎች የረዥም ጊዜ ምላሽ የአፈጻጸም ችግሮች ምንጭ ይሆናሉ። የዚህ ዓይነቱ ችግር መደበኛው መፍትሔ የበርካታ የኢንተር አገልግሎት ጥያቄዎችን ወደ አንድ ጥቅል ማሸግ ሲሆን ይህም ባቺንግ ይባላል።

ባች ማቀነባበርን ከተጠቀሙ በአፈጻጸም ወይም በኮድ ግልጽነት በውጤቶቹ ደስተኛ ላይሆኑ ይችላሉ። ይህ ዘዴ እርስዎ እንደሚያስቡት በጠሪው ላይ ቀላል አይደለም. ለተለያዩ ዓላማዎች እና በተለያዩ ሁኔታዎች ውስጥ, መፍትሄዎች በጣም ሊለያዩ ይችላሉ. የተወሰኑ ምሳሌዎችን በመጠቀም የበርካታ አቀራረቦችን ጥቅሞች እና ጉዳቶች አሳይሻለሁ።

የማሳያ ፕሮጀክት

ግልጽ ለማድረግ፣ አሁን እየሠራሁበት ባለው መተግበሪያ ውስጥ ካሉት አገልግሎቶች ውስጥ አንዱን ምሳሌ እንመልከት።

ለአብነት የመድረክ ምርጫ ማብራሪያየመጥፎ አፈጻጸም ችግር በጣም አጠቃላይ ነው እና የትኛውንም ቋንቋዎች ወይም መድረኮች አይጎዳውም. ይህ ጽሑፍ ችግሮችን እና መፍትሄዎችን ለማሳየት የፀደይ + ኮትሊን ኮድ ምሳሌዎችን ይጠቀማል። ኮትሊን ለጃቫ እና ለ C # ገንቢዎች እኩል ለመረዳት (ወይም ለመረዳት የማይቻል) ነው ፣ በተጨማሪም ፣ ኮዱ ከጃቫ የበለጠ የታመቀ እና ለመረዳት የሚቻል ነው። ለንጹህ የጃቫ ገንቢዎች ለመረዳት ቀላል ለማድረግ, የ Kotlin ጥቁር ​​አስማትን አስወግዳለሁ እና ነጭ አስማትን (በሎምቦክ መንፈስ) ብቻ እጠቀማለሁ. ጥቂት የኤክስቴንሽን ዘዴዎች ይኖራሉ ፣ ግን በእውነቱ ለሁሉም የጃቫ ፕሮግራመሮች እንደ ቋሚ ዘዴዎች ያውቃሉ ፣ ስለዚህ ይህ የምድጃውን ጣዕም የማያበላሸው ትንሽ ስኳር ይሆናል።
የሰነድ ማረጋገጫ አገልግሎት አለ. አንድ ሰው ሰነድ አዘጋጅቶ ለውይይት ያቀርባል፣ በዚህ ጊዜ አርትዖቶች ይደረጋሉ እና በመጨረሻም ሰነዱ ስምምነት ላይ ይደርሳል። የማጽደቁ አገልግሎት ራሱ ስለ ሰነዶች ምንም አያውቅም፡ እዚህ እኛ የማንቆጥረው ትንሽ ተጨማሪ ተግባራት ያሉት የአጽዳቂዎች ውይይት ብቻ ነው።

ስለዚህ, በእያንዳንዳቸው ውስጥ አስቀድሞ የተወሰነ የተሳታፊዎች ስብስብ ያላቸው ቻት ሩም (ከሰነዶች ጋር የሚዛመድ) አሉ. እንደ መደበኛ ውይይቶች፣ መልእክቶች ጽሑፍ እና ፋይሎችን ይይዛሉ እና ምላሾች ወይም ማስተላለፍ ይችላሉ፡-

data class ChatMessage(
  // nullable Ń‚Đ°Đş ĐşĐ°Đş ĐżĐžŃĐ˛ĐťŃĐľŃ‚ся Ń‚ĐžĐťŃŒĐşĐž ĐżĐžŃĐťĐľ persist
  val id: Long? = null,
  /** ĐĄŃŃ‹ĐťĐşĐ° Đ˝Đ° Đ°Đ˛Ń‚Ора */
  val author: UserReference,
  /** ĐĄĐžĐžĐąŃ‰ĐľĐ˝Đ¸Đľ */
  val message: String,
  /** ĐĄŃŃ‹ĐťĐşĐ¸ Đ˝Đ° Đ°Ń‚тачи */
  // Đ¸Đˇ-Са ĐžŃĐžĐąĐľĐ˝Đ˝ĐžŃŃ‚оК ŃĐ˛ŃĐˇĐşĐ¸ JPA+СУБД ĐżŃ€ĐžŃ‰Đľ ĐżĐžĐ´Đ´ĐľŃ€ĐśĐ¸Đ˛Đ°Ń‚ŃŒ Đ¸ null, Đ¸ ĐżŃƒŃŃ‚Ń‹Đľ ŃĐżĐ¸ŃĐşĐ¸
  val files: List<FileReference>? = null,
  /** Đ•ŃĐťĐ¸ ŃĐ˛ĐťŃĐľŃ‚ся ĐžŃ‚вотОП, Ń‚Đž ĐˇĐ´ĐľŃŃŒ ĐąŃƒĐ´ĐľŃ‚ ĐžŃ€Đ¸ĐłĐ¸Đ˝Đ°Đť */
  val replyTo: ChatMessage? = null,
  /** Đ•ŃĐťĐ¸ ŃĐ˛ĐťŃĐľŃ‚ся ĐżĐľŃ€ĐľŃŃ‹ĐťĐşĐžĐš, Ń‚Đž ĐˇĐ´ĐľŃŃŒ ĐąŃƒĐ´ĐľŃ‚ ĐžŃ€Đ¸ĐłĐ¸Đ˝Đ°Đť */
  val forwardFrom: ChatMessage? = null
)

ፋይል እና የተጠቃሚ አገናኞች ወደ ሌሎች ጎራዎች አገናኞች ናቸው። እዚህ የምንኖረው እንደዚህ ነው፡-

typealias FileReference Long
typealias UserReference Long

የተጠቃሚ ውሂብ በቁልፍ ልብስ ውስጥ ተከማችቶ በREST በኩል ተገኝቷል። ለፋይሎችም ተመሳሳይ ነው፡ ፋይሎች እና ሜታኢንፎርሜሽን ስለእነሱ በተለየ የፋይል ማከማቻ አገልግሎት ውስጥ ይኖራሉ።

ወደ እነዚህ አገልግሎቶች የሚደረጉ ጥሪዎች በሙሉ ናቸው። ከባድ ጥያቄዎች. ይህ ማለት እነዚህን ጥያቄዎች የማጓጓዝ ክፍያ በሶስተኛ ወገን አገልግሎት እንዲስተናገዱ ከሚፈጀው ጊዜ የበለጠ ነው ማለት ነው። በእኛ የሙከራ ወንበሮች ላይ፣ ለእንደዚህ አይነት አገልግሎቶች የተለመደው የጥሪ ጊዜ 100 ሚሰ ነው፣ ስለዚህ እነዚህን ቁጥሮች ወደፊት እንጠቀማለን።

የመጨረሻውን የ N መልዕክቶችን ከሁሉም አስፈላጊ መረጃዎች ለመቀበል ቀላል የ REST መቆጣጠሪያ መስራት አለብን። ማለትም፣ በግንባሩ ውስጥ ያለው የመልእክት ሞዴል ከሞላ ጎደል ተመሳሳይ ነው እናም ሁሉም መረጃዎች መላክ አለባቸው ብለን እናምናለን። በፊት-መጨረሻ ሞዴል መካከል ያለው ልዩነት ፋይሉ እና ተጠቃሚው አገናኞችን ለማድረግ በትንሹ ዲክሪፕት በሆነ መልኩ መቅረብ አለባቸው፡-

/** Đ’ Ń‚акОП Đ˛Đ¸Đ´Đľ ĐžŃ‚Đ´Đ°ŃŽŃ‚ŃŃ ŃŃŃ‹ĐťĐşĐ¸ Đ˝Đ° ŃŃƒŃ‰Đ˝ĐžŃŃ‚и Đ´ĐťŃ Ń„рОнта */
data class ReferenceUI(
  /** Đ˜Đ´ĐľĐ˝Ń‚ификатОр Đ´ĐťŃ url */
  val ref: String,
  /** Đ’идиПОо ĐżĐžĐťŃŒĐˇĐžĐ˛Đ°Ń‚оНю Đ˝Đ°ĐˇĐ˛Đ°Đ˝Đ¸Đľ ŃŃŃ‹ĐťĐşĐ¸ */
  val name: String
)
data class ChatMessageUI(
  val id: Long,
  /** ĐĄŃŃ‹ĐťĐşĐ° Đ˝Đ° Đ°Đ˛Ń‚Ора */
  val author: ReferenceUI,
  /** ĐĄĐžĐžĐąŃ‰ĐľĐ˝Đ¸Đľ */
  val message: String,
  /** ĐĄŃŃ‹ĐťĐşĐ¸ Đ˝Đ° Đ°Ń‚тачи */
  val files: List<ReferenceUI>,
  /** Đ•ŃĐťĐ¸ ŃĐ˛ĐťŃŃ‚ся ĐžŃ‚вотОП, Ń‚Đž ĐˇĐ´ĐľŃŃŒ ĐąŃƒĐ´ĐľŃ‚ ĐžŃ€Đ¸ĐłĐ¸Đ˝Đ°Đť */
  val replyTo: ChatMessageUI? = null,
  /** Đ•ŃĐťĐ¸ ŃĐ˛ĐťŃŃ‚ся ĐżĐľŃ€ĐľŃŃ‹ĐťĐşĐžĐš, Ń‚Đž ĐˇĐ´ĐľŃŃŒ ĐąŃƒĐ´ĐľŃ‚ ĐžŃ€Đ¸ĐłĐ¸Đ˝Đ°Đť */
  val forwardFrom: ChatMessageUI? = null
)

የሚከተሉትን መተግበር አለብን።

interface ChatRestApi {
  fun getLast(nInt): List<ChatMessageUI>
}

የዩአይ ፖስትፊክስ ማለት ለግንባሩ የDTO ሞዴሎች ማለት ነው፣ ማለትም፣ በREST በኩል ማገልገል ያለብን።

እዚህ ላይ የሚያስደንቀው ነገር ምንም አይነት የውይይት መታወቂያ እያሳለፍን አለመሆናችን እና የChatMessage/ChatMessageUI ሞዴል እንኳን የሌለው መሆኑ ነው። ይህንን ያደረኩት የምሳሌዎቹን ኮድ ላለማጨናገፍ ሆን ብዬ ነው (ቻቶቹ የተገለሉ ናቸው፣ ስለዚህ አንድ ብቻ እንዳለን መገመት እንችላለን)።

ፍልስፍናዊ ድፍረዛሁለቱም የChatMessageUI ክፍል እና የ ChatRestApi.getLast ዘዴ የዝርዝር ዳታ አይነትን የሚጠቀሙት በእውነቱ የታዘዘ አዘጋጅ ነው። ይህ በJDK ውስጥ መጥፎ ነው፣ ስለዚህ በበይነገጹ ደረጃ የንጥረ ነገሮችን ቅደም ተከተል ማወጅ (ሲጨመሩ እና ሲወገዱ ትዕዛዙን መጠበቅ) አይሰራም። ስለዚህ የታዘዘ ስብስብ በሚያስፈልግበት ጊዜ ዝርዝርን መጠቀም የተለመደ ተግባር ሆኗል (LinkedHashSetም አለ ነገር ግን ይህ በይነገጽ አይደለም)።
አስፈላጊ ገደብ፡ ረጅም የምላሾች ወይም የማስተላለፍ ሰንሰለቶች እንደሌሉ እንገምታለን። ያም ማለት እነሱ አሉ, ግን ርዝመታቸው ከሶስት መልእክቶች አይበልጥም. መላው የመልእክት ሰንሰለት ወደ ግንባር መተላለፍ አለበት።

ከውጫዊ አገልግሎቶች ውሂብ ለመቀበል የሚከተሉት ኤፒአይዎች አሉ፡

interface ChatMessageRepository {
  fun findLast(nInt): List<ChatMessage>
}
data class FileHeadRemote(
  val id: FileReference,
  val name: String
)
interface FileRemoteApi {
  fun getHeadById(idFileReference): FileHeadRemote
  fun getHeadsByIds(idSet<FileReference>): Set<FileHeadRemote>
  fun getHeadsByIds(idList<FileReference>): List<FileHeadRemote>
  fun getHeadsByChat(): List<FileHeadRemote>
}
data class UserRemote(
  val id: UserReference,
  val name: String
)
interface UserRemoteApi {
  fun getUserById(idUserReference): UserRemote
  fun getUsersByIds(idSet<UserReference>): Set<UserRemote>
  fun getUsersByIds(idList<UserReference>): List<UserRemote>
}

ውጫዊ አገልግሎቶች መጀመሪያ ላይ ለቡድን ሂደት እንደሚሰጡ እና በሁለቱም ስሪቶች: በሴት (የኤለመንቶችን ቅደም ተከተል ሳይጠብቁ በልዩ ቁልፎች) እና በ List (ብዜቶች ሊኖሩ ይችላሉ - ትዕዛዙ ተጠብቆ ይቆያል) ሊታይ ይችላል።

ቀላል አተገባበር

የዋህ አተገባበር

የREST መቆጣጠሪያችን የመጀመሪያው ቀላል ትግበራ በአብዛኛዎቹ ጉዳዮች እንደዚህ ያለ ነገር ይመስላል።

class ChatRestController(
  private val messageRepository: ChatMessageRepository,
  private val userRepository: UserRemoteApi,
  private val fileRepository: FileRemoteApi
) : ChatRestApi {
  override fun getLast(nInt) =
    messageRepository.findLast(n)
      .map it.toFrontModel() }
  
  private fun ChatMessage.toFrontModel(): ChatMessageUI =
    ChatMessageUI(
      id = id ?: throw IllegalStateException("$this must be persisted"),
      author = userRepository.getUserById(author).toFrontReference(),
      message = message,
      files = files?.let files ->
        fileRepository.getHeadsByIds(files)
          .map it.toFrontReference() }
      } ?: listOf(),
      forwardFrom = forwardFrom?.toFrontModel(),
      replyTo = replyTo?.toFrontModel()
    )
}

ሁሉም ነገር በጣም ግልጽ ነው, እና ይህ ትልቅ ተጨማሪ ነው.

ባች ማቀነባበርን እንጠቀማለን እና መረጃን ከውጫዊ አገልግሎት በቡድን እንቀበላለን። ግን ምርታማነታችን ምን ይሆናል?

ለእያንዳንዱ መልእክት በደራሲው መስክ ላይ መረጃ ለማግኘት አንድ ጥሪ ወደ UserRemoteApi እና ሁሉንም የተያያዙ ፋይሎችን ለማግኘት ወደ FileRemoteApi አንድ ጥሪ ይደረጋል። ያ ይመስላል። ለChatMessage የ forwardFrom እና replyTo መስኮች የተገኙት ይህ አላስፈላጊ ጥሪዎችን በማይፈልግበት መንገድ ነው እንበል። ነገር ግን እነሱን ወደ ChatMessageUI መቀየር ወደ ድግግሞሽ ይመራል፣ ማለትም የጥሪ ቆጣሪዎች በከፍተኛ ሁኔታ ሊጨምሩ ይችላሉ። ቀደም ብለን እንደጠቀስነው, ብዙ ጎጆዎች እንደሌለን እና ሰንሰለቱ በሶስት መልእክቶች የተገደበ እንደሆነ እናስብ.

በውጤቱም, በአንድ መልእክት ውስጥ ከሁለት እስከ ስድስት ጥሪዎች ወደ ውጫዊ አገልግሎቶች እና ለጠቅላላው የመልእክት ፓኬጅ አንድ የጃፓ ጥሪ እናገኛለን. አጠቃላይ የጥሪዎች ብዛት ከ2*N+1 እስከ 6*N+1 ይለያያል። ይህ በእውነተኛ ክፍሎች ውስጥ ምን ያህል ነው? አንድ ገጽ ለመስራት 20 መልዕክቶችን ይወስዳል እንበል። እነሱን ለመቀበል ከ 4 እስከ 10 ሰከንድ ይወስዳል. አስፈሪ! በ 500 ms ውስጥ ማስቀመጥ እፈልጋለሁ. እና በፊተኛው ክፍል ውስጥ እንከን የለሽ ማሸብለል ለማድረግ ስላሰቡ ለዚህ የመጨረሻ ነጥብ የአፈፃፀም መስፈርቶች በእጥፍ ሊጨመሩ ይችላሉ።

ምርቶች

  1. ኮዱ እጥር ምጥን ያለ እና እራሱን የቻለ ሰነድ ነው (የድጋፍ ቡድን ህልም)።
  2. ኮዱ ቀላል ነው, ስለዚህ እራስዎን በእግር ለመተኮስ ምንም እድሎች የሉም ማለት ይቻላል.
  3. ባች ማቀነባበር ባዕድ ነገር አይመስልም እና ኦርጋኒክ በሆነ መልኩ ወደ አመክንዮ የተዋሃደ ነው።
  4. የሎጂክ ለውጦች በቀላሉ የሚደረጉ እና አካባቢያዊ ይሆናሉ።

መቀነስ

በጣም ትንሽ እሽጎች ምክንያት አስፈሪ አፈጻጸም.

ይህ አካሄድ ብዙ ጊዜ በቀላል አገልግሎቶች ወይም በፕሮቶታይፕ ውስጥ ሊታይ ይችላል። ለውጦችን የማድረግ ፍጥነት አስፈላጊ ከሆነ, ስርዓቱን ማወሳሰብ ዋጋ የለውም. በተመሳሳይ ጊዜ, ለቀላል አገልግሎታችን አፈፃፀሙ በጣም አስፈሪ ነው, ስለዚህ የዚህ አሰራር ተግባራዊነት ወሰን በጣም ጠባብ ነው.

ናይቭ ትይዩ ሂደት

ሁሉንም መልዕክቶች በትይዩ ማስኬድ መጀመር ይችላሉ - ይህ በመልእክቶች ብዛት ላይ በመመስረት በጊዜ ውስጥ ያለውን የመስመር ጭማሪን ለማስወገድ ያስችልዎታል። ይህ በተለይ ጥሩ መንገድ አይደለም ምክንያቱም በውጫዊ አገልግሎት ላይ ትልቅ ከፍተኛ ጭነት ያስከትላል.

ትይዩ ሂደትን መተግበር በጣም ቀላል ነው፡-

override fun getLast(nInt) =
  messageRepository.findLast(n).parallelStream()
    .map it.toFrontModel() }
    .collect(toList())

ትይዩ የመልእክት ማቀናበሪያን በመጠቀም ከ300-700 ሚሴን በሐሳብ ደረጃ እናገኛለን፣ ይህም ከዋህነት ትግበራ በጣም የተሻለ ነው፣ ነገር ግን አሁንም በቂ ፈጣን አይደለም።

በዚህ አቀራረብ፣ የተጠቃሚ ማከማቻ እና የፋይል ማከማቻ ጥያቄዎች በተመሳሳይ መልኩ ይፈጸማሉ፣ ይህ ደግሞ በጣም ቀልጣፋ አይደለም። ይህንን ለማስተካከል የጥሪ አመክንዮውን በጣም መቀየር አለብዎት። ለምሳሌ፣ በማጠናቀቂያ ደረጃ (CompletableFuture ተብሎ የሚጠራ)፡-

private fun ChatMessage.toFrontModel(): ChatMessageUI =
  CompletableFuture.supplyAsync {
    userRepository.getUserById(author).toFrontReference()
  }.thenCombine(
    files?.let {
      CompletableFuture.supplyAsync {
        fileRepository.getHeadsByIds(files).map it.toFrontReference() }
      }
    } ?: CompletableFuture.completedFuture(listOf())
  ) authorfiles ->
    ChatMessageUI(
      id = id ?: throw IllegalStateException("$this must be persisted"),
      author = author,
      message = message,
      files = files,
      forwardFrom = forwardFrom?.toFrontModel(),
      replyTo = replyTo?.toFrontModel()
    )
  }.get()!!

መጀመሪያ ላይ ቀላል የካርታ ኮድ ለመረዳት ቀላል እየሆነ መጥቷል. ይህ የሆነበት ምክንያት ወደ ውጫዊ አገልግሎቶች የሚደረጉ ጥሪዎችን ውጤቶቹ ጥቅም ላይ ከዋሉበት መለየት ነበረብን። ይህ በራሱ መጥፎ አይደለም. ግን ጥሪዎችን ማጣመር በጣም የሚያምር አይመስልም እና ከተለመደው ምላሽ ሰጪ “ኑድል” ጋር ይመሳሰላል።

ኮርቲኖችን ከተጠቀሙ ፣ ሁሉም ነገር የበለጠ ጨዋ ይመስላል

private fun ChatMessage.toFrontModel(): ChatMessageUI =
  join(
    userRepository.getUserById(author).toFrontReference() },
    files?.let fileRepository.getHeadsByIds(files)
      .map it.toFrontReference() } } ?: listOf() }
  ).let (author, files) ->
    ChatMessageUI(
      id = id ?: throw IllegalStateException("$this must be persisted"),
      author = author,
      message = message,
      files = files,
      forwardFrom = forwardFrom?.toFrontModel(),
      replyTo = replyTo?.toFrontModel()
    )
  }

የት

fun <ABjoin(a: () -> Ab: () -> B) =
  runBlocking(IO{
    awaitAll(async a() }async b() })
  }.let {
    it[0as to it[1as B
  }

በንድፈ ሀሳብ, እንደዚህ አይነት ትይዩ ማቀነባበሪያዎችን በመጠቀም, 200-400 ms እናገኛለን, ይህም እኛ ከምጠብቀው ጋር ቀድሞውኑ ቅርብ ነው.

እንደ አለመታደል ሆኖ ፣ እንደዚህ ዓይነቱ ጥሩ ትይዩነት የለም ፣ እና የሚከፈለው ዋጋ በጣም ጨካኝ ነው-በተመሳሳይ ጊዜ ጥቂት ተጠቃሚዎች ብቻ ሲሰሩ ፣ የጥያቄዎች ብዛት በአገልግሎቶቹ ላይ ይወድቃል ፣ ለማንኛውም በትይዩ አይከናወንም ፣ ስለዚህ እኛ ወደ ሀዘናችን ይመለሳል 4 s.

እንደዚህ አይነት አገልግሎት ስጠቀም የኔ ውጤት 1300 መልዕክቶችን ለመስራት 1700-20 ms ነው። ይህ ከመጀመሪያው ትግበራ የበለጠ ፈጣን ነው, ግን አሁንም ችግሩን አይፈታውም.

ትይዩ መጠይቆችን አማራጭ አጠቃቀሞችየሶስተኛ ወገን አገልግሎቶች ባች ማቀነባበሪያ ካልሰጡስ? ለምሳሌ ፣ በበይነገጹ ዘዴዎች ውስጥ የቡድን ማቀነባበሪያ ትግበራ አለመኖሩን መደበቅ ይችላሉ-

interface UserRemoteApi {
  fun getUserById(idUserReference): UserRemote
  fun getUsersByIds(idSet<UserReference>): Set<UserRemote> =
    id.parallelStream()
      .map getUserById(it}.collect(toSet())
  fun getUsersByIds(idList<UserReference>): List<UserRemote> =
    id.parallelStream()
      .map getUserById(it}.collect(toList())
}

በሚቀጥሉት ስሪቶች ውስጥ የቡድን ሂደትን ለማየት ተስፋ ካደረጉ ይህ ትርጉም ይሰጣል።
ምርቶች

  1. በመልዕክት ላይ የተመሰረተ ትይዩ ሂደትን በቀላሉ ተግብር።
  2. ጥሩ ልኬት.

Cons:

  1. በትይዩ ለተለያዩ አገልግሎቶች የሚቀርቡ ጥያቄዎችን ሲያስተናግድ የውሂብ ማግኛን ከሂደቱ የመለየት አስፈላጊነት።
  2. በሶስተኛ ወገን አገልግሎቶች ላይ ጭነት መጨመር።

የተግባራዊነት ወሰን ከዋህነት አቀራረብ ጋር ተመሳሳይ መሆኑን ማየት ይቻላል. የሌሎችን ምሕረት የለሽ ብዝበዛ ምክንያት የአገልግሎትዎን አፈጻጸም ብዙ ጊዜ ለመጨመር ከፈለጉ ትይዩ የጥያቄ ዘዴን መጠቀም ተገቢ ነው። በእኛ ምሳሌ, አፈፃፀሙ በ 2,5 ጊዜ ጨምሯል, ግን ይህ በግልጽ በቂ አይደለም.

መሸጎጫ

ለውጫዊ አገልግሎቶች በጄፒኤ መንፈስ መሸጎጫ ማድረግ ይችላሉ ፣ ማለትም ፣ የተቀበሉትን ዕቃዎች እንደገና እንዳያገኙ በአንድ ክፍለ ጊዜ ውስጥ ያከማቹ (በምድብ ሂደት ውስጥም ጨምሮ)። እንደዚህ አይነት መሸጎጫዎችን እራስዎ መስራት ይችላሉ፣ ስፕሪንግን በሱ @Cacheable መጠቀም ይችላሉ፣ በተጨማሪም ሁልጊዜ እንደ EhCache ያለ ዝግጁ የሆነ መሸጎጫ በእጅ መጠቀም ይችላሉ።

የተለመደው ችግር መሸጎጫዎች ጠቃሚ የሆኑት መትከያዎች ካላቸው ብቻ ነው። በእኛ ሁኔታ ፣ በደራሲው መስክ ላይ ያሉ ምቶች በጣም ዕድላቸው ከፍተኛ ነው (እንበል ፣ 50%) ፣ ግን በፋይሎች ላይ ምንም አይነት ምቶች አይኖሩም። ይህ አካሄድ አንዳንድ ማሻሻያዎችን ያቀርባል፣ ነገር ግን አፈጻጸምን በእጅጉ አይለውጥም (እና ግስጋሴ ያስፈልገናል)።

የኢንተርሴሽን (ረዥም) መሸጎጫዎች ውስብስብ የሆነ የውሸት አመክንዮ ያስፈልጋቸዋል። በአጠቃላይ፣ በኋላ ላይ የመሃል መሸጎጫ መሸጎጫዎችን በመጠቀም የአፈጻጸም ችግሮችን ለመፍታት ሲወርዱ የተሻለ ይሆናል።

ምርቶች

  1. ኮድ ሳይቀይሩ መሸጎጫውን ይተግብሩ።
  2. ምርታማነት ብዙ ጊዜ ጨምሯል (በአንዳንድ ሁኔታዎች).

Cons:

  1. በተሳሳተ መንገድ ጥቅም ላይ ከዋለ የአፈፃፀም መቀነስ እድሉ።
  2. ትልቅ የማስታወስ ችሎታ በላይ, በተለይ ረጅም መሸጎጫዎች ጋር.
  3. ውስብስብ ውድቀቶች፣ ስህተቶች በሂደት ጊዜ ለመባዛት አስቸጋሪ የሆኑ ችግሮችን ያስከትላሉ።

በጣም ብዙ ጊዜ, መሸጎጫዎች ጥቅም ላይ የሚውሉት የንድፍ ችግሮችን በፍጥነት ለመጠገን ብቻ ነው. ይህ ማለት ግን ጥቅም ላይ መዋል የለባቸውም ማለት አይደለም. ይሁን እንጂ ሁልጊዜ እነሱን በጥንቃቄ መያዝ እና በመጀመሪያ የተገኘውን የአፈፃፀም ውጤት መገምገም እና ከዚያ ብቻ ውሳኔ ማድረግ አለብዎት.

በእኛ ምሳሌ፣ መሸጎጫዎች ወደ 25% አካባቢ የአፈጻጸም ጭማሪ ይሰጣሉ። በተመሳሳይ ጊዜ, መሸጎጫዎች በጣም ብዙ ጉዳቶች አሏቸው, ስለዚህ እዚህ አልጠቀምባቸውም.

ውጤቶች

ስለዚህ፣ ባች ማቀነባበርን የሚጠቀመውን አገልግሎት የዋህ አተገባበርን እና እሱን ለማፋጠን አንዳንድ ቀላል መንገዶችን ተመልክተናል።

የእነዚህ ሁሉ ዘዴዎች ዋነኛው ጠቀሜታ ቀላልነት ነው, ከእሱም ብዙ አስደሳች ውጤቶች አሉ.

የእነዚህ ዘዴዎች የተለመደ ችግር ዝቅተኛ አፈፃፀም ነው, በዋነኝነት በፓኬቶች መጠን ምክንያት. ስለዚህ, እነዚህ መፍትሄዎች ለእርስዎ የማይስማሙ ከሆነ, የበለጠ ሥር ነቀል ዘዴዎችን ግምት ውስጥ ማስገባት ተገቢ ነው.

መፍትሄዎችን መፈለግ የሚችሉባቸው ሁለት ዋና አቅጣጫዎች አሉ-

  • ከውሂብ ጋር ያልተመሳሰለ ሾል (የፓራዳይም ለውጥ ያስፈልገዋል, ስለዚህ በዚህ ጽሑፍ ውስጥ አልተብራራም);
  • የተመሳሰለ ሂደትን በመጠበቅ የቡድኖች ማስፋፋት።

የቡድኖች መስፋፋት የውጭ ጥሪዎችን ቁጥር በእጅጉ ይቀንሳል እና በተመሳሳይ ጊዜ ኮዱን እንዲመሳሰል ያደርገዋል. የጽሁፉ ቀጣይ ክፍል በዚህ ርዕስ ላይ ያተኮረ ይሆናል።

ምንጭ: hab.com

አስተያየት ያክሉ