2014-12-31 36 views
2

由於似乎mod_perl只管理Perl interpreters per VHOST,是 有什麼辦法可以影響哪個克隆解釋器mod_perl 選擇處理請求?我已閱讀了可配置的 示波器,並查看了源中的「modperl_interp_select」,並且我可以看到,如果請求已經有關聯的解釋器,那麼之一由mod_perl選擇。如何使mod_perl解釋器按照一些約定粘滯?

else if (r) { 
    if (is_subrequest && (scope == MP_INTERP_SCOPE_REQUEST)) { 
[...] 
    } 
    else { 
     p = r->pool; 
     get_interp(p); 
    } 

我想補充某種處理程序的mod_perl選擇一個 解釋器來處理請求,然後選擇傳譯員 它分配給請求自己之前的基礎上,包括在 要求不同的標準。

但是我很難理解這樣的處理程序是否可以存在於 全部或者是否有關於請求的所有內容都已經被 所選的解釋器mod_perl處理。

此外,我可以看到APR ::游泳池的API,但它似乎並沒有提供 設置當前池對象, 是「get_interp」在讀什麼mod_perl的一些用戶數據的能力。

任何人都可以幫助我嗎?謝謝!

的背景了一下:我在的cgi-bin目錄一個結構如下所示:

cgi-bin 
    software1 
     customer1 
      *.cgi 
      *.pm 
     customer2 
      *.cgi 
      *.pm 
    software2 
     customer1 
      *.cgi 
      *.pm 
     customer2 
      *.cgi 
      *.pm 

每個客戶使用該軟件的私有副本和軟件是使用本身,例如customer1的software1可以通過將一些特殊的software2客戶庫加載到它自己的Perl解釋器中來與customer1的software2交談。爲了使事情更加複雜,軟件2甚至可以通過使用svn:external將自己的私有安裝帶入軟件1的通用/通用部分。所以我在一個VHOST中有許多相同的軟件和相同的Perl軟件包,我不能保證所有這些私人安裝都具有相同的版本級別。

這是一個相當混亂,但已知在我們在相同的Perl解釋器內有規則工作。

但是現在出現mod_perl,根據需要克隆解釋器,並將它們重用到請求的任意子目錄中,在這種情況下,事情將會中斷,因爲解釋器突然已經處理了customer1的software1,現在應該處理software2的customer2,它使用通用的軟件包1,已經由Perl解釋器加載之前,因爲使用%INC而不是軟件的私有包2等等,所以使用它們...

是的,有不同的交易方式就像VHOST和子域persoftware或客戶或其他,但我想檢查保持一個VHOST和當前目錄結構的不同方式,只需使用mod_perl或Apache httpd提供的內容即可。有一種方法是,如果我能告訴mod_perl始終對同一個目錄的請求使用相同的Perl解釋器。這樣mod_perl會創建它的解釋器池,我將負責爲每個目錄選擇它們中的每一個。

+0

您有具體的理由使用mod_perl嗎?使用Plack你可以獲得更多的控制權(AFAIK)。 (也許我錯過了一些關鍵點)... – jm666

+0

PLACK對我們來說是全新的,你如何使用PLACK實現我的請求?我希望它像在mod_perl中一樣運行在httpd中,而不是獨立運行,但是需要控制哪個Perl解釋器被各種原因用於具有普通的舊CGI腳本的服務目錄。最後一件事很重要,解釋器不能被重用於不同的腳本/目錄。 –

+0

也許我誤解了你的需求,但是我會爲某些URL(每個你的CGI腳本都有自己的URL)設置apache(或任何httpd這樣的nginx)作爲「反向代理」,並且將爲每個腳本運行一個基於Plack的服務器(在不同的端口上)使用[CGI :: Emulate :: PSGI](https://metacpan.org/pod/CGI::Emulate::PSGI)或[CGI :: PSGI](https://metacpan.org/ POD/CGI :: PSGI)。因此,簡而言之,每個CGI腳本將在完全隔離的(但是httpd代理的)環境中在其自己的端口上運行一個獨立的Plack(perl)服務器。 – jm666

回答

0

「PerlOptions」是DIR範圍變量,不限於VirtualHosts,因此可以爲任何位置創建新的解釋器池。這些指令甚至可以放在.htaccess文件中以便於配置,但是在httpd中就是這樣。CONF應該給你想要的效果:

<Location /cgi-bin/software1/customer1> 
    PerlOptions +Parent 
</Location> 
<Location /cgi-bin/software1/customer2> 
    PerlOptions +Parent 
</Location> 
<Location /cgi-bin/software2/customer1> 
    PerlOptions +Parent 
</Location> 
<Location /cgi-bin/software2/customer2> 
    PerlOptions +Parent 
</Location> 
+0

你嘗試過嗎?我可以自己閱讀文檔,但是你真的真的嘗試過嗎?它不起作用,mod_perl錯誤說,父不是每個目錄選項,我發現其他人有相同的問題:「每個目錄PerlOption無效:父」我已經找到相應的源代碼在mod_perl的錯誤爲好。我想這是因爲解釋器綁定到APR池,而這些池似乎只能用於請求對象,服務器配置對象等。在.htaccess中有這樣的聲明是我多年前嘗試的第一件事...... –

+1

對,這應該按照文檔工作,但@ithread_opts不在lib/ModPerl/Code.pm +136的Dir中。所以PerlOption測試失敗。它可能很簡單,只需將ithread選項添加到Dir數組並重建mod_perl即可。 –

+0

感謝您的提示,我無法親自找到該代碼,因此不瞭解Parent的有效性設置。 CODE.pm是否只在構建過程中用於爲實際執行檢查的mod_perl二進制生成本地代碼?或者你知道在構建之後還有什麼方法影響ithread_opts的有效性嗎? –

0

我所學到到目前爲止,它是不會輕易可以影響有關選定翻譯的mod_perl的決定。如果一個人想,似乎一個需要真正打補丁的mod_perl在C水平或提供自己的C-處理程序的httpd作爲掛鉤的mod_perl之前運行。最後mod_perl只是httpd本身的處理程序的一個組合,所以把它放在前面做一些特殊的事情是可能的。這是另外一個問題,如果它是明智的,這樣做,是因爲一個人必須要處理一些mod_perl的內部喜歡這樣的事實沒有翻譯可用目前並在我的情況下結束,我需要一張地圖某處口譯和它們相關的處理目錄。

最後它不是那麼容易,我不想修補mod_perl或在低級別C啓動httpd處理程序/掛鉤。

有關文檔目的,我想提一提它進入了我的腦海兩種可能的解決方法:

## Perl的線程##的游泳池

在我的情況下,當前的mod_perl方法的問題是,它的克隆Perl解釋低水平C和那些由httpd的池提供的線程運行,每個線程可以運行任何解釋任何給定的時間,除非它是不是已經被另一個線程。通過這種方法,似乎不可能在不使用任何低級別的XS的情況下訪問Perl本身內的解釋器,尤其是不可能通過Perl's Threads API管理解釋器和線程,因爲它不是Perl線程,它是由Perl執行的解釋器httpd線程。儘管如此,兩者的表現完全相同,因爲在創建Perl線程期間,當前的解釋器也被克隆,並且相關的OS線程被創建等。但是在使用Perl的線程時,你對共享數據等有更多的影響。

所以我目前的問題解決方法可能是不能讓的mod_perl和它的解釋處理請求,而是創造的Perl線程的自己的線程池,而直接使用PerlModule或這樣的VHOST啓動。這些線程可以直接在Perl中完全管理,可以創建一些隊列以絕對路徑的形式派發工作到請求的CGI應用程序等。除了線程池本身之外,還需要一個處理程序,它將被調用而不是例如。 modperl來::註冊表來充當調度員:那就需要根據某些條件使用,並把請求的路徑到它的隊列中,線程本身可能最終如哪個線程來決定只需創建ModPerl :: Registry的新實例來處理給定的文件。當然,這裏和那裏會有一些膠水需要...

這種方法當然有一些缺點:聽起來像是相當數量的工作,使mod_perl已經實現的一些功能翻倍,特別是關於池維護和雙打使用的線程和存儲器的量,這是因爲解釋的mod_perl和線程將只用於執行調度處理程序和附加的一種將具有螺紋和解釋處理的Perl線程內的請求。線程的數量根本不應該是一個很大的問題,mod_perl只會睡眠並等待Perl線程完成它的工作。

## @ INC鉤子的源代碼改變##

另一個,我想更簡單,方法是將延伸modperl來::註冊一個自己的mod_perl處理器再次進行聯合使用的@INC hooks for Perl's require。關鍵在於處理程序是讀取請求文件的第一個地方,在編譯之前可以更改源文件。每

use XY::Z; 
XY::Z->new(...); 

可改爲

use SomePrefix::XY::Z; 
SomePrefix::XY::Z->new(...); 

其中SomePrefix將僅僅是請求文件的父目錄的完整路徑更改爲一個有效的Perl package name。 ModPerl :: Registry已經做了類似的事情,而transforming一個請求的CGI腳本自動到一個mod_perl處理程序,所以這一般工作,並且ModPerl :: Registry已經提供了一些邏輯來生成軟件包名稱等。這種變化導致Perl不會再自動找到這些包,只是因爲它們並不存在Perl中已知的新名稱,這就是@INC鉤子所應用的地方。

掛鉤負責識別這些更改的包,只是因爲SomePrefix的名稱或SomePrefix前面的標記前綴或其他內容,並將它們映射到文件系統中的文件以提供所請求文件的句柄Perl可以在「require」期間加載。此外,鉤子將提供一個回調函數,Perl會爲每一行文件讀取調用該回調函數,並將作爲源代碼過濾器,再次更改每個「包」,「使用」或「要求」語句以使SomePrefix位於。這將導致掛鉤負責​​爲這些包提供文件句柄等。

這裏的關鍵是在運行時改變源代碼一次:而不是Perl通常需要的「XY/Z.pm」將在我的目錄結構中可用n次,並將在%INC中保存爲「XY/Z.pm」,其中一個允許Perl需要「SomePrefix/XY/Z.pm」,它將存儲在%INC中,並且對於每個由mod_perl使用的Perl解釋器,因爲SomePrefix反映了請求文件的唯一安裝目錄。 Perl已經沒有空間認爲它已經加載了XY :: Z,只是因爲它之前處理了來自另一個目錄的請求。

當然這隻適用於容易「使用......」語句,例如「eval(」require $ package「);」會讓事情變得更復雜一些。

評論歡迎... :-)