Проблема со спящим постоянным количеством в 1 секунду после каждой передачи заключается в том, что у вас будет прерывистая производительность сети.
Пусть BandwidthMaxThreshold является искомым пределом полосы пропускания.
Пусть TransferRate является текущей скоростью передачи соединения.
Затем ...
Если вы обнаружите свой TransferRate> BandwidthMaxThreshold, вы выполните SleepTime = 1 + SleepTime * 1.02 (увеличьте время сна на 2%)
До или после каждой сетевой операции выполните Sleep (SleepTime)
Если вы обнаружите, что ваш TransferRate намного ниже, чем ваш BandwidthMaxThreshold, вы можете уменьшить время сна. В качестве альтернативы вы всегда можете разлагать / уменьшать время сна. В конце концов ваш SleepTime снова достигнет 0.
Вместо увеличения на 2% вы также можете увеличить линейное увеличение разницы между TransferRate - BandwidthMaxThreshold.
Это решение хорошо, потому что у вас не будет спит, если сеть пользователя уже не так высока, как хотелось бы.
Если вы запускаете Rails на Passenger и Heroku: (если нет, переходите прямо к ответу Ноака Магедмана)
Ответ Ноаха Магедмана был очень полезен для меня, чтобы правильно настроить CloudFront.
Я также установил rack-cors
в точности так, как описано, и, хотя он работал нормально в процессе разработки, команды CURL в работе никогда не возвращали ни одной из конфигураций CORS:
curl -H "Origin: https://tidyme-staging.com.au" -I http://tidyme-staging.com.au/assets/31907B_4_0-588bd4e720d4008295dcfb85ef36b233ee0817d7fe23c76a3a543ebba8e7c85a.ttf
HTTP/1.1 200 OK
Connection: keep-alive
Server: nginx/1.10.0
Date: Wed, 03 Aug 2016 00:29:37 GMT
Content-Type: application/x-font-ttf
Content-Length: 316664
Last-Modified: Fri, 22 Jul 2016 03:31:57 GMT
Expires: Thu, 31 Dec 2037 23:55:55 GMT
Cache-Control: max-age=315360000
Cache-Control: public
Accept-Ranges: bytes
Via: 1.1 vegur
Обратите внимание, что я пингую сервер напрямую без Проходя через CDN, CDN затем после аннулирования всего контента должен просто переслать все, что ответит сервер. Важной строкой здесь является Server: nginx/1.10.0
, которая указывает, что ресурсы обслуживаются nginx, а не Rails. Как следствие, конфигурации rack-cors
не применяются.
Решение, которое сработало для нас, находится здесь: http://monksealsoftware.com/ruby-on-rails-cors-heroku-passenger-5-0-28/
В основном это касалось клонирования и изменения файла конфигурации nginx для Пассажира, что не является идеальным, поскольку эту копию необходимо поддерживать каждый раз, когда Пассажир обновляется и шаблон меняется.
===
Вот краткая сводка:
Перейдите в корневую папку вашего проекта Rails и сделайте копию шаблона конфигурации nginx
cp $(passenger-config about resourcesdir)/templates/standalone/config.erb config/passenger_config.erb
Откройте config/passenger_config.erb
и закомментируйте эту строку
<%# include_passenger_internal_template('rails_asset_pipeline.erb', 8, false) %>
Добавьте эти конфигурации ниже указанной выше строки
### BEGIN your own configuration options ###
# This is a good place to put your own config
# options. Note that your options must not
# conflict with the ones Passenger already sets.
# Learn more at:
# https://www.phusionpassenger.com/library/config/standalone/intro.html#nginx-configuration-template
location ~ "^/assets/.+\.(woff|eot|svg|ttf|otf).*" {
error_page 490 = @static_asset_fonts;
error_page 491 = @dynamic_request;
recursive_error_pages on;
if (-f $request_filename) {
return 490;
}
if (!-f $request_filename) {
return 491;
}
}
# Rails asset pipeline support.
location ~ "^/assets/.+-([0-9a-f]{32}|[0-9a-f]{64})\..+" {
error_page 490 = @static_asset;
error_page 491 = @dynamic_request;
recursive_error_pages on;
if (-f $request_filename) {
return 490;
}
if (!-f $request_filename) {
return 491;
}
}
location @static_asset {
gzip_static on;
expires max;
add_header Cache-Control public;
add_header ETag "";
}
location @static_asset_fonts {
gzip_static on;
expires max;
add_header Cache-Control public;
add_header ETag "";
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, HEAD, OPTIONS';
add_header 'Access-Control-Allow-Headers' '*';
add_header 'Access-Control-Max-Age' 3628800;
}
location @dynamic_request {
passenger_enabled on;
}
### END your own configuration options ###
Измените Procfile
, чтобы включить эту пользовательскую конфигурацию файл
web: bundle exec passenger start -p $PORT --max-pool-size 2 --nginx-config-template ./config/passenger_config.erb
Затем разверните ...
===
Если вы знаете лучшее решение, пожалуйста, оставьте в комментариях.
После реализации команда CURL дала следующий ответ:
curl -H "Origin: https://tidyme-staging.com.au" -I http://tidyme-staging.com.au/assets/31907B_4_0-588bd4e720d4008295dcfb85ef36b233ee0817d7fe23c76a3a543ebba8e7c85a.ttf
HTTP/1.1 200 OK
Connection: keep-alive
Server: nginx/1.10.0
Date: Wed, 03 Aug 2016 01:43:48 GMT
Content-Type: application/x-font-ttf
Content-Length: 316664
Last-Modified: Fri, 22 Jul 2016 03:31:57 GMT
Expires: Thu, 31 Dec 2037 23:55:55 GMT
Cache-Control: max-age=315360000
Cache-Control: public
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, HEAD, OPTIONS
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 3628800
Accept-Ranges: bytes
Via: 1.1 vegur
У меня была та же проблема, и мне удалось ее решить.
Вы правильно сказали Cloudfront разрешить эти заголовки, но вы не добавили эти заголовки туда, где Cloudfront получает шрифт. Да, ваши исходные заголовки разрешены, но Heroku все равно не отправляет эти заголовки со шрифтом.
Чтобы это исправить, вам нужно добавить правильные заголовки CORS к шрифту на Heroku. К счастью, это довольно легко.
Сначала добавьте камень rack/cors
в ваш проект. https://github.com/cyu/rack-cors
Затем настройте сервер Rack для загрузки и настройки CORS для любых ресурсов, которые он обслуживает. Добавьте следующее после предварительной загрузки приложения в config.ru
require 'rack/cors'
use Rack::Cors do
allow do
origins '*'
resource '/cors',
:headers => :any,
:methods => [:post],
:credentials => true,
:max_age => 0
resource '*',
:headers => :any,
:methods => [:get, :post, :delete, :put, :patch, :options, :head],
:max_age => 0
end
end
. Это устанавливает любые ресурсы, возвращаемые из Heroku, для применения соответствующих заголовков CORS. Вы можете ограничить применение заголовков в зависимости от вашего файла и требований безопасности.
После развертывания перейдите в Cloudfront и начните аннулирование всего, что ранее давало вам ошибку разрешения CORS. Теперь, когда Cloudfront загружает свежую копию из Heroku, у него будут правильные заголовки, и Cloudfront передаст эти заголовки клиенту, как ранее было настроено с вашими Origin
разрешениями.
Чтобы убедиться, что вы обслуживаете правильные заголовки со своего сервера, вы можете использовать следующую команду curl для проверки ваших заголовков: curl -I -s -X GET -H "Origin: www.yoursite.com" http://www.yoursite.dev:5000/assets/fonts/myfont.svg
Вы должны увидеть возвращенные следующие заголовки:
Access-Control-Allow-Origin: www.yoursite.com
Access-Control-Allow-Methods: GET, POST, DELETE, PUT, PATCH, OPTIONS, HEAD
Access-Control-Max-Age: 0
Access-Control-Allow-Credentials: true
Вот репозиторий, демонстрирующий использование пользовательского шрифта с Rails 5.2, который работает на Heroku. Это идет дальше и оптимизирует обслуживание шрифтов, чтобы быть максимально быстрым в соответствии с https://www.webpagetest.org/
https://github.com/nzoschke / edgecors
app/assets/fonts
@font-face
в файл scss и использовать font-url
помощник Из app/assets/stylesheets/welcome.scss
:
@font-face {
font-family: 'Inconsolata';
src: font-url('Inconsolata-Regular.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
body {
font-family: "Inconsolata";
font-weight: bold;
}
Я использую CloudFront, добавленный с Heroku Edge addon .
Если вы используете свой собственный CloudFront, не забудьте настроить его так, чтобы он перенаправлял заголовок браузера Origin
на исходный сервер.
Сначала настройте префикс CDN и заголовки Cache-Control
по умолчанию в production.rb
:
Rails.application.configure do
# e.g. https://d1unsc88mkka3m.cloudfront.net
config.action_controller.asset_host = ENV["EDGE_URL"]
config.public_file_server.headers = {
'Cache-Control' => 'public, max-age=31536000'
}
end
Если вы попытаетесь получить доступ к шрифту с URL-адреса herokuapp.com на URL-адрес CDN, вы получите Ошибка CORS в вашем браузере:
Доступ к шрифту в ' https://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttf ' from origin ' https://edgecors.herokuapp.com 'заблокировано политикой CORS: в запрошенном ресурсе отсутствует заголовок «Access-Control-Allow-Origin». edgecors.herokuapp.com/ GET https://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttf net :: ERR_FAILED
Поэтому настройте CORS, чтобы разрешить доступ к шрифт от Heroku к URL CDN:
module EdgeCors
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 5.2
config.middleware.insert_after ActionDispatch::Static, Rack::Deflater
config.middleware.insert_before 0, Rack::Cors do
allow do
origins %w[
http://edgecors.herokuapp.com
https://edgecors.herokuapp.com
]
resource "*", headers: :any, methods: [:get, :post, :options]
end
end
end
end
Конвейер ресурсов создает файл .ttf.gz
, но не обслуживает его. Этот патч обезьяны заменяет белый список gzip конвейера ресурсов на черный список:
require 'action_dispatch/middleware/static'
ActionDispatch::FileHandler.class_eval do
private
def gzip_file_path(path)
return false if ['image/png', 'image/jpeg', 'image/gif'].include? content_type(path)
gzip_path = "#{path}.gz"
if File.exist?(File.join(@root, ::Rack::Utils.unescape_path(gzip_path)))
gzip_path
else
false
end
end
end
Конечным результатом является файл нестандартного шрифта в app/assets/fonts
, который подается из долгоживущего кеша CloudFront.