ปัญหาหลายตำแหน่งของ Nginx


15

ฉันกำลังพยายามแบ่งแอปพลิเคชั่น 3 ตัวออกจากที่เก็บหนึ่งแห่งเป็น 3 แต่ทำให้โครงสร้าง URL ดังนั้นโดยทั่วไปสถานที่ที่แตกต่างกันภายใต้โดเมนเดียวกันจะต้องถูกส่งโดยแอปพลิเคชันที่แตกต่างกัน

สิ่งที่ฉันกำลังดิ้นรนคือแอปหนึ่งต้องเป็นทางเลือกสำหรับ URL ที่ไม่มีอยู่จริงดังนั้นหากแอปแรกไม่ตรงกันและแอปที่สองไม่มีอยู่แอปที่สามควรจัดการคำขอ

โครงสร้างที่ฉันมีคือ:

/ etc / nginx / sites-enabled / main_site, ที่นี่, นอกเหนือจาก server_name และบันทึกที่ฉันได้รับinclude /etc/nginx/subsites-enabled/*, ที่ฉันมีไฟล์กำหนดค่า 3 ไฟล์, หนึ่งไฟล์สำหรับแต่ละแอป

ไฟล์กำหนดค่า 3 ไฟล์แต่ละไฟล์มีบล็อกที่ตั้ง

ฉันได้ลองใช้ lookahead เชิงลบใน regex (โดยทั่วไปแล้วพยายามที่จะ hardcode URL ที่แอพอื่น ๆ จัดการ) แต่ล้มเหลว

ดังนั้นเพื่อสรุป:

/ และ / ชุมชนควรได้รับการจัดส่งโดย /etc/nginx/subsites-enabled/example.org/home (สคริปต์ Perl ไม่กี่ตัว)

/ ข่าวควรส่งโดย /etc/nginx/subsites-enabled/example.org/news (wordpress)

ทุกอย่างอื่นควรส่งโดย /etc/nginx/subsites-enabled/example.org/app (แอพเค้ก)

perl bit ทำงานได้ดี ปัญหาที่ฉันมีคือแอปกำลังรับช่วงต่อข่าวสาร (อาจเป็นเพราะมันตรงกับ *) ฉันได้ลองตัวเลือกที่หลากหลาย (ฉันเคยไปที่นี่มา 2 วันแล้ว) แต่ก็ไม่มีใครแก้ปัญหาทั้งหมดได้ (บางครั้ง สินทรัพย์คงไม่ทำงาน ฯลฯ )

การกำหนดค่าของฉันคือ:

/etc/nginx/sites-enabled/example.org:

server {
    listen   80;
    server_name example.org;
    error_log /var/log/nginx/example.org.log;

    include /etc/nginx/subsites-enabled/example.org/*;
}

/etc/nginx/subsites-enabled/example.org/home:

location = / {
  rewrite ^.*$ /index.pl last;
}

location ~* /community(.*) {
  rewrite ^.*$ /index.pl last;
}

location ~ \.pl {
  root   /var/www/vhosts/home;
  access_log /var/log/nginx/home/access.log;
  error_log /var/log/nginx/home/error.log;

  include /etc/nginx/fastcgi_params;
  fastcgi_index index.pl;
  fastcgi_param SCRIPT_FILENAME /var/www/vhosts/home$fastcgi_script_name;
  fastcgi_pass  unix:/var/run/fcgiwrap.socket;
}

/ etc / ngins / ไซต์ย่อยที่เปิดใช้งาน / ข่าว

location /news {
  access_log /var/log/nginx/news/access.log;
  error_log /var/log/nginx/news/error.log debug;

  error_page 404 = /news/index.php;

  root /var/www/vhosts/news;

  index index.php;

  if (!-e $request_filename) {
      rewrite ^.*$ /index.php last;
  }

  location ~ \.php {
    include /etc/nginx/fastcgi_params;
    fastcgi_pass  127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /var/www/vhosts/news$fastcgi_script_name;
  }
}

/ etc / Nginx / ไซต์ย่อยที่เปิดใช้งาน / แอป:

location ~ .* {
  access_log /var/log/nginx/app/access.log;
  error_log /var/log/nginx/app/error.log;

  rewrite_log on;

  index index.php;
  root /var/www/vhosts/app/app/webroot;

  if (-f $request_filename) {
    expires 30d;
    break;
  }

  if (!-e $request_filename) {
    rewrite ^.*$ /index.php last;
  }

  location ~ \.php {
    include /etc/nginx/fastcgi_params;
    fastcgi_pass  127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /var/www/vhosts/app/app/webroot$fastcgi_script_name;
  }
}

a) โพสต์การกำหนดค่าของคุณพร้อมกับตัวอย่างของการเปลี่ยนเส้นทางที่หลากหลาย (รวมถึงการเปลี่ยนเส้นทางสำหรับ URL ที่ไม่มีอยู่) b) ใช้try_filesพร้อมบล็อคตำแหน่งที่ระบุชื่อ (ใช้ส่วน@นำหน้า) ที่แมปไปยังแอปเริ่มต้นของคุณ คุณยังสามารถตั้งค่า error_page ที่แม็พ 404 กับตำแหน่งที่ระบุชื่อได้
cyberx86

@ cyberx86 ฉันได้เพิ่มรายละเอียดและกำหนดค่าของฉัน
Andrei Serdeliuc

อย่างรวดเร็วแสดงให้เห็นบางสิ่งที่ก) การจับคู่ regex จะเหนือกว่าธรรมดาสตริง - เพื่อให้บล็อกแอปของคุณจะตรงกับแทนของบล็อกข่าวของคุณ - location ^~ /newsลอง b) สำหรับบล็อกแอปของคุณคุณควรจะสามารถทำได้location /(ซึ่งไม่เหมือนกันlocation = /แต่ควรตรงกับทุกอย่างที่ไม่ได้จับคู่ไว้แล้ว c) ในบางกรณี (โดยเฉพาะ regexes) คำสั่งมีความสำคัญ - คุณอาจต้องการรวม 3 ไฟล์เป็นไฟล์เดียวโดยบล็อกในลำดับที่ถูกต้อง นอกจากนี้การใช้ try_files !-eแทน จนเห็นwiki.nginx.org/HttpCoreModule#location
cyberx86

ฉันลองทุกรูปแบบของรูปแบบเหล่านั้นมากรวมถึงการรวมไว้ในไฟล์เดียว (แม้ว่าพวกเขาจะต้องแยกออกจากกันเมื่อพวกเขาถูกนำไปใช้งานแยกต่างหาก) แต่ก็ไม่มีเลย ข่าวเพิ่งได้รับการจัดการโดยแอป
Andrei Serdeliuc

ดีฉันคิดว่าได้แก้ไขมัน - bit trickier กว่าที่ฉันคาดไว้ตอนแรก - แต่แน่นอนสนุกเพื่อจับคู่กับ ขอบคุณสำหรับปริศนา
cyberx86

คำตอบ:


47

มีสิ่งผิดปกติเกิดขึ้นกับการกำหนดค่าของคุณสองสิ่งที่เกี่ยวข้องคือ:

  1. เส้นทางภายในบล็อกสถานที่ยังคงมีเส้นทางที่ตรงกัน
  2. เขียนซ้ำด้วย 'สุดท้าย' ดำเนินการต่อโดยดูตำแหน่งที่มีอยู่ทั้งหมดสำหรับการแข่งขัน (แบ่งออกจากบล็อกตำแหน่งปัจจุบัน)

ตัวอย่างเช่นใช้ URL example.org/news/test.htm

  • location /newsบล็อกจะตรงกับมัน
  • เส้นทางที่ใช้อยู่/news/test.htm- ไม่เปลี่ยนแปลงเนื่องจากอยู่ในบล็อกตำแหน่ง
  • การเพิ่มพา ธ ไปยัง document_root คุณจะได้รับ: /var/www/vhosts/news/news/test.htm
  • ใบแจ้งยอดของคุณif (!-e $request_filename)ควรจับไฟล์ที่ไม่มีอยู่นี้
  • คุณเขียนเส้นทางไปที่ /index.php
  • เนื่องจากคุณกำลังใช้lastกระบวนการเริ่มต้นใหม่ (แยกออกจากบล็อกตำแหน่ง)
  • /index.phplocation /app blockถูกจับในขณะนี้โดย

ปัญหาดังกล่าวข้างต้นโดยมีคำสั่งรูทจะรวมกันเมื่อคุณไปที่บล็อกสถานที่แอปของคุณ ไม่เหมือนกับบล็อก 'news' ที่คุณสามารถเอา 'news' ออกจาก path (เนื่องจากมันจะถูกเพิ่มเข้าไปอีกครั้ง) คุณไม่สามารถทำสิ่งนี้กับ path ของ app ซึ่งลงท้ายด้วย 'webroot'

การแก้ปัญหาอยู่ในaliasคำสั่ง สิ่งนี้ไม่เปลี่ยน document_root แต่เปลี่ยนพา ธ ไฟล์ที่ใช้เพื่อให้บริการตามคำขอ แต่น่าเสียดายที่rewriteและมีแนวโน้มที่จะประพฤติบิตโดยไม่คาดคิดด้วยtry_filesalias

เริ่มจากตัวอย่างง่ายๆ - ไม่มี PHP - แค่ HTML และบล็อก Perl ของคุณ - แต่ด้วยโครงสร้างโฟลเดอร์ที่ตรงกับคุณ (ทดสอบบน Nginx 1.0.12, CentOS 6):

server {
    server_name example.org;
    error_log /var/log/nginx/example.org.error.log notice;
    access_log /var/log/nginx/example.org.access.log;
    rewrite_log on;

    location = / {
        rewrite ^ /index.pl last;
    }

    location ^~ /community {
        rewrite ^ /index.pl last;
    }

    location ~ \.pl {
        root   /var/www/vhosts/home;

        [fastcgi_stuff...]
    }


    location ^~ /news {
        alias /var/www/vhosts/news;
        index index.htm;

        try_files $uri $uri/ /news/index.htm;
    }

    location ^~ /app {
        alias /var/www/vhosts/app/app/webroot;
        index index.htm;

        try_files $uri $uri/ /app/index.htm;
    }

    location / {
        rewrite ^/(.*) /app/$1 last;
    }
}
  • location = / - จะจับคู่กับเส้นทางรากเท่านั้น
  • location ^~ /community - จะจับคู่ทุกเส้นทางที่ขึ้นต้นด้วย / community
  • location ~ \.pl - จะจับคู่ไฟล์ทั้งหมดที่มี. pl
  • location ^~ /news - จะจับคู่ทุกเส้นทางที่ขึ้นต้นด้วย / news
  • location ^~ /app - จะจับคู่ทุกเส้นทางที่ขึ้นต้นด้วย / app
  • location / - จะจับคู่เส้นทางทั้งหมดที่ไม่ตรงกับด้านบน

คุณควรจะสามารถลบ^~- แต่อาจเสนอการปรับปรุงประสิทธิภาพเล็กน้อยเนื่องจากหยุดการค้นหาเมื่อพบคู่ที่ตรงกัน

ในขณะที่มันควรเป็นเรื่องง่าย ๆ ในการเพิ่มบล็อก PHP กลับเข้าไป แต่น่าเสียดายที่ปัญหาเล็กน้อย - try_files(และการเขียนซ้ำของคุณ) ไม่จบลงด้วยการผ่านเส้นทางที่ต้องการไปยังบล็อกที่ตั้งที่ซ้อนกัน - และใช้aliasเมื่อส่วนขยายเท่านั้น ที่ระบุในบล็อกตำแหน่งไม่ทำงาน

ทางออกหนึ่งคือการใช้บล็อคที่ตั้งแยกต่างหากที่ทำการจับภาพพร้อมกับคำสั่ง alias - มันไม่ได้สวยงาม แต่เท่าที่ฉันสามารถบอกได้มันทำงานได้ (ทดสอบอีกครั้งบน Nginx 1.0.12, CentOS 6 - จาก แน่นอนฉันไม่ได้ติดตั้ง CakePHP, Wordpress และ Perl - ฉันใช้ไฟล์ PHP และ HTML สองไฟล์ในแต่ละโฟลเดอร์)

server {
    server_name example.org;
    error_log /var/log/nginx/example.org.error.log notice;
    access_log /var/log/nginx/example.org.access.log;
    rewrite_log on;

    location = / {
        rewrite ^ /index.pl last;
    }

    location ^~ /community {
        rewrite ^ /index.pl last;
    }

    location ~ \.pl {
        root   /var/www/vhosts/home;
        access_log /var/log/nginx/home.access.log;
        error_log /var/log/nginx/home.error.log;
        include /etc/nginx/fastcgi_params;
        fastcgi_index index.pl;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass  unix:/var/run/fcgiwrap.socket;
    }

    location /news {
        access_log /var/log/nginx/news.access.log;
        error_log /var/log/nginx/news.error.log notice;
        alias /var/www/vhosts/news;
        index index.php;
        try_files $uri $uri/ /news/index.php;
    }

    location ~* ^/news/(.*\.php)$ {
        access_log /var/log/nginx/news.php.access.log;
        error_log /var/log/nginx/news.php.error.log notice;
        alias /var/www/vhosts/news/$1;
        try_files "" /news/index.php;
        include /etc/nginx/fastcgi_params;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_NAME $1;
        fastcgi_param SCRIPT_FILENAME /var/www/vhosts/news/$1;
        fastcgi_pass  127.0.0.1:9000;
    }

    location /app {
        alias /var/www/vhosts/app/app/webroot;
        access_log /var/log/nginx/app.access.log;
        error_log /var/log/nginx/app.error.log notice;
        index index.php;
        try_files $uri $uri/ /app/index.php;
    }

    location ~* ^/app/(.*\.php)$ {
        access_log /var/log/nginx/news.access.log;
        error_log /var/log/nginx/news.error.log notice;
        alias /var/www/vhosts/app/app/webroot/$1;
        try_files "" /app/index.php;
        include /etc/nginx/fastcgi_params;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_NAME $1;
        fastcgi_param SCRIPT_FILENAME /var/www/vhosts/app/app/webroot/$1;
        fastcgi_pass  127.0.0.1:9000;
    }

    location / {
        rewrite ^/(.*) /app/$1 last;
    }
}

การกำหนดค่าด้านบนใช้สิ่งที่ง่ายด้านบนและทำการเปลี่ยนแปลงสองอย่าง:

  • เพิ่มบล็อกสถานที่สองแห่ง:
    • location ~* ^/news/(.*\.php)$ - จะจับคู่ไฟล์ทั้งหมดที่ลงท้ายด้วย. php โดยมีพา ธ ที่ขึ้นต้นด้วย / news /
    • location ~* ^/app/(.*\.php)$ - จะจับคู่ไฟล์ทั้งหมดที่ลงท้ายด้วย. php โดยมีพา ธ ที่ขึ้นต้นด้วย / app /
  • ลบการ^~จับคู่ - นี่เป็นสิ่งจำเป็นเพื่อให้บล็อกตำแหน่งที่เพิ่มสองรายการสามารถจับคู่กับพา ธ (มิฉะนั้นการจับคู่จะหยุดในบล็อก / news หรือ / app)

ควรสังเกตว่าลำดับการจับคู่สถานที่มีความสำคัญมากที่นี่:

  • ตรงทั้งหมดก่อน (ใช้=)
  • ตรงกับ^~วินาที
  • การจับคู่บล็อก regex
  • สตริงทั่วไป - เฉพาะในกรณีที่ไม่พบ regex ที่ตรงกัน

regex ที่ตรงกันจะแทนที่สตริงตรง!

จุดสำคัญที่กล่าวถึงคือเมื่อมีการใช้การจับภาพด้วยนามแฝง URL ทั้งหมดจะถูกแทนที่ไม่ใช่เฉพาะโฟลเดอร์นำ น่าเสียดายที่นี่หมายถึงว่า$fastcgi_script_nameมันว่างเปล่าดังนั้นฉันใช้มัน$1แทน

ฉันแน่ใจว่าคุณจะต้องทำการเปลี่ยนแปลงเล็กน้อย แต่หลักฐานขั้นพื้นฐานควรทำงานได้ คุณควรจะสามารถแยกบล็อกออกเป็นหลาย ๆ ไฟล์ได้ตามต้องการเพราะการเรียงลำดับจะไม่มีผลกับการกำหนดค่า


2
เพื่อนฉันหวังว่าฉันจะสามารถโหวตคุณ 100 ครั้ง คุณบริสุทธิ์จริงๆ ขอบคุณ!
Andrei Serdeliuc
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.