μ΄ μ€μ λλ±μ±μ κΈ°λ°μΌλ‘ λͺ¨λ μ΄μ λν΄ μΉ μμΌ λ©μμ§λ₯Ό 보λ λλ€.
μΌλΆ μ΄μ κ±°λν ν μ€νΈ λ€ν λλ JSON κ΅¬μ± μΌ μ μμΌλ―λ‘ μ¬κΈ°μ λͺ κ°μ§ ν©λ¦¬μ μΈ νν° νν°λ₯Ό μΆκ°ν΄μΌν©λλ€.
μ±λμ μ΄λ¦μ ETSμ κ°μΉμ΄λ©° GBκΉμ§λ μμ²λ μ μμ΅λλ€.
κ·Έ λ²κ·Έμ κ΄ν΄μλ κ·Έ κ²μ¬μ κ΄λ ¨μ΄ μλ€κ³ μκ°ν©λλ€.
https://github.com/supabase/realtime/blob/894f4bb8923017467c78803711d8adbef8c090fe/server/lib/realtime/subscribers_notification.ex#L140 -L142
νμ¬ κ΅¬νμμλ μ΅λ 100 κ°μ κΈ°νΈκΉμ§λ§ ν€λ₯Ό νμΈν μ μμ΅λλ€.
κ°μ¬ν©λλ€ @ abc3.
λ¬Έμ λ₯Ό λ§λ€κΈ° μ μ λ΄ μ½λλ₯Ό νμΈν΄μΌν©λλ€ π
μ΄ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ λͺ κ°μ§ ν μ€νΈλ₯Ό μ€μ νκ² μ΅λλ€. @fracek λ λ¬Έμ κ° μμμ νμΈ νμΌλ―λ‘ μ΄λμμ μ€λ₯κ° λ°μνλμ§
ν€ 2500 κΈΈμ΄λ‘ νμΈνμ΅λλ€. λ²κ·Έλ₯Ό μ¬ννλ λ°©λ²μ λ³΄μ¬ μ£Όμλ©΄ κΈ°κΊΌμ΄ μ‘°μ¬νκ² μ΅λλ€. :λΆνλ€:
λλ μ€μκ°μ μλ‘μ΄ λ³΅μ¬λ³ΈμΌλ‘ μμνκ³ (μ»€λ° 894f4bb89230
), μλ² ( mix deps.get
)μ λ
Έλ js μμ ( yarn install
)μ λν depsλ₯Ό μ»μ΅λλ€. node-js μμ ( docker-compose up db
)μμ dbλ₯Ό μμν©λλ€.
μλ²λ₯Ό μμν©λλ€.
PORT=4000 \
HOSTNAME=localhost \
DB_USER=postgres \
DB_HOST=localhost \
DB_PASSWORD=postgres \
DB_NAME=postgres \
DB_PORT=5432 \
DB_PORT=5432 \
SLOT_NAME=TEST_SLOT \
mix phx.server
λ° node-js μμ ( yarn run start
).
λ€μ μ€ν¬λ¦½νΈλ₯Ό μ¬μ©νμ¬ μΌλΆ λ°μ΄ν°λ₯Ό μ½μ ν©λλ€.
import psycopg2
import time
def main():
conn = psycopg2.connect(
host="localhost",
database="postgres",
user="postgres",
password="postgres"
)
cur = conn.cursor()
name = 'name'
cur.execute("INSERT INTO users(name) VALUES(%s)", (name, ))
conn.commit()
main()
node-js μμ λ‘ μ€νΈλ¦¬λ° λ λ°μ΄ν°λ₯Ό λ³Ό μ μμ΅λλ€. λ¬Έμμ΄ κΈΈμ΄λ₯Ό 4000 ( name = 'name' * 1000
)μΌλ‘ λ³κ²½νλ©΄ μλν©λλ€. name = 'name' * 1000000
( 1_000_000
)κΉμ§ λ¬Έμμ΄μ ν¬κΈ°λ₯Ό μ μ§μ μΌλ‘ (10/10) λ립λλ€. λ¨Όμ ν° λ¬Έμμ΄μ μ½μ
νκ³ κ·Έ νμ μμ λ¬Έμμ΄μ μ½μ
νλλ‘ μ€ν¬λ¦½νΈλ₯Ό λ³κ²½νμ΅λλ€.μ΄ κ²½μ°μλ node-jsκ° λ μ€ νλλ₯Ό μμ νμ§ μμ΅λλ€.
import psycopg2
import time
def main():
conn = psycopg2.connect(
host="localhost",
database="postgres",
user="postgres",
password="postgres"
)
cur = conn.cursor()
name = 'name' * 1000000
cur.execute("INSERT INTO users(name) VALUES(%s)", (name, ))
conn.commit()
name = 'name'
cur.execute("INSERT INTO users(name) VALUES(%s)", (name, ))
conn.commit()
main()
λ¬Έμ λ μ±λμ΄ ν° νμ΄λ‘λλ₯Ό μ²λ¦¬ ν μ ββμλ€λ κ²μ λλ€.
λ§μ§λ§ μ€ν μ€ νλλ 볡μ μ§μ°μ νμΈνλ κ²μ λλ€. λ€μ λͺ λ Ήμ μ¬μ©ν©λλ€.
select
slot_name, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS replicationSlotLag, active
from pg_replication_slots ;
μΌλ°μ μΌλ‘ κ²°κ³Όλ λ€μκ³Ό κ°μ΅λλ€.
slot_name | replicationslotlag | active
-----------+--------------------+--------
test_slot | 56 bytes | t
(1 row)
λλ νμ΄μ¬ μ€ν¬λ¦½νΈλ₯Ό ν λ² μ€ννκ³ μ»€μ§λ κ²μ λ΄ λλ€ (μ€ν¬λ¦½νΈλ₯Ό μ€νν λλ§λ€ μ½ 40kB μ© μ»€μ§λλ€). @ w3b6x9 λ κ³ κ° μΈμ€ν΄μ€μμμ΄ ν¬κΈ°κ° μ½ 20MB
μμ½νλ©΄ ν° νμ μ½μ ν λ λ κ°μ§ λμ λλ λ¬Έμ κ° μμ΅λλ€.
λ΄ μΆμΈ‘μ λ κ°μ§ μ£Όμ λ¬Έμ κ° μλ€λ κ²μ λλ€ (μλ§ κ΄λ ¨μ΄μμ μλ μκ³ μλ μλ μμ΅λλ€).
νμ§λ§ name = 'name' * 1000000
λ 40MBμ λΆκ³Όν©λλ€.
μ κ²½μ°μλ μλνμ§λ§ @fracek μμ λ₯Ό ν΅ν΄ λ μμΈν
Btw, λ΄ ν μ€νΈλ ~ 10secμ λ§€μ° ν° μ§μ° μκ°μ 보μ¬μ€λλ€. μμ MBλ₯Ό μ 곡νκΈ°μλ λ무 λ§μ΅λλ€.
export default async (req, res) => {
const values = Array(1000000).fill("name").join('')
const text = `INSERT INTO stress(value) VALUES('${values}') RETURNING id`
const q = await pool.query(text)
res.json(JSON.stringify(q.rows))
}
@ abc3 λ₯Ό ν μ€νΈ ν΄ μ£Όμ μ κ°μ¬ν©λλ€-μ΄ λλ¬ΈμΌ μ μμ΅λλ€ : https://github.com/supabase/realtime/pull/120
Prodμμμ΄ λμμλ³΄κ³ μμμΌλ―λ‘ PRμ λλλ € μΌνμ΅λλ€. μ΄ PRμ λ³ν© ν νμλ μ¬μ ν λλ¦° κ²½μ° μ§μ° μκ°μ μμ ν΄μΌν©λλ€.
λ΄ κ³μ°μμ μ€μλ₯Όνμ΅λλ€ : 40μ΄ μλλΌ 4MB))
μ΄ INSERT INTO users(name) VALUES(repeat('name', 1000000))
ν΅ν΄ μ½μ
ν
μ€νΈ
μ°Ύμμ΄μ!
λλ²κ·Έ μμ€μ ν¬ν¨νκ³ λ€μμ ν¬ν¨νμ§ μλ μλ΅ μκ° :
μ΄ νμ λͺ μ΄ λμ μ€νλ©λλ€.
https://github.com/supabase/realtime/blob/894f4bb8923017467c78803711d8adbef8c090fe/server/lib/realtime/replication.ex#L72 -L73
μμ μ¬νμ μ¬ν ν μ μμ΅λλ€. μ΄λ²€νΈλ μ¬μ ν μΉ μμΌμ ν΅ν΄ μ νλμ§ μμ§λ§ μ μ΄λ μΈμ€ν΄μ€κ° μλ΅νμ§ μμ΅λλ€. μ νμ΄!
λΈλΌμ°μ λ κΈ΄ λ¬Έμμ΄μ λμ½λ©νκ³ λ λλ§νλ λ° μ½κ°μ μκ°μ΄ νμν©λλ€.
μλ₯Ό μ½κ° λ³κ²½νλ©΄ λ λͺ
νν΄μ§ κ²μ
λλ€.
μ΄κ²μ μ κ±°ν΄μΌν©λλ€ :
https://github.com/supabase/realtime/blob/894f4bb8923017467c78803711d8adbef8c090fe/examples/next-js/pages/index.js#L28
κ·Έκ²μ λ체
https://github.com/supabase/realtime/blob/894f4bb8923017467c78803711d8adbef8c090fe/examples/next-js/pages/index.js#L44 -L53
μ
messageReceived(channel, msg) {
console.log('got message')
}
λΈλΌμ°μ μ½μμμ λ©μμ§λ₯Ό μ½μ΅λλ€.
cur = conn.cursor ()
μ΄λ¦ = 'μ΄λ¦'* 1000000
cur.execute ( "INSERT INTO users (name) VALUES (% s)", (name,))
conn.commit ()
@fracek μ΄ μ»΄ν¨ν°μ λ¬Έμ λ₯Ό
λλ λλ²κΉ
νλ λμ κ·Έκ²μ νμΈνλ¬ κ°λ€. λμΌν νΈλμμ
μμ κ° νμ κ°μ΄ 'name' * 1000000
(4MB) μΈ 100 κ°μ νμ μ½μ
νμ΅λλ€.
볡μ κ° μ§νλλ λμ 볡μ μ§μ°μ λͺ¨λ νμΈνμ΅λλ€ (μ½ 5.3MBμμ μΌκ΄μ± μ μ§).
λ° νλ¬μ μ§μ° :
_ μ΄μ κ³ κ°μ DB μΈμ€ν΄μ€λ₯Ό λλ²κΉ ν λ λ³Έ κ²κ³Ό λΉμ·ν©λλ€. 볡μ μ§μ°μ΄ μ¦κ°ν λ€μ μ§μ° (12MB, 16MB, 20MB λ±)μμ μΌκ΄μ±μ μ μ§νκ³ 3-5 λΆ μ¬μ΄μ νλ¬μ μ§μ°μ΄ λ°μν©λλ€ ._
κ½€ κΈ°λ€λ Έλ€κ° λ©μμ§λ₯Ό λ°μμ΅λλ€. κ°κ°μλ 'name' * 1000000
(4MB) κ°μ΄ ν¬ν¨λμ΄ μμ΅λλ€. λν κ° 4MB κ° (~ 90 μ΄)μ μ λ¬νλ 100 κ°μ λ©μμ§λ₯Ό 보λ΄λ κ²κ³Ό λΉκ΅νμ¬ λ³΅μ μ 걸리λ μκ° (~ 30 λΆ)μ μΆμ νμ΅λλ€.
짧μ μκ° λ΄μ μ¬λ¬ κ°μ ν° λ©μμ§λ₯Ό λ³΄λΌ λ Phoenix μ±λμμ μ°κ²° λκΉ λ¬Έμ κ°μλ μ¬λμ μ°Ύμμ΅λλ€. ν μ¬μ©μκ° μΈκΈνμ΅λλ€.
- Phoenix μ λ 60 μ΄ μ λμ νμ μμμ μ¬μ©νμ¬ ννΈ λΉνΈ μ λμ λ©μμ§λ₯Ό μμ νλ€κ³ μκ°ν©λλ€.
- λ¨μΌ λ©μμ§λ₯Ό 보λ΄λ λ° μκ°μ΄ λ μ€λ 걸리면 νΌλμ€λ νμ΄νκ° λ©μ·κ±°λ μλ λ κ²μΌλ‘ μκ°νμ¬ μ£½μ λλ€.
κ·Έλ¦¬κ³ λ€λ₯Έ μ¬μ©μ μΈ sasajuric
λ μμ μκ² μ ν©ν λ€μ μ루μ
μ μ 곡νμ΅λλ€.
- μλ¦¬μΌ λΌμ΄μ μΈλΆμμ νμ΄λ‘λ μμΆ / μμΆ ν΄μ
- : erlang.term_to_binary λ° : erlang.binary_to_termμ μ¬μ©νμ¬ λ©μμ§ μ§λ ¬ν / μ μ§λ ¬ν
μ§κΈμ λͺ
μ¬ν΄μΌ ν μ¬νμ΄μ§λ§ λμ λΉλμ λ§λν νμ΄λ‘λλ‘ μΈν΄ λ©μμ§κ° μ μ‘λμ§ μλλ€λ μ¬μ€μ λ°κ²¬ ν κ²½μ° κ°μ₯ λ¨Όμ ν μμλ κ²μ μ΅μ λ΄μ₯ μ§λ ¬ λ³νκΈ° Phoenix.Socket.V2.JSONSerializer
( sasajuric
μ μν μμ
μ μννκΈ° μ μ νμ¬ V1
)λ₯Ό μ¬μ©νκ³ μμ΅λλ€.
λ€μκ³Ό κ°μ μ΄μ λλ¬ΈμΌ μ μμ΅λλ€. # 120
μ, realtime
μλ²κ° κ³μ λ€μ μμλκ³ μꡬ 볡μ μ¬λ‘―μΌλ‘ μ€λ¨ λ λΆλΆμ μ ννλ©΄ λ μ€λ 걸리λ κ²μ λ³Ό μ μμ΅λλ€ (μλ μνλ‘ λμκ° μμλ κ²½μ°). :undefined.handle_message/4
μ€λ₯λ‘ μΈν μν) κ³ κ°μ΄ λ©μμ§λ₯Όλ°μ μ μμ΅λλ€.
κ³ κ°μ΄ ν λ²μ μμ²λ μμ μ λ°μ΄νΈλ₯Ό μννλ€λ μ μ κ³ λ €νλ©΄ μ΄κ²μ μ μμΌ μ μμ΅λλ€ ( @kiwicopple μ΄λκ°μμ μΈκΈ ν κ² κ°μ΅λλ€). # 120μ΄ λ³ν©λμμΌλ©° 곧 κ³ κ°μ μν΄ λ°°ν¬ λ μμ μ΄λ―λ‘ κ³μ λͺ¨λν°λ§νλ©΄λ©λλ€.
@ abc3 : btw, λΌμ°ν μκ° μ°¨νΈ # 118 μ΄μλ
κ°μ¬! λ΄ κΈ°μ¬κ° λμμ΄λμ΄ κΈ°μ©λλ€.
μ νμ λ¬Έμ κ° λ€μ λ°μνλ©΄ λͺ¨λν°λ§ κ²°κ³Όλ₯Ό 곡μ νμμμ€.
μ€λλ λΉ λ₯Έ μ루μ
λ μκ°μ μΆκ°ν©λλ€ https://github.com/supabase/realtime/issues/8#issuecomment -564551365
https://github.com/supabase/realtime/blob/af6344c7746e8a8af6a11a9b498721c1f97e339b/server/lib/realtime_web/channels/realtime_channel.ex#L21 -L24
λ°λΌμ μμ μ½λμ Realtime.SubscribersNotification.notify_subscribers
ꡬνμ μ μ¬ν λ°μ΄ν°μ μ¬λ¬ 볡μ¬λ³Έμ 보λ
λλ€.
μλ₯Ό λ€μ΄ users
ν
μ΄λΈμ νμ μ½μ
νλ©΄ this.addChannel('realtime:*')
λ° this.addChannel('realtime:public:users')
κ°μ
ν ν΄λΌμ΄μΈνΈλ 4 κ°μ λ©μμ§λ₯Όλ°μ΅λλ€.
νλμ λ©μμ§κ° 4MBμ΄λ©΄ μλ²λ 16MBλ₯Ό 보λ
λλ€.
κ°μ₯ μ μ©ν λκΈ
μ°Ύμμ΄μ!
λλ²κ·Έ μμ€μ ν¬ν¨νκ³ λ€μμ ν¬ν¨νμ§ μλ μλ΅ μκ° :
μ΄ νμ λͺ μ΄ λμ μ€νλ©λλ€.
https://github.com/supabase/realtime/blob/894f4bb8923017467c78803711d8adbef8c090fe/server/lib/realtime/replication.ex#L72 -L73