ป้ายกำกับ

วันพุธที่ 30 เมษายน พ.ศ. 2557

Ubuntu 14.04 LTS: ปัญหา Subversion Server ทำงานไม่เสถียร

วันก่อนผมได้เล่าให้เพื่อนๆฟังไปแล้ว เกี่ยวกับปัญหาการใช้งาน Subversion บน Eclipse ซึ่งเมื่อผมทำการ Checkout โปรเจ็คออกมา บางโปรเจ็คก็ไม่มีปัญหาอะไร แต่บางโปรเจ็คก็เกิดอาการดาวโหลดบางไฟล์ไม่ได้ โดยฟ้อง
RA layer request failed
GET ... Internal Server Error

เกี่ยวอะไรกับ MySQL?

ทีแรกนึกว่ามีบางไฟล์เสียหาย แต่เมื่อผมทดลองซ้ำๆหลายๆรอบ ดูเหมือนว่าอาการจะไม่แน่นอน ไม่ซ้ำไฟล์เดิม และบางครั้ง Error ก็เปลี่ยนไปเป็น server close connection ผมจึงคิดว่าปัญหามันน่าจะเกิดที่ Apache Web Server มากกว่า โดยเมื่อเข้าไปดู Log ไฟล์ ก็แทบจะไม่มีอะไรบอกเกี่ยวกับ svn เลย แต่กลับมีข้อความเกี่ยวกับ MySQL เช่น query ไม่ได้ database connection lost อะไรทำนองนั้น ทีแรกผมก็ไม่ได้เอะใจ เพราะคิดว่าไม่เกี่ยวข้องกับ Subversion สักหน่อย แต่ทำไมมันดูเหมือนจะเกี่ยวกัน เพราะฟ้อง warning ตรงตอน GET ไฟล์ แต่เอาเถอะโปรแกรมรุ่นใหม่อาจจะมีการเปลี่ยนไปใช้ฐานข้อมูล MySQL ร่วมด้วยก็ได้ ผมก็เลยพุ่งเป้าไปที่ MySQL

ทีแรกก็ลองปรับค่า max_allowed_packet จาก 16M เป็น 64M ค่า max_connection จาก 100 เป็น 200 ค่า query_cache_limit จาก 1M เป็น 16M ด้วยเหตุผลที่ว่า อาการคล้ายๆกับ MySQL ทำงานไม่ได้ อาจจะเพราะตอน Checkout ไฟล์จำนวนมากๆ เกิด connection จำนวนมาก (ถ้าเป็น 1 ไฟล์ต่อ 1 connection) ก็จะเกิดปัญหาประมาณนี้ ซึ่งก็ช่วยให้สามารถ Checkout ไฟล์ได้มากขึ้น แต่สุดท้ายก็ตายทุกครั้ง

ผมเข้าไปดูค่าใน /var/log/mysql/error.log แล้ว ก็ไม่พบความผิดปกติอะไรเลย ดูเหมือน MySQL จะทำงานได้เป็นปกติดีทุกประการ ผมก็คิดไม่ออกว่ามันเกิดอะไรขึ้น และคิดว่า มันต้องมีปัญหาที่คำสั่ง SQL เพราะ error ใน Apache Web Server ระบุว่า query ไม่ได้ บางครั้งมีคำว่า "SELECSELECT ..." เหมือนคำสั่งมันกลายเป็นขยะไป ทำให้ระบบรวนไปหมด ผมจึงต้องลงลึกเข้าไปในระดับทุกๆคำสั่งที่ส่งให้กับ MySQL เลยว่ามีปัญหาอะไร ผมจึงไปตั้งค่า general_log_file และ general_log (ปกติจะปิดไว้) เพื่อดูค่าการทำงานในแต่ละคำสั่งของ MySQL ซึ่งจะบันทึกไว้ที่ /var/log/mysql/mysql.log (ปกติจะไม่มีไฟล์นี้อยู่)

สุดท้ายผมก็เห็นคำสั่ง
SELECT xxx FROM profiles WHERE login_name=? AND disabledtext = ''
ก็ได้ถึงบางอ้อว่า จริงๆแล้ว คำสั่งนี้เป็นคำสั่งที่เกิดจาก Apache Module ที่มีชื่อว่า mod_auth_mysql เป็นโมดูลที่เกี่ยวกับ การ Authentication เข้าใช้งาน และ Authorization สำหรับยืนยันสิทธิ์ในการเข้าถึงไฟล์ต่างๆของ Subversion  ซึ่งผมเลือกใช้โมดูลนี้เพื่อตั้งค่าให้มีการใช้ account จากฐานข้อมูล MySQL ของ Bugzilla ดังนั้น ทุกๆครั้งที่มีการดาวโหลดไฟล์ จะมีการตรวจสอบสิทธิ์ทุกครั้ง และทำให้เกิดการ query ด้วยคำสั่งข้างบนซ้ำๆจำนวนมาก อาจจะทำให้เกิดอาการไม่เสถียร

Multi-Processing Module (MPM) Prefork vs. Worker

เมื่อรู้ว่าปัญหาเกิดจากโมดูล mod_auth_mysql ทำงานไม่เสถียรแล้ว ผมจึงคิดว่าน่าจะต้องปรับค่าที่เกี่ยวกับการจัดการประมวลผลโมดูล หรือที่เรียกว่า MPM ซึ่งเมื่อตรวจสอบ Apache Web Server ก็พบว่า มีการตั้งค่าแตกต่างไปจากรุ่นก่อน (Ubuntu 12.04) คือ การแยก MPM ออกเป็นโมดูล และเลือกตั้งค่าไว้เป็น mpm_event ในขณะที่ค่าเก่าที่ผมเคยตั้งไว้เป็น mpm_prefork ผมเองก็จำไม่ได้แล้วว่าทำไมถึงใช้ prefork แต่ไหนๆก็ไหนๆแล้ว ผมก็เลยทดลองปรับค่าดู ซึ่งค่าเดิมที่ตั้งไว้คือ default ตามข้างล่างนี้
<IfModule mpm_event_module>
    StartServers                    2
    MinSpareThreads          25
    MaxSpareThreads         75
    ThreadLimit                   64
    ThreadsPerChild            25
    MaxClients                   150
    MaxRequestsPerChild      0
</IfModule>
เมื่อทดลองปรับค่า เช่น MaxClient ลดให้น้อยลง MaxRequestsPerChild กำหนดให้เป็นค่า 1000 แทนที่จะเป็น 0 ซึ่งหมายถึงไม่จำกัด ค่า MaxSpareThreads ลดลง ค่า ThreadLimit ลดลง ThreadsPerChild ลดลง ผลปรากฏว่า เมื่อ Checkout การทำงานค่อนข้างดีขึ้น แต่สุดท้ายแล้วก็นิ่งไปนาน แล้วเกิด connection timeout ขี้น เมื่อดูใน Log ไฟล์ ไม่มีข้อมูลใดๆ เพราะ Apache Web Server ตายไปเรียบร้อยแล้ว ผมก็พยายามทดลองปรับค่าต่างๆแล้ว สุดท้ายสรุปว่าโมดูล mod_auth_mysql ไม่ใช่ thread safe โมดูล (ในขณะที่ข้อมูลจากบางเว็บไซต์ระบุว่าเป็น thread safe) ไม่สามารถใช้งานกับ mpm_worker หรือ mpm_event ได้

prefork เป็นการประมวลผลแบบไม่ใช้ thread โดย root process จะมีการแตก child process ออกมา และแต่ละ child process จะดูแล connection หลาย connection ต่อ process

worker เป็นการประมวลผลแบบใช้ thread โดย root process จะมีการแตก child process ออกมา และแต่ละ child process จะแตก thread ออกมาเพื่อดูแลแต่ละ connection

prefork เหมาะกับการทำงานที่รองรับโมดูลที่ไม่ได้ออกแบบมาให้เป็น thread safe และสำหรับประสิทธิภาพแล้ว ทั้ง prefork และ worker ทำงานได้พอๆกัน แต่ prefork จะใช้ทรัพยากรณ์ หน่วยความจำมากกว่า worker ส่วน event นั้นเป็น worker อีกรูปแบบหนึ่งที่จะจัดการ thread ได้ดีขึ้น

สรุปว่า mod_auth_mysql ไม่เป็น thread safe ต้องใช้กับ prefork เท่านั้น ซึ่งเมื่อผมทดลองปรับไปใช้ prefork ปัญหาทุกอย่างก็หมดไป นิ่งเสถียรดีมาก แต่ด้วยความคิดที่ว่า event มันดูดีกว่า prefork นะ ใช้ทรัพยากรณ์น้อยกว่า ผมจึงคิดว่า เราน่าจะหาทางใช้ event นะ

Apache DBD Module

ผมค้นไปค้นมาก็พบว่า Apache มีโมดูลที่ทำงานกับฐานข้อมูล SQL อยู่แล้ว ชื่อว่า mod_dbd ดังรายละเอียดในหน้า Apache DBD API ที่น่าสนใจคือ
  1. ไม่ยึดติดกับฐานข้อมูลใดๆ โดยจะต้องติดตั้ง driver สำหรับแต่ละฐานข้อมูลเพิ่ม เช่นฐานข้อมูลที่มี driver แล้วคือ MSSQL, SyBase, MySQL, Oracle, PostgreSQL, SQLite, และ ODBC
  2. ใช้กับ MPM ได้หลายแบบทั้งแบบ threaded หรือ non-threaded
  3. จัดการ connection pooling แบบไดนามิกส์เพื่อรองรับโปรแกรมใหญ่ๆได้
และนอกจากนี้ยังมีโมดูล mod_authn_dbd สำหรับการทำ Authentication และโมดูล mod_authz_dbd สำหรับการทำ Authorization ด้วย ทำให้ตอบโจทย์ที่ผมคิดไว้พอดี ผมจึงตัดสินใจทดสอบการใช้งานดู โดยติดตั้งโมดูลต่างๆ และแก้ไข config ไฟล์ ตามตัวอย่างใน document ของ mod_authn_dbd ดังนี้
# mod_dbd configuration
# UPDATED to include authentication cacheing
DBDriver pgsql
DBDParams "dbname=apacheauth user=apache password=xxxxxx"
DBDMin  4
DBDKeep 8
DBDMax  20
DBDExptime 300
<Directory /usr/www/myhost/private>
  # mod_authn_core and mod_auth_basic configuration
  # for mod_authn_dbd
  AuthType Basic
  AuthName "My Server"
  # To cache credentials, put socache ahead of dbd here
  AuthBasicProvider socache dbd
  # Also required for caching: tell the cache to cache dbd lookups!
  AuthnCacheProvideFor dbd
  AuthnCacheContext my-server
  # mod_authz_core configuration
  Require valid-user
  # mod_authn_dbd SQL query to authenticate a user
  AuthDBDUserPWQuery "SELECT password FROM authn WHERE user = %s"
</Directory>
ในตัวอย่างนี้ จะมีการใช้ AuthBasicProvider โดยเน้นว่าให้ใช้ socache เพื่อทำ cache ให้กับ credential ด้วย ผมก็ได้ทำตามคือ ติดตั้ง socache เพิ่ม และที่สำคัญคือ AuthDBUserPWQuery ที่ต้องสั่ง query รหัสผ่านสำหรับผู้ใช้มาเพื่อตรวจสอบ โดยใส่ %s ไว้ตรงที่เป็นชื่อผู้ใช้ที่จะกรอกผ่าน browser มา ผลการรันปรากฏว่าเกิด Segmentation fault error ครับ Apache สตาร์ทไม่ขึ้น ผมจึงค่อยๆถอดบางคำสั่งที่ไม่จำเป็นออก และสุดท้ายพบว่าปัญหาอยู่ที่ AuthnCacheProvideFor และ AuthnCacheContext ครับ เมื่อตัดสองคำสั่งนี้ออก Apache ก็ทำงานได้ตามปกติ

Password Format

จากคำอธิบายของคำสั่ง AuthDBUserPWQuery ระบุว่า ผลของการ query จะนำเอาเฉพาะข้อความที่อยู่ใน row แรก column แรกเท่านั้นมาพิจารณาเป็นรหัสผ่านในรูปแบบรหัสที่เข้ารหัสแล้ว ซึ่งวิธีพิจารณามีสองแบบคือ แบบ Basic หรือ แบบ Digest ตามที่ได้ระบุ provider ไว้ (ผมขอไม่พูดถึงแบบ Digest นะครับ) เช่นในกรณีนี้ ผมใช้ AuthBasicProvider มีรายละเอียดรูปแบบของข้อมูลรหัสที่จะนำมาเปรียบเทียบตามที่ระบุไว้ชัดเจนในเอกสารคู่มือของ Apache เรื่อง Password Format โดยแบบ Basic มีอยู่ 5 รูปแบบคือ
  1. bcrypt: ข้อความ "$2y$" + ข้อความที่เข้ารหัสด้วยอัลกอริทึม crypt_blowfish
  2. MD5: ข้อความ "$apr1$" + ข้อความที่เข้ารหัสด้วยอัลกอริทึม MD5 ในแบบของ Apache เอง (ไม่เหมือนกับ MD5 อื่นๆ ผมเสียเวลาเข้าใจผิดทดสอบอยู่นานเหมือนกัน)
  3. SHA1: ข้อความ "{SHA}" + ข้อความที่เข้ารหัสด้วย Base64 ของอัลกอริทึม SHA-1 (ไม่ปลอดภัย)
  4. CRYPT: ข้อความที่เข้ารหัสด้วยฟังก์ชัน crypt บนระบบ Unix เท่านั้น (ไม่ปลอดภัย)
  5. PLAIN: ข้อความที่ไม่เข้ารหัส เฉพาะบนระบบ Windows และ Netware (ไม่ปลอดภัย)
อ๊ะๆ สังเกตเห็นอะไรไหมครับ รหัสผ่านที่เข้ารหัสแล้ว จะมีการใส่สัญลักษณ์พิเศษไว้เพื่อให้รู้ว่าเข้ารหัสด้วยวิธีไหน แต่ไม่ต้องกังวลนะครับ อัลกอริทึมที่เข้ารหัสพวกนี้ เป็นอัลกอริทึมที่ออกแบบมาให้ย้อนกลับได้ยาก ทางเดียวที่ง่ายกว่าคือ ต้องหารหัสมาเข้ารหัสด้วยวิธีเดียวกันแล้วได้ค่าที่ตรงกันจึงจะบอกได้ว่าเป็นรหัสที่ถูกต้อง ใครสนใจเรื่องรูปแบบของรหัสสามารถอ่านเพิ่มเติมจากลิ้งค์ที่ให้ไว้ได้นะครับ ในนั้นมีการแนะนำการใช้คำสั่ง htpasswd และคำสั่ง openssl เพื่อทดสอบดูว่า รหัสที่เข้าด้วยอัลกอริทึมแบบต่างๆแล้วได้รูปแบบเป็นอย่างไร

กลับมาเข้าเรื่องปัญหาของผมต่อนะครับ จากฐานข้อมูลผู้ใช้ใน MySQL ของ Bugzilla รหัสผ่านที่เข้ารหัสไว้แล้วนั้น มีรูปแบบไม่เหมือนกับที่ Apache ระบุไว้ ดังนั้น คำสั่งที่จะ query รหัสผ่านมานั้น จะต้องมีการจัดรูปแบบใหม่ให้ถูกต้อง โดยรูปแบบของ Bugzilla จะอยู่ในแบบ
รหัสที่เข้ารหัสแล้ว + "{" + ชื่อ Digest อัลกอริทึม + "}"
เช่น (ขอสมมติรหัสนะครับ)
123456789ABCDEFGHIjklmnopqrstuvwxyZ{MD5}
ถ้าหากผม query มาตรงๆ ก็จะทำให้ mod_authn_dbd ตรวจสอบรหัสผ่านไม่ถูก เพราะถ้าเป็น MD5 จะต้องมีรหัสเป็นประมาณ
$apr1$123456789ABCDEFGHIjklmnopqrstuvwxyZ
ซึ่งก็ไม่ใช่เรื่องยากสักเท่าไรนักที่จะใช้คำสั่ง substring ของ SQL ตัดและต่อคำเข้าไป แต่ปัญหาใหญ่ของผมตอนนี้คือ รหัส MD5 แบบทั่วไปที่ใช้อยู่ใน Bugzilla ซึ่งเขียนด้วยภาษา perl โดยใช้ Digest::MD5 นั้นไม่เหมือนกับ Apache MD5 หรือที่เรียกว่า APR1 ทำให้ผมต้องไปควานหาว่า perl มีอัลกอริทึมเข้ารหัสแบบไหนให้ใช้บ้าง ซึ่งถ้าเป็นไปตาม man page ของ Digest ก็คือมีดังนี้ (เรียงตามลำดับความเร็ว)
Algorithm   Size  Implementation               MB/s
MD4         128   Digest::MD4 v1.3            165.0
MD5         128   Digest::MD5 v2.33            98.8
SHA-256     256   Digest::SHA2 v1.1.0          66.7
SHA-1       160   Digest::SHA v4.3.1           58.9
SHA-1       160   Digest::SHA1 v2.10           48.8
SHA-256     256   Digest::SHA v4.3.1           41.3
Haval-256   256   Digest::Haval256 v1.0.4      39.8
SHA-384     384   Digest::SHA2 v1.1.0          19.6
SHA-512     512   Digest::SHA2 v1.1.0          19.3
SHA-384     384   Digest::SHA v4.3.1           19.2
SHA-512     512   Digest::SHA v4.3.1           19.2
Whirlpool   512   Digest::Whirlpool v1.0.2     13.0
MD2         128   Digest::MD2 v2.03             9.5
Adler-32     32   Digest::Adler32 v0.03         1.3
CRC-16       16   Digest::CRC v0.05             1.1
CRC-32       32   Digest::CRC v0.05             1.1
MD5         128   Digest::Perl::MD5 v1.5        1.0
CRC-CCITT    16   Digest::CRC v0.05             0.8
ผมควานหา package อื่นๆที่เกี่ยวข้องหมดแล้วพบคำสั่งเข้ารหัส Apache MD5 อยู่ใน libcrypt-passwdmd5-perl แต่นั่นเป็น Crypt::PasswdMD5 ไม่ใช่ Digest ซึี่งหากจะใช้คำสั่งนี้ ผมจะต้องเข้าไปแก้ Bugzilla ซึ่งเป็นวิธีที่ไม่น่าทำสักเท่าไรนัก (แต่จริงๆแล้วก็อยากจะลองดูเหมือนกันนะ ☺) จึงต้องตัดสินใจลดระดับความปลอดภัยลงมาเป็น SHA-1

สรุป

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

วันจันทร์ที่ 28 เมษายน พ.ศ. 2557

Ubuntu 14.04 LTS: ปัญหา Subversion บน Eclipse 3.8

หลังจากที่ผมติดตั้ง Ubuntu 14.04 LTS ไปประมาณหนึ่งสัปดาห์ ตอนนี้ก็ได้ฤกษ์ใช้งาน Eclipse เขียนโปรแกรมสักที และเนื่องจากโปรแกรมหลายๆตัวที่ผมเขียน ผมใช้ Subversion เก็บซอสโค้ดไว้ จึงทำการ Import โปรแกรมมา แต่ปรากฏว่าเกิดปัญหาขึ้น 2 เรื่อง

ปัญหาที่ 1 SVN มี 2 เมนู

เมื่อเลือกเมนู File/Import จะปรากฏหน้าต่าง ซึ่งปกติแล้ว เราก็จะเลือกหัวข้อย่อย SVN โดยจะมีหัวข้อ Checkout Projects from SVN ดังภาพ (ขออภัยที่ผมลืมเก็บภาพตอนที่มี 2 หัวข้อ) แต่ปรากฏว่ามี SVN อีกอันหนึ่ง มีหัวข้อย่อยคล้ายๆกัน ผมก็เกิดความสงสัยขึ้น แอ๊ะเกิดอะไรขึ้นกับ Eclipse และเมื่อเปิดไปที่เมนู Window/Preferences/Team เพื่อดูการตั้งค่าของ Subversion ก็ปรากฏว่า มีหัวข้อ SVN อยู่ 2 หัวข้อเช่นกัน

หลังจากที่ตรวจสอบ Plug-In ต่างๆที่ติดตั้ง (เลือกลิ้งค์ Uninstall or update ที่เมนู Window/Preferences/Install/Update) ก็ได้ข้อสรุปว่า ผมติดตั้ง Eclipse Team Provider สำหรับ Subversion ไปสองตัวคือ Subversive และ Subclipse ซึ่งปกติแล้ว ผมจะใช้ Subversive อยู่เป็นประจำ เพราะมี Connector หลายแบบให้เลือกใช้ แต่เอ Subclipse มันมาได้ไง? เราเผลอไปติดตั้งตอนไหนนะ? จะเอาออกดีหรือเปล่า? เพื่อให้มั่นใจ ผมจึงศึกษาข้อมูลดูจาก StackOverflow และพบว่า เขาแนะนำให้ใช้ Subclipse ดีกว่า เพราะทีมพัฒนา(มาตอบเอง) บอกว่า ทีมงานเขา Active กว่า Subversive ที่มีผู้พัฒนาอยู่น้อย และยังติดวงเล็บต่อท้ายว่า Incubation ตั้งนานแล้ว นอกจากนี้ เขายังทำงานร่วมกับทีมที่พัฒนา Subversion บนระบบอื่นๆ เช่น AnkhSVN และ TortoiseSVN อย่างไกล้ชิด เพื่อให้สามารถทำงานเข้ากันได้

โอเคครับ ผมก็เลยตัดสินใจ ถอน Subversive ออก แต่ตอนที่ถอนออก เราจะต้องไล่ถอน Plug-In ต่างๆที่เกี่ยวข้องออกให้หมดนะครับ ไม่อย่างนั้นแล้ว เมนู SVN ของ Subversive จะยังคงปรากฏให้เห็นอยู่ อาจจะทำให้เกิดความสับสนในการใช้งานได้ เพราะมันจะคล้ายๆกัน สำหรับ Plug-In ที่เกี่ยวข้องกับ Subversive ก็คือ
  • Subversive SVN Team Provider (Incubation)
  • Subversive SVN JDT Ignore Extensions (Optional) (Incubation)
  • Subversive SVN Integration for the Mylyn Project (Optional) (Incubation)
  • Subversive Revision Graph (Optional) (Incubation)
  • Subversive SVN Connectors
  • Native JavaHL x.x Implementation (Optional)
  • SVNKit x.x.x Implementation (Optional)

ปัญหาที่ 2 Subclipse 1.8 ไม่สามารถทำงานร่วมกับ JavaHL 1.8 ได้

เมื่อเหลือแต่ Subclipse แล้ว ผมก็เริ่มต้น Import โปรแกรมใหม่ แต่ก็ไม่สำเร็จเนื่องจาก Subclipse ฟ้องว่าไม่สามารถทำงานร่วมกับ JavaHL ที่มีอยู่ได้ ต้องใช้รุ่น 1.7.x ดังภาพ
เมื่อตรวจสอบระบบแล้ว พบว่า Ubuntu 14.04 มี Package ของ Subclipse รุ่น 1.8 และ JavaHL รุ่น 1.8 เช่นกัน แต่จากคำอธิบายในบทความเรื่อง Wiki ของ JavaHL ระบุรุ่นที่ทำงานร่วมกันไว้คือ
Subclipse VersionSVN/JavaHL Version
1.10.x1.8.x
1.8.x1.7.x
1.6.x1.6.x
1.4.x1.5.x
1.2.x1.4.x
1.0.x1.4.x
นั่นหมายความว่า ถ้าใช้ Subclipse 1.8 ก็จะต้องติดตั้ง JavaHL 1.7 ซึ่ง Ubuntu 14.04 ไม่มีให้ และถ้าจะใช้ JavaHL 1.8 ตามที่ Ubuntu 14.04 มีให้ ก็ต้องอัพเกรด Subclipse เป็น 1.10 โดยทีแรกผมพยายามจะหา JavaHL 1.7 มาติดตั้งแล้ว แต่เกิดปัญหาว่า ในระบบอาจจะมีโปรแกรมอื่นๆที่ต้องใช้งาน JavaHL ด้วยเช่นกัน ไม่ใช่มีเพียง Eclipse เท่านั้น ทำให้เกิดปัญหา dependency ต่างๆพันกันไปหมด สุดท้ายผมก็เลยตัดสินใจ อัพเกรด Subclipse โดยเข้าไปที่ Install New Software และเพิ่ม Repository สำหรับ Subclipse รุ่น 1.10.x ตรงช่อง Work with ด้วย URL http://subclipse.tigris.org/update_1.10.x เท่านี้ก็จะปรากฏ Plug-In รุ่น 1.10 และส่วนที่เกี่ยวข้องอื่นๆมาให้เราเลือกติดตั้งได้ทันทีดังภาพ
เมื่อติดตั้งแล้ว ก็จะสามารถใช้งาน Subversion ได้ตามปกติ