ActionCable 是 WebSocket 协议最好单独起服务,从兼容性考虑:
sidekiq-worker-killer
https://darkreader.org 自己调呀。
难招是钱没给到位。
# Gemfile
gem "anycable-rails", "~> 0.6.2"
gem "google-protobuf", "~> 3.7"
gem "jwt", "~> 2.1"
# Procfile
bundle exec anycable --server-command="anycable-go --headers=Upgrade,Host,Referer,User-Agent,X-Forwarded-For,X-Real-IP,X-Request-Id,Remote_addr,Origin,Connection,Authorization,Sec-WebSocket-Protocol,Sec-WebSocket-Key,Sec-WebSocket-Accept --host=localhost --port 3334"
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/assets/compiled/action_cable.min.js"></script>
<script type="application/javascript">
(function() {
this.App || (this.App = {});
App.initialize = (async () => {
const accessToken = await getToken();
ActionCable.INTERNAL.protocols.push(accessToken.auth.access_token);
return ActionCable.createConsumer("ws://localhost:3334/cable");
})();
}).call(this);
});
</script>
token = request.headers["HTTP_SEC_WEBSOCKET_KEY"].to_s.split(", ").last
牛逼!
50 ~ 80 万年薪,Java 领域常见,再看看我们招聘板块,35 万顶天啦~(≧▽≦)/~啦啦啦
# frozen_string_literal: true
# Redis > .env > default
# FeatureToggle.fetch('ROLE_MAPPING') { { "read" => ["list", "read"], "list" => ["list", "read", "write"] } }
# FeatureToggle.fetch('WHITELIST') { ["23","33","43","53"] }
# FeatureToggle.fetch('HACK_ENABLE') { false }
module FeatureToggle
class << self
def fetch(key)
return read(key) if exists?(key)
load ENV.fetch(key.upcase) { block_given? ? yield : nil }
end
def read(key)
data = client.get(key.upcase)
data = ENV.fetch(key.upcase) { block_given? ? yield : nil } if data.nil?
load data
end
def write(key)
return nil unless block_given?
data = yield
body = data.is_a?(String) ? data : Oj.dump(data)
client.set(key.upcase, body)
data
end
def delete(key)
if exists?(key)
data = read(key)
client.del(key.upcase)
data
end
end
def keys
client.keys
end
private
def load(data)
return Oj.load(data) if json?(data)
return data.to_b if bool?(data)
data
end
def exists?(key)
client.exists(key.upcase)
end
def json?(data)
data =~ %r(^(\{|\[)(.*)(\]|\})$)
end
def bool?(data)
data =~ %r((true|false|yes|no|on|off))i
end
def client
@client ||= Redis::Namespace.new(NAMESPACE, redis: Redis.current)
end
# redis key
NAMESPACE = [Rails.application.class.parent_name.underscore, Rails.env, "FeatureToggle"].join(":").freeze
end
end
tus-ruby-server
app/models/concerns/soft_delete.rb
这个人?他可是 sidekiq 的作者
场地里不提供 WiFi
shrine + tus + minio
行情
你自己搞个博客不如去“简书”开专栏
我用 Octotree
最近招人的公司不少呢
多谢 @Reigihnius 解答
# /etc/letsencrypt/options-ssl-nginx.conf
ssl_session_cache shared:le_nginx_SSL:1m;
ssl_session_timeout 1440m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES128-SHA ECDHE-ECDSA-AES256-SHA ECDHE-ECDSA-AES128-SHA256 ECDHE-ECDSA-AES256-SHA384 ECDHE-RSA-AES128-GCM-SHA256 ECDHE-RSA-AES256-GCM-SHA384 ECDHE-RSA-AES128-SHA ECDHE-RSA-AES128-SHA256 ECDHE-RSA-AES256-SHA384 DHE-RSA-AES128-GCM-SHA256 DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES128-SHA DHE-RSA-AES256-SHA DHE-RSA-AES128-SHA256 DHE-RSA-AES256-SHA256 EDH-RSA-DES-CBC3-SHA";
#59 楼 @JoostShao 已修改原贴,在主题上加了 ppt 的链接。
$(document).on 'ready page:load', -> # 加载且缓存。
App.config()
App.init()
return
$(document).on 'page:change turbolinks:load', -> # 页面 change 后执行。
if App.weixin()
$('body').on 'click touchstart mousedown', 'a[href*="https://itunes.apple.com"]', (e) ->
e.stopPropagation()
e.preventDefault()
$('#wechat-modal').modal 'show'
return
switch true
when $('body.photos').length > 0
photo = new (App.Photo)
if $('.photos.index').length > 0
photo.uploader()
photo.index currentPage
when $('body.episodes').length > 0
episode = new (App.Episode)
if $('.episodes.index').length > 0
episode.index currentPage
else if $('.episodes.show').length > 0
App.hide_nav()
episode.show episodeId
when $('body.orders').length > 0
order = new (App.Order)
if $('.orders.index').length > 0
order.index currentPage
else if $('.orders.show').length > 0
App.hide_nav()
order.show orderId
return
stop_all_streams
加在 stream_from
上面。passenger_enabled on;
passenger_app_env production;
passenger_app_type rack;
passenger_app_group_name websocket;
passenger_startup_file /home/deploy/ruby/rails/<appname>/current/cable/config.ru;
passenger_force_max_concurrent_requests_per_process 0
# -*- encoding: utf-8 -*-
require ::File.expand_path('../../config/environment', __FILE__)
Rails.application.eager_load!
require 'action_cable/process/logging'
# See https://www.phusionpassenger.com/library/config/tuning_sse_and_websockets/
if defined?(::PhusionPassenger)
PhusionPassenger.advertised_concurrency_level = 0
end
run ActionCable.server
passenger_force_max_concurrent_requests_per_process 0;
吱吱