Pertama, disclaimer. Jangan lakukan ini. Saya melakukan ini untuk menguji teori dan untuk membuktikan suatu hal. ASP.NET Core dan .NET Core yang menjalankannya adalah open source dan berjalan hampir di mana saja. Saya ingin melihat apakah saya dapat menjalankan situs ASP.NET Core di hosting termurah GoDaddy ($3, meskipun skalanya menjadi $8) yang pada dasarnya hanya mendukung PHP. Ini bukan VM Linux lengkap. Itu terkunci dan terbatas. Anda tidak memiliki akar. Anda kehilangan sebagian besar alat yang Anda harapkan akan Anda miliki.
TAPI.
Saya ingin melihat apakah saya bisa menjalankan ASP.NET Core di atasnya. Mungkin jika saya melakukannya, mereka (dan host murah lainnya) akan berbicara dengan tim .NET, mengetahui bahwa ASP.NET Core adalah open source dan dapat dengan mudah dijalankan di infrastruktur mereka yang ada.
LAGI: Jangan lakukan ini. Ini hacky. Ini konyol. Tapi itu keren. MENURUT OPINI SAYA. Juga, terima kasih banyak kepada Tomas Weinfurt atas bantuannya!
Pertama, saya pergi ke GoDaddy dan mendaftar ke hosting murah mereka. Sekali lagi, bukan VM, tetapi yang mereka bagikan. Saya juga mendaftarkan supercheapaspnetsite.com juga. Mereka menggunakan sistem manajemen web berbasis cPanel yang tidak memungkinkan Anda melakukan apa pun. Anda dapat mengaktifkan SSH, melakukan beberapa hal PHP, dan umumnya melihat-lihat, tetapi itu bukan level rendah.
Pertama saya ssh (shoosh!) dan melihat apa yang saya kerjakan. Saya menggunakan fitur Ubuntu di Windows 10, yang harus diaktifkan oleh setiap pengembang. Sangat mudah untuk bekerja dengan host Linux jika Anda memulai dari Linux di Windows 10.
secretname@theirvmname [/proc]$ cat version Linux version 2.6.32-773.26.1.lve1.4.46.el6.x86_64 ([email protected]) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-18) (GCC) ) #1 SMP Tue Dec 5 18:55:41 EST 2017 secretname@theirvmname [/proc]$
Oke, sepertinya Red Hat, jadi CentOS 6 seharusnya kompatibel.
Saya akan menggunakan .NET Core 2.1 (yang dalam pratinjau sekarang!) dan mendapatkan SDK di https://www.microsoft.com/net/download/all dan menginstalnya di mesin Windows saya di mana saya akan mengembangkan dan membangun aplikasi. Saya tidak PERLU menggunakan Windows untuk melakukan ini, tetapi ini adalah laptop yang saya miliki dan juga senang mengetahui bahwa saya dapat membangun di Windows tetapi menargetkan CentOS/RHEL6.
Selanjutnya saya akan membuat situs ASP.NET baru dengan
dotnet new razor
dan kemudian saya akan menerbitkan versi mandiri seperti ini:
dotnet publish -r rhel.6-x64
Dan file-file itu akan berakhir di folder seperti \supercheapaspnetsite\bin\Debug\netcoreapp2.1\rhel.6-x64\publish\
CATATAN: Anda mungkin perlu menambahkan umpan NuGet untuk harian untuk pratinjau .NET Core ini agar runtime RHEL6 diunduh selama publikasi lokal ini.
Kemudian saya menggunakan WinSCP (atau klien FTP/SCP apa pun yang Anda suka, rsync, dll) untuk memasukkan file ke folder ~/www di situs bersama GoDaddy Anda. Lalu saya
chmod +x ./supercheapasnetsite
untuk membuatnya dapat dieksekusi. Sekarang, dari sesi ssh saya di GoDaddy, mari coba jalankan aplikasi saya!
secretname@theirvmname [~/www]$ ./supercheapaspnetsite Failed to load hb, error: libunwind.so.8: cannot open shared object file: No such file or directory Failed to bind to CoreCLR at '/home/secretname/public_html/libcoreclr.so'
Tentu tidak bisa semudah itu bukan? .NET Core menginginkan perpustakaan bersantai (objek bersama) dan tidak ada di sistem yang terkunci ini.
DAN saya tidak punya yum/apt/rpm atau cara menginstalnya kan?
Saya bisa mencari file tar.gz di suatu tempat seperti ini http://download.savannah.nongnu.org/releases/libunwind/ tapi saya perlu memikirkan versi dan memastikan semuanya sesuai. Mengingat bahwa saya menargetkan CentOS6, saya harus mulai di sini https://centos.pkgs.org/6/epel-x86_64/libunwind-1.1-3.el6.x86_64.rpm.html dan unduh libunwind-1.1-3.el6 .x86_64.rpm.
Saya perlu membuka file rpm itu dan mendapatkan perpustakaan. Paket RPM hanyalah header di atas arsip CPIO, jadi saya bisa apt-get install rpm2cpio dari instance Ubuntu lokal saya (di Windows 10). Kemudian dari /mnt/c/users/scott/Downloads (tempat saya mengunduh file) saya akan mengekstraknya.
rpm2cpio ./libunwind-1.1-3.el6.x86_64.rpm | cpio -idmv
Itu dia.
Bagian ini keren. Meskipun saya memiliki file-file ini, saya tidak memiliki root atau cara apa pun untuk "menginstal" mereka. Namun saya dapat mengekspor/menggunakan variabel lingkungan LD_LIBRARY_PATH untuk mengontrol bagaimana perpustakaan dimuat ATAU saya dapat meletakkan file-file ini di $ORIGIN/netcoredeps . Anda dapat membaca lebih lanjut tentang Aplikasi Linux Mandiri di .NET Core di sini.
Eksekusi utama dari aplikasi .NET Core yang diterbitkan (yang merupakan host .NET Core) memiliki properti RPATH yang disetel ke
$ORIGIN/netcoredeps
. Itu berarti bahwa ketika pemuat pustaka bersama Linux mencari pustaka bersama, pemuat itu melihat ke lokasi ini sebelum mencari ke lokasi pustaka bersama default. Perlu dicatat bahwa jalur yang ditentukan olehLD_LIBRARY_PATH
variabel lingkungan atau pustaka yang ditentukan olehLD_PRELOAD
variabel lingkungan masih digunakan sebelum properti RPATH. Jadi, untuk menggunakan salinan lokal perpustakaan pihak ketiga, pengembang perlu membuat direktori bernamanetcoredeps
di sebelah aplikasi utama yang dapat dieksekusi dan salin semua dependensi yang diperlukan ke dalamnya.
Pada titik ini saya telah menambahkan folder "netcoredeps" ke folder publik saya, dan kemudian menyalinnya (scp) ke GoDaddy. Ayo jalankan lagi.
secretname@theirvmname [~/www]$ ./supercheapaspnetsite FailFast: Couldn't find a valid ICU package installed on the system. Set the configuration flag System.Globalization.Invariant to true if you want to run with no globalization support. at System.Environment.FailFast(System.String) at System.Globalization.GlobalizationMode.GetGlobalizationInvariantMode() at System.Globalization.GlobalizationMode..cctor() at System.Globalization.CultureData.CreateCultureWithInvariantData() at System.Globalization.CultureData.get_Invariant() at System.Globalization.CultureInfo..cctor() at System.StringComparer..cctor() at System.AppDomain.InitializeCompatibilityFlags() at System.AppDomain.Setup(System.Object) Aborted
Ok, sekarang mengeluh tentang paket ICU. Ini untuk globalisasi. Itu juga disebutkan dalam dokumen aplikasi linux mandiri dan ada biner yang sudah dikompilasi yang bisa saya unduh. Tapi ada pilihan.
Jika aplikasi Anda tidak secara eksplisit memilih untuk tidak menggunakan globalisasi, Anda juga perlu menambahkan
libicuuc.so.{version}
,libicui18n.so.{version}
, danlibicudata.so.{version}
Saya suka "opt-out" jadi saya tidak perlu menggali up ini (walaupun saya bisa) jadi saya bisa mengatur CORECLR_GLOBAL_INVARIANT env var ke 1, atau saya bisa menambahkan System.Globalization.Invariant =true ke supercheapaspnetsite.runtimeconfig .json, yang akan saya lakukan hanya untuk menjadi menjengkelkan.;)
Ketika saya menjalankannya lagi, saya mendapatkan keluhan lain tentang libuv. Pustaka bersama lain yang tidak diinstal pada instance ini. Saya bisa ambil dan taruh di netcoredeps ATAU karena saya menggunakan .NET Core 2.1, saya bisa mencoba sesuatu yang baru. Ada beberapa perbaikan yang dilakukan di .NET Core 2.1 di sekitar soket dan kinerja http. Di sisi klien, pustaka terkelola baru ini ditulis dari bawah ke atas dalam kode terkelola menggunakan Span
Dengan kata lain, saya dapat mem-bypass penggunaan libuv sepenuhnya dengan mengubah Program.cs saya untuk menggunakan use UseSockets() seperti ini.
public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseSockets() .UseStartup<Startup>();
Mari kita jalankan lagi. Saya akan menambahkan variabel lingkungan ASPNETCORE_URLS dan menyetelnya ke port tinggi seperti 8080. Ingat, saya bukan admin jadi saya tidak bisa menggunakan port apa pun di bawah 1024.
secretname@theirvmname [~/www]$ export ASPNETCORE_URLS="http://*:8080" secretname@theirvmname [~/www]$ ./supercheapaspnetsite Hosting environment: Production Content root path: /home/secretname/public_html Now listening on: http://0.0.0.0:8080 Application started. Press Ctrl+C to shut down.
Astaga, ini benar-benar dimulai.
Oke, tapi saya tidak bisa mengaksesnya dari supercheapaspnetsite.com:8080 karena ini adalah hosting bersama terkelola milik GoDaddy yang dikunci. Saya tidak bisa begitu saja membuka port atau meneruskan port di panel kontrol mereka.
Tetapi. Mereka menggunakan Apache, dan yang memiliki file .htaccess!
Bisakah saya menggunakan mod_proxy dan mencoba ini?
ProxyPassReverse / http://127.0.0.1:8080/
Sepertinya tidak, mereka belum mengaktifkan ini. Kemungkinan mereka tidak ingin melakukan proxy ke domain eksternal, tetapi alangkah baiknya jika mereka mengizinkan localhost. Kekecewaan. Begitu dekat.
Baik, saya akan proxy lalu lintas sendiri. (Tidak sempurna, tapi ini semua adalah lonjakan)
RewriteRule ^(.*)$ "show.php" [L]
Keren, sekarang proxy murahan masuk show.php.
<?php $site = 'http://127.0.0.1:8080'; $request = $_SERVER['REQUEST_URI']; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $site . $request); curl_setopt($ch, CURLOPT_HEADER, TRUE); $f = fopen("headers.txt", "a"); curl_setopt($ch, CURLOPT_VERBOSE, 0); curl_setopt($ch, CURLOPT_STDERR, $f); #don't output curl response, I need to strip the headers. #yes I know I can just CURLOPT_HEADER, false and all this # goes away, but for testing we log headers curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); $hold = curl_exec($ch); #strip headers $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $headers = substr($hold, 0, $header_size); $response = substr($hold, $header_size); $headerArray = explode(PHP_EOL, $headers); echo $response; #echo ourselves. Yes I know curl can do this for us. ?>
Cemas, ya. Bekerja untuk GET? Juga, ya. Ini benar-benar tugas Apache, bukan tugas kami, tapi pujian untuk Tomas atas ide jahat ini.
Ledakan. Bagaimana dengan halaman lain di /about? Ya.
Menyenangkan. Tapi saya harus menjalankan aplikasi sendiri. Saya tidak memiliki supervisor atau manajer proses (sekali lagi ini sudah ditangani oleh GoDaddy untuk PHP tetapi saya berada di dunia yang tidak memiliki hak istimewa.) Mendorong dan menjalankannya adalah ide yang buruk dan tidak berkelanjutan. (Yah, semua ini tidak berkelanjutan, tapi tetap saja.)
Kami dapat menyalin "layar" dan memulainya dan melepaskannya seperti menggunakan aplikasi screen ./supercheapaspnet, tetapi sekali lagi, jika macet, tidak ada yang akan memulainya. Kami melakukan memiliki crontab, jadi untuk saat ini, kami akan meluncurkan aplikasi sesuai jadwal sesekali untuk melakukan pemeriksaan kesehatan dan jika perlu, tetap menjalankannya. Juga menambahkan beberapa alat debugging di ~/bin:
secretname@theirvmname [~/bin]$ ll total 304 drwxrwxr-x 2 4096 Feb 28 20:13 ./ drwx--x--x 20 4096 Mar 1 01:32 ../ -rwxr-xr-x 1 150776 Feb 28 20:10 lsof* -rwxr-xr-x 1 21816 Feb 28 20:13 nc* -rwxr-xr-x 1 123360 Feb 28 20:07 netstat*
Secara keseluruhan, tidak terlalu sulit. ASP.NET Core dan .NET Core di bawahnya dapat berjalan hampir di mana saja, seperti PHP, Python, apa pun.
Jika Anda seorang tuan rumah dan Anda ingin berbicara dengan seseorang di Microsoft tentang menyiapkan hosting bersama ASP.NET Core, kirim email ke [email protected] dan bicaralah dengan mereka! Jika Anda GoDaddy, saya minta maaf, dan Anda juga harus mengirim email.;)
Sponsor: Dapatkan JetBrains Rider terbaru untuk men-debug kode .NET pihak ketiga, Smart Step Into, peningkatan debugger lainnya, C# Interactive, wizard proyek baru, dan kode pemformatan dalam kolom.