একটি আক্কা স্ট্রিমটি জনবসতি করতে একটি প্রবাহ পরিষেবাতে প্রেরণ করা


9

আউটপুট স্ট্রিমে ডেটা ধাক্কা দেওয়ার জন্য আমাকে একটি প্রবাহের পরিষেবা (অ্যাজুরে ব্লব পরিষেবা) কল করতে হবে, তারপরে আমাকে ঘুরিয়ে ফিরিয়ে ক্লায়েন্টের কাছে ফিরে যেতে হবে, আক্কা মাধ্যমে। আক্কা (এবং কেবলমাত্র সার্লেট কোড) ব্যতীত, আমি কেবল সার্লেটলেট আউটপ্রেমটি পেয়ে এগ্রুর সার্ভিসের পদ্ধতিতে পাস করব।

আমি সবচেয়ে কাছাকাছি গিয়ে হোঁচট খাওয়ার চেষ্টা করতে পারি, এবং স্পষ্টতই এটি ভুল, এটি এমন কিছু

        Source<ByteString, OutputStream> source = StreamConverters.asOutputStream().mapMaterializedValue(os -> {
            blobClient.download(os);
            return os;
        });

        ResponseEntity resposeEntity = HttpEntities.create(ContentTypes.APPLICATION_OCTET_STREAM, preAuthData.getFileSize(), source);

        sender().tell(new RequestResult(resposeEntity, StatusCodes.OK), self());

ধারণাটি হ'ল আমি ব্লবক্লিয়েন্ট.ডাউনলোড (ওএস) কল করে একটি আউটপুটস্প্রিম পপুলেশন পাওয়ার জন্য একটি প্রবাহ পরিষেবাটি কল করছি;

মনে হচ্ছে ল্যাম্বদা ফাংশনটি ডেকে ফিরে আসে এবং ফিরে আসে তবে তারপরে এটি ব্যর্থ হয়, কারণ কোনও তথ্য বা কিছু নেই। যেন আমার মনে হচ্ছে না যে ল্যাম্বডা ফাংশনটি কাজটি করে তবে সম্ভবত কিছু জিনিস ফেরত দেয় যা কাজ করে? নিশ্চিত না.

এক এই কিভাবে কাজ করে?


এর আচরণ কী download? এটি কি ডেটা প্রবাহিত করে osএবং কেবল একবার ডেটা লিখিত হয়ে যাওয়ার পরে ফিরে আসে?
আলেক

উত্তর:


2

এখানে আসল সমস্যাটি হচ্ছে অ্যাজুর এপিআই ব্যাক-চাপ দেওয়ার জন্য ডিজাইন করা হয়নি। আউটপুট স্ট্রিমের পক্ষে আউজুরে ফিরে সিগন্যাল করার কোনও উপায় নেই যে এটি আরও ডেটার জন্য প্রস্তুত নয়। এটি অন্য উপায়ে রাখার জন্য: যদি আজুর আপনার ডেটা গ্রাহ্য করতে সক্ষম হওয়ার চেয়ে দ্রুত গতিতে চাপ দেয় তবে কোথাও কোথাও কিছু কুৎসিত বাফার ওভারফ্লো ব্যর্থতা থাকতে হবে।

এই সত্যটি গ্রহণ করে, পরবর্তী সেরা জিনিসগুলি আমরা করতে পারি:

  • Source.lazySourceযখন প্রবাহের চাহিদা থাকে তখনই ডেটা ডাউনলোড শুরু করতে ব্যবহার করুন (যেমন, উত্সটি চালিত হচ্ছে এবং ডেটা অনুরোধ করা হচ্ছে)।
  • downloadকলটিকে অন্য কোনও থ্রেডে রাখুন যাতে উত্সটি ফিরে না আসা অবরুদ্ধ করেই এটি কার্যকর করা অব্যাহত থাকে। একবার এটি করার উপায়টি একটি Future(জাভা সেরা অনুশীলনগুলি কী তা আমি নিশ্চিত নই, তবে যেভাবেই ভালভাবে কাজ করা উচিত) with যদিও এটি প্রাথমিকভাবে গুরুত্বপূর্ণ হবে না, আপনাকে বাদে অন্য কোনও মৃত্যুদন্ডের প্রসঙ্গটি বেছে নেওয়ার প্রয়োজন হতে পারে system.dispatcher- এটি সমস্তই downloadব্লক করছে কিনা তা নির্ভর করে ।

এই জাভা কোডটি যদি ত্রুটিযুক্ত হয় তবে আমি আগাম ক্ষমা চেয়ে নিচ্ছি - আমি স্কালার সাথে আক্কা ব্যবহার করি, তাই এটি আক্কা জাভা এপিআই এবং জাভা সিনট্যাক্সের রেফারেন্সটি দেখার থেকে শুরু করে।

ResponseEntity responseEntity = HttpEntities.create(
  ContentTypes.APPLICATION_OCTET_STREAM,
  preAuthData.getFileSize(),

  // Wait until there is downstream demand to intialize the source...
  Source.lazySource(() -> {
    // Pre-materialize the outputstream before the source starts running
    Pair<OutputStream, Source<ByteString, NotUsed>> pair =
      StreamConverters.asOutputStream().preMaterialize(system);

    // Start writing into the download stream in a separate thread
    Futures.future(() -> { blobClient.download(pair.first()); return pair.first(); }, system.getDispatcher());

    // Return the source - it should start running since `lazySource` indicated demand
    return pair.second();
  })
);

sender().tell(new RequestResult(responseEntity, StatusCodes.OK), self());

ফ্যান্টাস্টিক। অনেক ধন্যবাদ. আপনার উদাহরণের জন্য একটি ছোট সম্পাদনা হ'ল: ফিউচার্স.ফিউচার (() -> {ব্লবক্লিয়েন্ট.ডাউনলোড (পেয়ার.ফার্স্ট ()); রিটার্ন পেয়ার.ফার্স্ট (); system, সিস্টেম.getDispatcher ());
MeBigFatGuy

@MeBigFatGuy ঠিক আছে, ধন্যবাদ!
এলেক

1

এক্ষেত্রে OutputStreamহ'ল "বস্তুগত মান" Sourceএবং এটি কেবল তখনই তৈরি হবে যখন স্ট্রিমটি চালানো হবে (বা "প্রবাহিত প্রবাহে" বস্তুগত ")। আপনি এটি Sourceআক্কা এইচটিটিপিকে হস্তান্তর করার পরে এটি চালানো আপনার নিয়ন্ত্রণের বাইরে চলে গেছে এবং এটি পরে আপনার উত্সটি চালাবে।

.mapMaterializedValue(matval -> ...)সাধারণত বস্তুগত মানটিকে রূপান্তর করতে ব্যবহৃত হয় তবে যেহেতু এটি বস্তুগতকরণের অংশ হিসাবে আহ্বান করা হয় আপনি এটি ব্যবহার করতে পারেন যেমন কোনও বার্তায় ম্যাচওয়াল প্রেরণের মতো পার্শ্ব প্রতিক্রিয়াগুলি যেমন আপনি খুঁজে বের করেছেন ঠিক তেমন কোনও অসুবিধে নেই with এমনকি যদি এটি মজার মনে হয়। এটি বোঝা গুরুত্বপূর্ণ যে স্ট্রিমটি তার বস্তুগতকরণটি সম্পূর্ণ করবে না এবং যতক্ষণ না সেই ল্যাম্বদা শেষ না হয় ততক্ষণ চলতে থাকবে না। এর অর্থ সমস্যাগুলি যদি download()কোনও ভিন্ন থ্রেডে কিছু কাজ বন্ধ করে দেওয়ার সাথে সাথে অবিলম্বে ফিরে আসার চেয়ে অবরুদ্ধ হয়।

তবে আরও একটি সমাধান রয়েছে: Source.preMaterialize()এটি উত্সকে রূপ দেয় এবং আপনাকে ইতিমধ্যে শুরু হওয়া উত্সটি গ্রাস করতে ব্যবহার করতে পারে এমন Pairএকটি বস্তুগত মান এবং একটি নতুন Sourceদেয়:

Pair<OutputStream, Source<ByteString, NotUsed>> pair = 
  StreamConverters.asOutputStream().preMaterialize(system);
OutputStream os = pair.first();
Source<ByteString, NotUsed> source = pair.second();

মনে রাখবেন যে আপনার কোডে ভাবার জন্য আরও কয়েকটি অতিরিক্ত বিষয় রয়েছে, সর্বাধিক গুরুত্বপূর্ণভাবে যদি blobClient.download(os)কলটি শেষ না হওয়া অবধি ব্লক হয়ে থাকে এবং আপনি অভিনেতার কাছ থেকে কল করেন, সেক্ষেত্রে আপনাকে অবশ্যই নিশ্চিত করতে হবে যে আপনার অভিনেতা প্রেরণকারীকে অনাহারে না থামায় এবং থামবে না কার্যকর করা থেকে আপনার অ্যাপ্লিকেশনটিতে অন্যান্য অভিনেতা (আক্কা ডক্স দেখুন: https://doc.akka.io/docs/akka/current/typed/dispatchers.html#blocking-needs- careful-management )।


1
উত্তরের জন্য ধন্যবাদ. আমি কীভাবে এটি সম্ভবত কাজ করতে পারে তা দেখছি না? যখন ব্লবক্লিয়েন্ট.ডাউনলোড (ওএস) বলা হয় তখন বাইটগুলি কোথায় যায় (যদি আমি নিজে এটি কল করছি)? ভাবুন এখানে একটি টেরাবাইট ডেটা লিখে বসে আছে waiting আমার কাছে মনে হচ্ছে যে blobClient.download কলটি প্রেরকের কাছ থেকে কল করা উচিত te কল কলটি যাতে এটি মূলত একটি IOUtils.copy- মত অপারেশন হয় .. প্রাক-ম্যাটারিয়ালাইজ ব্যবহার করে আমি দেখতে পাচ্ছি না কীভাবে ঘটে?
মেবিগফ্যাটগুয়ে

আউটপুট স্ট্রিমের একটি অভ্যন্তরীণ বাফার রয়েছে, যতক্ষণ না এটি বাফার পূর্ণ হয় ততক্ষণ এটি লেখাগুলি গ্রহণ করতে শুরু করবে, যদি অ্যাসিঙ্ক ডাউনস্ট্রিমটি ততক্ষণে উপাদানগুলি গ্রহণ করা শুরু না করে তবে এটি লেখার থ্রেডটি ব্লক করে দেবে (এ কারণেই আমি উল্লেখ করেছি যে ব্লকিং পরিচালনা করা গুরুত্বপূর্ণ)।
জোহানান্দ্রেন

1
তবে আমি যদি প্রাক-মেটেরিয়ালাইজ করি এবং আউটপুট স্ট্রিম পাই, তবে এটি আমার কোড যা ব্লবক্লিয়েন্ট.ডাউনলোড (ওএস) করছে; সঠিক? তার মানে আমি এগিয়ে যাওয়ার আগে এটি সম্পন্ন করতে হবে, যা অসম্ভব।
মেবিগফ্যাটগুয়ে

যদি ডাউনলোড (ওএস) কোনও থ্রেডের কাঁটাচামচ না করে, আপনাকে এটি ব্লক হয়ে যাওয়ার সাথে মোকাবেলা করতে হবে এবং এটি নিশ্চিত করতে হবে যে অন্য কোনও ক্রিয়াকলাপ বন্ধ হচ্ছে না। একটি উপায় হ'ল কাজটি করার জন্য একটি সুতোর কাঁটাচামচ করা, অন্যটি প্রথমে অভিনেতার কাছ থেকে প্রতিক্রিয়া জানাবে এবং তারপরে সেখানে ব্লকিংয়ের কাজটি করবে, সেক্ষেত্রে আপনাকে অবশ্যই নিশ্চিত করতে হবে যে অভিনেতা অন্যান্য অভিনেতা না খেয়ে না থাকে, লিঙ্কটি শেষে দেখুন আমার উত্তর.
জোহানান্দ্রেন

এই মুহুর্তে আমি এটিকে আদৌ কাজ করার চেষ্টা করছি get এটি একটি 10 ​​বাইট ফাইল প্রক্রিয়াও করতে পারে না।
মেবিগফ্যাটগুয়ে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.