2016-04-04 13 views
14

मेरे पास Gradle Shadow प्लगइन द्वारा उत्पन्न एक वसा/uber JAR है। मुझे अक्सर नेटवर्क पर वसा जेएआर भेजना पड़ता है और इसलिए, मेरे लिए सीसीए 40 एमबी डेटा के बजाय फाइल का केवल डेल्टा भेजने के लिए सुविधाजनक है। rsync इस उद्देश्य के लिए एक महान उपकरण है। हालांकि, मेरे स्रोत कोड में एक छोटा सा परिवर्तन अंतिम वसा जेएआर में एक बड़ा बदलाव होता है और इसके परिणामस्वरूप rsync जितना संभव हो उतना मदद नहीं कर रहा है।जार से rsyncable जार कैसे परिवर्तित करें?

क्या मैं वसा जेएआर को rsync- अनुकूल JAR में परिवर्तित कर सकता हूं?

एक समाधान/समाधान की मेरे विचार:

  • rsync पर भारी वजन रखो और यह किसी भी तरह बताते हैं कि यह एक संपीड़ित फ़ाइल के साथ काम करता (मैं किसी भी तरह से यह करने के लिए नहीं मिला)।
  • जार rsyncable करने के लिए गैर rsyncable जार कन्वर्ट
  • Gradle छाया बताएँ rsyncable जार (not possible at the moment)

संभवतः संबंधित प्रश्नों उत्पन्न करने के लिए:

+0

टिप्पणी करते हुए में मामला किसी के जवाब।मुझे यह भी पता होना चाहिए। –

+0

यह जेएआर को rsync के साथ अनपॅक करने और रिमोट मास्चिन पर फिर से ज़िप करने का विकल्प है? इस तरह rsync कम यातायात होने में सक्षम होना चाहिए। –

+0

अच्छा, यह एक विकल्प है। हालांकि मैं स्रोत मशीन पर सबकुछ तैयार करना पसंद करूंगा। मुझे लगता है, इस समाधान के लिए बहुत सारे अनावश्यक I/O डिस्क संचालन की भी आवश्यकता होगी। –

उत्तर

1

मैं build.gradle में अपने मूल विन्यास कोड की जगह:

jar { 
    manifest { 
     attributes(
       'Main-Class': 'com.my.project.Main', 
     ) 
    } 
} 

task fatJar(type: Jar) { 
    manifest.from jar.manifest 
    classifier = 'all' 
    from { 
     configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) } 
    } { 
     exclude "META-INF/*.SF" 
     exclude "META-INF/*.DSA" 
     exclude "META-INF/*.RSA" 
    } 
    with jar 
} 

(समाधान यहां पोस्ट https://stackoverflow.com/a/31426413/99256 का उपयोग करना) के साथ

shadowJar { 
    zip64 true 
    entryCompression = org.gradle.api.tasks.bundling.ZipEntryCompression.STORED 
    exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA' 
    manifest { 
     attributes 'Main-Class': 'com.my.project.Main' 
    } 
} 

अंतिम fatJar बहुत बड़ा है (यानी 56 एमबी) छाया छाया प्लगइन जो मेरे लिए उत्पादित (यानी 35 एमबी) से अधिक है। हालांकि, अंतिम जार (जब मैं अपने स्रोत कोड में एक छोटे से परिवर्तन, rsync स्थानान्तरण केवल एक डेटा की बहुत छोटी राशि बनाने) rsyncable हो रहा है।

कृपया ध्यान दें मैं Gradle के बहुत सीमित ज्ञान है कि इतने यह सिर्फ मेरी अवलोकन है और इसे आगे पर इसे सुधारने के लिए संभव हो सकता है।

+0

जोड़ा है यह संपीड़न बंद कर दिया है जो मैंने अपने उत्तर में किया था। दस्तावेज़ देखें इस पर ... org.gradle.api.tasks.bundling.ZipEntryCompression.STORED यहां https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/bundling/ZipEntryCompression.html#STORED – Harry

+0

@ हैरी यदि आप मेरे उत्तर (मेरे लिए परिप्रेक्ष्य के लिए एक समाधान) को एकीकृत करते हैं (इसे मेरे परिप्रेक्ष्य से पूर्ण उत्तर देने के लिए), तो मैं आपको खुशी से पुरस्कार दूंगा क्योंकि मुझे सामान्य रूप से आपका उत्तर पसंद है। –

+0

मैंने अभी इसे अपडेट किया है। क्या उससे मदद हुई। अगर आप उत्तर में कोई और बदलाव चाहते हैं तो बस मुझे बताएं। एक साइड नोट के रूप में यदि आप संपीड़न में रूचि रखते हैं तो हटर पुरस्कार http://prize.hutter1.net/ पर एक नज़र डालें। मैंने इसे कई महीनों तक संपीड़न के साथ गड़बड़ कर दिया जब मैंने इसे पाया। – Harry

2

जहाँ तक मुझे पता है, rsyncable gzip संकुचित डेटा के हर 8192 बाइट बाइट सीमाओं के लिए हफमैन पेड़ और पैडिंग को रीसेट करके काम करता है। यह संपीड़न पर लंबी दूरी के दुष्प्रभाव से बचाता है (rsync कम से कम बाइट गठबंधन होने पर स्थानांतरित डेटा ब्लॉक का ख्याल रखता है)

इस अर्थ में, छोटी फ़ाइलों वाली एक जार (8192 बाइट से कम) पहले से ही rsyncable है, क्योंकि प्रत्येक फ़ाइल अलग से संपीड़ित है। एक परीक्षण के रूप में आप यह जांचने के लिए जार के -0 विकल्प (कोई संपीड़न) का उपयोग कर सकते हैं कि यह rsync में मदद करता है, लेकिन मुझे लगता है कि यह नहीं होगा।

rsyncability आप (कम से कम) की जरूरत है सुधार करने के लिए:

  • यकीन है कि फ़ाइलें उसी क्रम में जमा हो जाती है सुनिश्चित करें।
  • सुनिश्चित करें कि अपरिवर्तित फ़ाइलों से जुड़े मेटा डेटा भी अपरिवर्तित हैं, क्योंकि प्रत्येक फ़ाइल में स्थानीय फ़ाइल शीर्षलेख होता है। उदाहरण के लिए अंतिम संशोधन समय .class फ़ाइलों के लिए समस्याग्रस्त है।
    मुझे जार के लिए निश्चित नहीं है, लेकिन ज़िप अतिरिक्त फ़ील्ड की अनुमति देता है, जिनमें से कुछ rsync मैचों को रोक सकते हैं, उदा। यूनिक्स एक्सटेंशन के लिए अंतिम acces समय।

संपादित करें:

FILENAME=SomeJar.jar 

rm -rf tempdir 
mkdir tempdir 

unzip ${FILENAME} -d tempdir/ 

cd tempdir 

# set the timestamp to 2000-01-01 00:00 
find . -print0 | xargs --null touch -t 200001010000 

# normalize file mode bits, maybe not necessary 
chmod -R u=rwX,go=rX . 

# sort and zip files, without extra 
find . -type f -print | sort | zip ../${FILENAME}_normalized -X [email protected] 

cd .. 
rm -rf tempdir 

rsync आँकड़े जब पहली जार/ज़िप में निहित फ़ाइल निकाल दिया जाता है:: मैं निम्न कमांड के साथ कुछ परीक्षण किया था

total: matches=1973 hash_hits=13362 false_alarms=0 data=357859 
sent 365,918 bytes received 12,919 bytes 252,558.00 bytes/sec 
total size is 4,572,187 speedup is 12.07 

जब पहली फ़ाइल हटा दिया गया है और प्रत्येक टाइमस्टैम्प संशोधित है:

total: matches=334 hash_hits=124326 false_alarms=4 data=3858763 
sent 3,861,473 bytes received 12,919 bytes 7,748,784.00 bytes/sec 
total size is 4,572,187 speedup is 1.18 

तो एक महत्वपूर्ण अंतर है, लेकिन जितना मैं उम्मीद करता हूं उतना नहीं।

यह भी लगता है कि फ़ाइल प्रकार के परिवर्तन से transfert को प्रभावित नहीं करता

+0

धन्यवाद। मुझे मूलभूत समझ है कि कैसे rsyncable दुर्भाग्यवश, यह वास्तव में मेरे प्रश्न का उत्तर नहीं दे रहा है क्योंकि आप यह नहीं कहते कि मैं आपके द्वारा प्रस्तावित किए जाने वाले कार्यों को कैसे कर सकता हूं। मैं आपके इनपुट की सराहना करता हूं। –

+0

सबसे सरल समाधान जो मैं सोच सकता हूं वह जार को अनपैक करना, टाइमस्टैम्प बदलना और मरम्मत करना है यह सॉर्ट किया गया। यह आपके द्वारा उपयोग किए जाने वाले ओएस पर निर्भर करता है, उदाहरण के लिए लिनक्स के लिए यह 'unzip', 'touch' और' ज़िप 'पर आधारित होगा। यह मुश्किल नहीं है लेकिन मुझे थोड़ा अजीब लगता है कि कोई भी निर्मित उपकरण नहीं है जो पहले से ही करता है कि – bwt

+0

@btw: मैं लिनक्स का उपयोग कर रहा हूं। क्या आप कृपया अपने दृष्टिकोण का एक कामकाजी उदाहरण दिखा सकते हैं? –

1

के एक कदम वापस ले चलते हैं (हो सकता है क्योंकि यह केंद्रीय निर्देशिका में संग्रहीत किया जाता है?); यदि आप बड़े जार नहीं बनाते हैं, तो यह एक समस्या बन जाती है।

तो, यदि आप अलग-अलग निर्भरता जार को अलग से तैनात करते हैं, और आप उन्हें एक वसा जार में जार नहीं करते हैं, तो आपने यहां समस्या का समाधान भी किया है।

कि ऐसा करने के लिए, मान लें कि आपके पास करते हैं:

  • /foo/yourapp.jar
  • /foo/lib/guava.jar
  • /foo/lib/h2.jar

Class-Path: lib/guava.jar lib/h2.jar 
0:

फिर, yourapp.jar की META-INF/MANIFEST.MF फ़ाइल में निम्न प्रविष्टि डाल

और अब आप केवल java -jar yourapp.jar चला सकते हैं और यह निर्भरता उठाकर काम करेगा। अब आप इन फ़ाइलों को व्यक्तिगत रूप से rsync के साथ स्थानांतरित कर सकते हैं; yourapp.jar बहुत छोटा होगा, और आपकी निर्भरता जार आमतौर पर नहीं बदलेगी, इसलिए उनको rsyncing जब अधिक समय नहीं लगेगा।

मुझे पता है कि यह सीधे पूछे जाने वाले प्रश्न का उत्तर नहीं देता है, लेकिन मैं इस सवाल के 9 0% + में शर्त लगाता हूं, वसा नहीं तो उचित जवाब है।

एनबी: चींटी, मेवेन, अमरूद, सही अभिव्यक्ति प्रविष्टि डालने का ख्याल रख सकते हैं। अगर आपके जार का इरादा इसे चलाने के लिए नहीं है, लेकिन, उदाहरण के लिए, यह एक वेब सर्वलेट कंटेनर के लिए एक युद्ध है , उनके पास अपने नियम हैं कि यह निर्दिष्ट करने के लिए कि आपकी निर्भरता जार कहाँ रहते हैं।

3

ऐसा करने के दो तरीके हैं जिनमें से दोनों संपीड़न को बंद करना शामिल हैं। Gradle पहले तो जार पद्धति का उपयोग करके इसे बंद ...

आप इस Gradle का उपयोग कर सकते

jar { 
    manifest { 
     attributes(
       'Main-Class': 'com.my.project.Main', 
     ) 
    } 
} 

task fatJar(type: Jar) { 
    manifest.from jar.manifest 
    classifier = 'all' 
    from { 
     configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) } 
    } { 
     exclude "META-INF/*.SF" 
     exclude "META-INF/*.DSA" 
     exclude "META-INF/*.RSA" 
    } 
    with jar 
} 

मुख्य बात के साथ

shadowJar { 
    zip64 true 
    entryCompression = org.gradle.api.tasks.bundling.ZipEntryCompression.STORED 
    exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA' 
    manifest { 
     attributes 'Main-Class': 'com.my.project.Main' 
    } 
} 

(इस जवाब वास्तव में ओपी से आया) यहाँ कि संपीड़न बंद कर दिया गया है यानी

org.gradle.api.tasks.bundling.ZipEntryCompression.STORED 

आप डॉक्स यहां पा सकते हैं

https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/bundling/ZipEntryCompression.html#STORED

हाँ आप इसे एक नया संग्रह पर के बारे में 40% की तेजी लाने के कर सकते हैं और एक जार पर 200 से अधिक% से संग्रहित आप पहले से ही rsync'd गए हैं। यह चाल जार को को संपीड़ित नहीं करना है, आप rsyncs chunking एल्गोरिदम का लाभ उठा सकते हैं।

मैं निम्न कमांड का इस्तेमाल किया वर्ग फ़ाइलों का एक बहुत कुछ के साथ एक निर्देशिका संपीड़ित करने के लिए ...

jar cf0 uncompressed.jar . 
jar cf compressed.jar . 

यह निम्न दो जार बनाया ...

-rw-r--r-- 1 rsync jar 28331212 Apr 13 14:11 ./compressed.jar 
-rw-r--r-- 1 rsync jar 38746054 Apr 13 14:10 ./uncompressed.jar 

ध्यान दें कि असंपीड़ित जार का आकार लगभग 10 एमबी बड़ा है।

मैं तो इन फ़ाइलों rsync'd और निम्न कमांड का प्रयोग उन्हें समय समाप्त हुआ। (नोट, संपीड़ित फ़ाइल के लिए संपीड़न को चालू करने पर भी थोड़ा प्रभाव पड़ा, मैं बाद में समझाऊंगा)।

संपीडित जार

time rsync -av -e ssh compressed.jar [email protected]:/tmp/ 

building file list ... done 
compressed.jar 

sent 28334806 bytes received 42 bytes 2982615.58 bytes/sec 
total size is 28331212 speedup is 1.00 

real 0m9.208s 
user 0m0.248s 
sys 0m0.483s 

असम्पीडित जार

time rsync -avz -e ssh uncompressed.jar [email protected]:/tmp/ 

building file list ... done 
uncompressed.jar 

sent 11751973 bytes received 42 bytes 2136730.00 bytes/sec 
total size is 38746054 speedup is 3.30 

real 0m5.145s 
user 0m1.444s 
sys 0m0.219s 

हम लगभग 50% की एक speedup प्राप्त की है। यह कम से कम rsync को गति और हम एक अच्छा बढ़ावा लेकिन क्या बाद में rsyncs जहां एक छोटा सा परिवर्तन किया गया है के बारे में मिलता है।

मैं निर्देशिका कि निर्मित आकार में 170 बाइट था जार घास काटना वे इस आकार के होते हैं से एक वर्ग फ़ाइल हटाया ..

-rw-r--r-- 1 rsycn jar 28330943 Apr 13 14:30 compressed.jar 
-rw-r--r-- 1 rsync jar 38745784 Apr 13 14:30 uncompressed.jar 

अब समय बहुत अलग हैं।

संपीडित जार

building file list ... done 
compressed.jar 

sent 12166657 bytes received 31998 bytes 2217937.27 bytes/sec 
total size is 28330943 speedup is 2.32 

real 0m5.435s 
user 0m0.378s 
sys 0m0.335s 

असम्पीडित जार

building file list ... done 
uncompressed.jar 

sent 220163 bytes received 43624 bytes 175858.00 bytes/sec 
total size is 38745784 speedup is 146.88 

real 0m1.533s 
user 0m0.363s 
sys 0m0.047s 

तो हम बड़े जार rsyncing में तेजी लाने के कर सकते हैं इस पद्धति का उपयोग एक बहुत फ़ाइलें। इसका कारण सूचना सिद्धांत से संबंधित है। जब आप डेटा को संपीड़ित करते हैं तो यह डेटा से आम बातों को हटा देता है यानी जो आपको छोड़ा जाता है, वह यादृच्छिक डेटा की तरह दिखता है, सर्वोत्तम कंप्रेसर इस जानकारी को और अधिक हटा देते हैं। किसी भी डेटा और अधिकांश संपीड़न एल्गोरिदम में एक छोटा सा परिवर्तन डेटा के आउटपुट पर नाटकीय प्रभाव डालता है।

पिन एल्गोरिथ्म प्रभावी रूप से चेकसम कि सर्वर और ग्राहक के बीच एक ही हैं खोजने के लिए rsync के लिए यह कठिन बना रही है और इस लिए इसे और अधिक डेटा स्थानांतरित करने की जरूरत है का मतलब है। जब आप इसे असम्पीडित करते हैं तो आप rsync को जो कुछ भी अच्छा करते हैं, उसे दो फाइलों को सिंक करने के लिए कम डेटा भेजते हैं।

संबंधित मुद्दे