אצווה אביבית באמצעות מחיצה

1. סקירה כללית

בהקדמה הקודמת שלנו ל- Spring Batch, הצגנו את המסגרת ככלי לעיבוד אצווה. בדקנו גם את פרטי התצורה וההטמעה לביצוע עבודת חוט בודדת בתהליך יחיד.

כדי ליישם עבודה עם עיבוד מקביל כלשהו, ​​ניתנות מגוון אפשרויות. ברמה גבוהה יותר, ישנם שני מצבים של עיבוד מקביל:

  1. תהליך יחיד, רב-הברגה
  2. ריבוי תהליכים

במאמר מהיר זה נדון בחלוקה של שלב, שניתן ליישם הן עבור עבודות בודדות והן עבור עבודות מרובות תהליכים.

2. מחיצת שלב

באביב אצווה עם חלוקה מספק לנו את המתקן לחלק את הביצוע של א שלב:

סקירת מחיצות

התמונה לעיל מציגה יישום של א עבודה עם מחיצה שלב.

יש שלב נקרא "מאסטר", שהביצוע שלו מחולק לכמה שלבי "עבד". עבדים אלה יכולים לתפוס את מקומו של אדון, והתוצאה עדיין תהיה ללא שינוי. שניהם אדונים ועבדים הם מקרים של שלב. עבדים יכולים להיות שירותים מרוחקים או סתם אשכולות מקומיים.

במידת הצורך נוכל להעביר נתונים מהמאסטר לעבד. נתוני המטא (כלומר JobRepository), מוודא שכל עבד מוצא להורג פעם אחת בלבד בביצוע יחיד של עבודה.

להלן תרשים הרצף המראה כיצד הכל עובד:

שלב מחיצה

כפי שמוצג, PartitionStep מניע את ההוצאה להורג. ה PartitionHandler אחראי על פיצול עבודתו של "המאסטר" ל"עבדים ". הכי נכון שלב הוא העבד.

3. POM של Maven

התלות של Maven זהה לאזכור במאמר הקודם שלנו. כלומר, Spring Core, Spring Batch והתלות במסד הנתונים (במקרה שלנו, SQLite).

4. תצורה

במאמר ההיכרות שלנו ראינו דוגמה להמרת נתונים כספיים מקובץ CSV לקובץ XML. בואו נרחיב את אותה דוגמא.

כאן, אנו להמיר את המידע הכספי מחמישה קבצי CSV לקבצי XML תואמים, באמצעות יישום רב-שרשור.

אנו יכולים להשיג זאת באמצעות יחיד עבודה ו שלב מחיצה. יהיו לנו חמישה שרשורים, אחד לכל אחד מקבצי ה- CSV.

קודם כל, בואו ניצור עבודה:

@Bean (name = "partitionerJob") Job partitionerJob () זורק את UnexpectedInputException, MalformedURLException, ParseException {return jobs.get ("partitioningJob") .start (partitionStep ()) .build (); }

כפי שאנו רואים, זה עבודה מתחיל עם מחיצה שלב. זהו צעד האב שלנו אשר יחולק לשלבי עבדים שונים:

@Bean Step Step partitionStep () זורק את UnexpectedInputException, MalformedURLException, ParseException {return steps.get ("partitionStep"). Partitioner ("slaveStep", partitioner ()) .step (slaveStep ()) .taskExecutor (taskExecutor (). (); }

הנה, ניצור את מחיצות שלב באמצעות StepBuilderFactory. לשם כך, עלינו למסור את המידע אודות SlaveSteps וה מחיצה.

ה מחיצה הוא ממשק המספק את האפשרות להגדיר קבוצה של ערכי קלט לכל אחד מהעבדים. במילים אחרות, ההיגיון לחלק משימות לשרשורים בהתאמה הולך כאן.

בוא ניצור יישום של זה, שנקרא CustomMultiResourcePartitioner, שם נכניס את שמות קבצי הקלט והפלט אל ה- ExecutionContext להעביר לכל צעד עבד:

מחלקה ציבורית CustomMultiResourcePartitioner מיישם את המחיצה {@ מחיצת מפה ציבורית ציבורית (int gridSize) {מפה מפה = HashMap חדש (gridSize); int i = 0, k = 1; עבור (משאב משאב: משאבים) {ExecutionContext context = ExecutionContext חדש (); Assert.state (resource.exists (), "המשאב לא קיים:" + resource); context.putString (keyName, resource.getFilename ()); context.putString ("opFileName", "פלט" + k +++ ". xml"); map.put (PARTITION_KEY + i, הקשר); i ++; } מפה חזרה; }}

אנו ניצור גם את השעועית למחלקה זו, בה אנו נותנים את ספריית המקור לקבצי קלט:

@Bean מחיצת CustomMultiResourcePartitioner הציבורית () {CustomMultiResourcePartitioner מחיצה = חדש CustomMultiResourcePartitioner (); משאבי משאבים []; נסה את {resources = resoursePatternResolver .getResources ("file: src / main / resources / input / *. csv"); } לתפוס (IOException e) {לזרוק RuntimeException חדש ("בעיות קלט / פלט בעת פתרון" + "תבנית קובץ הקלט.", e); } partitioner.setResources (משאבים); מחיצה מחזירה; }

נגדיר את שלב העבדים, בדיוק כמו כל צעד אחר עם הקורא והכותב. הקורא והכותב יהיו זהים כפי שראינו בדוגמת ההיכרות שלנו, אלא שהם יקבלו את פרמטר שם הקובץ מה- StepExecutionContext.

שים לב כי השעועית הזו צריכה להיות ממושכת, כך שהם יוכלו לקבל את stepExecutionContext פאראמים, בכל צעד ושעל. אם הם לא יהיו בהיקף צעדים, השעועית שלהם תיווצר בתחילה ולא תקבל את שמות הקבצים ברמת שלב:

@StepScope @Bean FlatFileItemReader publicReader (@Value ("# {stepExecutionContext [fileName]}") שם קובץ מחרוזת) זורק UnexpectedInputException, ParseException {FlatFileItemReader reader = FlatFileItemReader חדש (); DelimitedLineTokenizer tokenizer = DelimitedLineTokenizer חדש (); מחרוזת [] אסימונים = {"שם משתמש", "userid", "transactiondate", "סכום"}; tokenizer.setNames (אסימונים); reader.setResource (ClassPathResource חדש ("קלט /" + שם קובץ)); DefaultLineMapper lineMapper = חדש DefaultLineMapper (); lineMapper.setLineTokenizer (tokenizer); lineMapper.setFieldSetMapper (RecordFieldSetMapper חדש ()); reader.setLinesToSkip (1); reader.setLineMapper (lineMapper); קורא חוזר; } 
@Bean @StepScope itemWriter ציבורי itemWriter (Marshaller marshaller, @Value ("# {stepExecutionContext [opFileName]}") שם קובץ מחרוזת) זורק MalformedURLException {StaxEventItemWriter itemWriter = StaxEventItemWriter חדש); itemWriter.setMarshaller (marshaller); itemWriter.setRootTagName ("transactionRecord"); itemWriter.setResource (ClassPathResource חדש ("xml /" + שם קובץ)); פריט להחזיר }

תוך כדי אזכור הקורא והכותב בשלב העבד, נוכל להעביר את הטיעונים כבטלים, מכיוון שלא ישתמשו בשמות קבצים אלה מכיוון שהם יקבלו את שמות הקבצים stepExecutionContext:

@Bean הצעד הציבורי slaveStep () זורק UnexpectedInputException, MalformedURLException, ParseException {צעדים להחזיר. Get ("slaveStep"). נתח (1) .reader (itemReader (null)) .writer (itemWriter (marshaller (), null)). (); }

5. מסקנה

במדריך זה דנו כיצד ליישם עבודה עם עיבוד מקביל באמצעות Spring Batch.

כמו תמיד, היישום המלא של דוגמה זו זמין ב- GitHub.


$config[zx-auto] not found$config[zx-overlay] not found