Ruby on Rails 확장 성 / 성능?
저는 한동안 PHP를 사용 해왔고 훌륭한 프레임 워크 인 CodeIgniter와 잘 사용했습니다. 저는 새로운 개인 프로젝트를 시작하고 있으며 마지막으로 무엇을 사용할지 고려 중이었습니다 (PHP 대 ROR) 저는 ROR이 가지고있는 확장 성 문제 때문에 PHP를 사용했습니다. 특히 Twitter 개발자가 그것에 대해 말한 내용을 읽은 후에는 특히 그렇습니다. ROR에서 확장 성이 여전히 문제입니까, 아니면 개선 되었습니까?
새로운 언어를 배우고 싶은데 ROR이 흥미로워 보입니다. PHP는 작업을 완료하지만 모든 사람이 구문과 구성을 알기 때문에 모호하고 하나의 큰 해킹처럼 느껴집니다.
Ryan Doherty의 답변을 조금 확장하려면 ...
저는 일상적인 작업 (.NET / C #)을 위해 정적으로 형식화 된 언어로 작업하고 Ruby를 부수적으로 사용합니다. 현재 근무하기 전에 저는 뉴욕 타임즈 신디케이션 서비스에서 일하는 루비 개발 회사의 수석 프로그래머였습니다. 그 전에는 PHP에서도 작업했습니다 (아주 오래 전).
간단히 말해서, 저는 레일 (그리고 더 일반적으로 루비) 성능 문제와 몇 가지 다른 대안을 직접 경험했습니다. Ryan이 말했듯이 자동으로 확장되지는 않습니다. 병목 현상을 찾는 데에는 작업과 엄청난 인내가 필요합니다.
우리가 다른 사람들과 심지어 우리 자신에게서 본 성능 문제의 대부분은 ORM 계층에서 성능이 느린 쿼리를 처리하고있었습니다. Rails / ActiveRecord에서 Rails / DataMapper로, 마지막으로 Merb / DM으로 이동했습니다. 각 반복은 단순히 기본 프레임 워크로 인해 더 빨라졌습니다.
캐싱은 성능면에서 놀라운 일입니다. 안타깝게도 데이터를 캐시 할 수 없습니다. 캐시는 최대 5 분마다 효과적으로 무효화됩니다. 우리 사이트의 거의 모든 부분이 동적이었습니다. 그렇게 할 수 없다면 아마도 우리의 경험에서 배울 수있을 것입니다.
우리는 데이터베이스 색인을 심각하게 미세 조정하고, 쿼리가 어리석은 일을하지 않는지 확인하고, 절대적으로 필요한 것보다 더 많은 쿼리를 실행하지 않는지 확인해야했습니다. "매우 어리석은 일"이라고 말하면 1 + N 쿼리 문제를 의미합니다.
#1 query
Dog.find(:all).each do |dog|
#N queries
dog.owner.siblings.each do |sibling|
#N queries per above N query!!
sibling.pets.each do |pet|
#Do something here
end
end
end
DataMapper는 위의 문제를 처리하는 훌륭한 방법입니다 ( 1 + N 문제가 없습니다 ).하지만 더 나은 방법은 두뇌를 사용하고 다음과 같은 쿼리를 중지하는 것입니다. D 원시 성능이 필요할 때 대부분의 ORM 레이어는 매우 사용자 지정 쿼리를 쉽게 처리하지 못하므로 직접 작성하는 것이 좋습니다.
우리는 또한 상식적인 일을했습니다. 우리는 성장하는 데이터베이스를 위해 강력한 서버를 구입하여 전용 상자로 옮겼습니다. 우리는 또한 수많은 처리와 데이터를 지속적으로 가져와야했습니다. 우리는에 우리의 처리를 이동 그 뿐만 아니라 자신의 상자. 또한 데이터 가져 오기 유틸리티를 위해 전체 스택을로드하는 것을 중단했습니다. 우리는 꼭 필요한 것만을 멋지게로드했습니다 (따라서 메모리 오버 헤드를 줄였습니다!).
이미 알 수없는 경우는 / 레일 / Merb는 루비에 관해서 ... 일반적으로, 당신은 확장 할 필요가 밖으로 문제에 하드웨어를 던지고. 그러나 결국 하드웨어는 저렴합니다. 엉뚱한 코드에 대한 변명의 여지가 없습니다! :디
그리고 이러한 어려움에도 불구하고 제가 도울 수 있다면 저는 개인적으로 다른 프레임 워크에서 프로젝트를 시작하지 않을 것입니다. 나는 언어를 좋아하고 매일 그것에 대해 계속해서 배웁니다. 그것은 C #이 더 빠르지 만 C #에서 얻지 못하는 것입니다.
나는 또한 오픈 소스 도구, 언어로 작업을 시작하는 데 드는 저렴한 비용, 무언가를 가져와 시장성 여부를 확인하는 데 드는 저렴한 비용을 즐깁니다. 항상 우아하고 아름다운 언어로 작업하면서 ...
결국, 프레임 워크를 선택할 때 하루 종일 살고, 호흡하고, 먹고, 잠을 자고 싶은 것이 전부입니다. Microsoft의 사고 방식이 마음에 들면 .NET으로 이동하십시오. 오픈 소스를 원하지만 여전히 구조를 원한다면 Java를 사용해보십시오. 동적 언어를 원하고 여전히 루비보다 구조가 더 많으면 파이썬을 사용해보십시오. 우아함을 원한다면 Ruby를 사용해보세요. (I kid, I kid ... 법안에 맞는 다른 많은 우아한 언어가 있습니다. 화염 전쟁을 시작하려고하지 않습니다. : D)
지옥, 그들 모두를 시도하십시오! 나는 최적화에 대해 조기에 걱정하는 것이 프레임 워크를 선택하거나 선택하지 않아야하는 이유가 아니라는 위의 답변에 동의하는 경향이 있지만 이것이 유일한 답변이라는 데 동의하지 않습니다.
요컨대, 극복해야 할 어려움이 있지만 언어의 우아함 인 imho가 그 단점을 훨씬 능가합니다.
소설은 미안하지만 성능 문제로 돌아왔다. 그것은 수 있습니다 극복 될 수있다. 그러니 두려워하지 마십시오.
RoR은 방대한 웹 사이트에서 많이 사용되고 있지만 다른 언어 나 프레임 워크 와 마찬가지로 많은 사용자에게 확장하려면 좋은 아키텍처 (db 확장, 캐싱, 튜닝 등)가 필요합니다.
쉽게 확장 할 수 있도록 RoR에 몇 가지 사소한 변경이 있었지만 마술처럼 확장 될 것이라고 기대하지 마십시오. 모든 웹 사이트에는 다른 크기 조정 문제가 있으므로 크기를 조정하려면 몇 가지 작업을해야합니다.
빠른 개발, 쉬운 디버깅, 쉬운 배포, 좋은 도구 등 프로젝트에 성공할 수있는 가장 좋은 기회를 제공 할 기술을 개발하십시오 (요점이 새로운 언어를 배우는 것이 아니라면).
한 달에 수천만 개의 고유 항목을 얻는 경우 항상 두 사람을 고용하고 필요한 경우 다른 기술로 다시 작성할 수 있습니다.
... 당신은 캐시 에서 갈퀴 -ing 될 것입니다 (미안합니다-저항 할 수 없습니다!)
우선, Ruby on Rails는 완전한 웹 애플리케이션 프레임 워크이기 때문에 Rails를 Symfony, CodeIgniter 또는 CakePHP와 비교하는 것이 더 합리적 일 것입니다. PHP 또는 PHP 프레임 워크와 비교할 때 Rails 애플리케이션은 작고 깨끗하며 읽기 쉽다는 장점을 제공합니다. PHP는 작은 개인 페이지 (원래 "개인 홈 페이지"를 의미 함)에 적합하며 Rails는 대규모 사이트를 구축하는 데 사용할 수있는 완전한 MVC 프레임 워크입니다.
Ruby on Rails 는 유사한 PHP 프레임 워크보다 더 큰 확장 성 문제 가 없습니다 . Rails와 PHP는 비슷한 수의 객체에서 작동하는 적당한 수의 사용자 (10,000-100,000) 만있는 경우 잘 확장됩니다. 수천 명의 사용자에게는 고전적인 모 놀리 식 아키텍처로 충분합니다. 약간의 M & M (Memcached 및 MySQL)으로 수백만 개의 객체를 처리 할 수도 있습니다. M & M 아키텍처는 MySQL 서버를 사용하여 쓰기를 처리하고 Memcached를 사용하여 높은 읽기로드를 처리합니다. 정규화 된 관계형 테이블 (또는 기껏해야 SQL 마스터 / 다중 읽기 슬레이브 설정)을 사용하는 단일 SQL 서버 인 기존 스토리지 패턴은 더 이상 대규모 사이트에서 작동하지 않습니다.
Google, Twitter 및 Facebook과 같은 수십억 명의 사용자가 있다면 아마도 분산 아키텍처가 더 좋을 것입니다. 제한없이 애플리케이션을 확장하려면 저렴한 상용 하드웨어를 기반으로 사용하고, 애플리케이션을 서비스 집합으로 나누고, 각 구성 요소 또는 서비스를 자체적으로 확장 가능하게 유지하고 (모든 구성 요소를 확장 가능한 서비스로 설계) 애플리케이션에 대한 아키텍처. 그런 다음 NoSQL 데이터베이스 및 분산 해시 테이블 (DHT)과 같은 적절한 확장 가능한 데이터 저장소가 필요하며,이를 사용하려면 정교한 맵 축소 알고리즘이 필요하며 SOA, 외부 서비스 및 메시징을 처리해야합니다. PHP 나 Rails는 여기서 마법의 총알을 제공하지 않습니다.
RoR의 단점은 Alexa의 상위 100 위 안에 들지 않는 한 확장 성 문제가 없다는 것입니다. Phusion, Passenger 또는 Mongrel을 짜낼 수 없다면 공유 호스팅의 안정성에 더 많은 문제가 있습니다.
잠시 시간을내어 Twitter 사람들이 처리해야하는 문제를 살펴본 다음 앱을 해당 수준으로 확장해야하는지 자문 해보십시오.
그런 다음 어쨌든 Rails에서 빌드하십시오. 트위터 수준의 볼륨에 도달하면 성능 최적화 옵션을 고려할 수있는 행복한 위치에있을 것입니다. 적어도 좋은 언어로 적용 할 것입니다!
You can't compare PHP and ROR, PHP is a scripting language as Ruby, and Rails is a framework as CakePHP.
Stated that, I strongly suggest you Rails, because you will have an application strictly organized in MVC pattern, and this is a MUST for your scalability requirement. (Using PHP you had to take care about the project organization on your own).
But for what about scalability, Rails it's not just MVC: For instance, you can start to develop your application with a database, changing it on road without any effort (in the most part of cases), so we can state that a Rails application is (almost) database indipendent because it's ORM (that allow you to avoid database query), you can do a lot of other stuff.
(take a look to this video http://www.youtube.com/watch?v=p5EIrSM8dCA )
Just wanted to add some more info to Keith Hanson's smart point about 1 + N problem where he states:
DataMapper is an excellent way to handle the above problem (there are no 1 + N problems with it), but an even better way is to use your brain and stop doing queries like that :D When you need raw performance, most of the ORM layers won't easily handle extremely custom queries, so you might as well hand write them.
Doctrine is one of the most popular ORM's for PHP. It addresses this 1 + N complexity problem intrinsic to ORMs by providing a language called Doctrine Query Language (DQL). This allows you to write SQL like statements that use your existing model relationships. e.g
$q = Doctrine_Query::Create() ->select(*) ->from(ModelA m) ->leftJoin(m.ModelB) ->execute()
I'm getting the impression from this thread that the scalability issues of ROR come down primarily to the mess that ORMs are in with regard to loading child objects - ie the '1+N' problem mentioned above. In the above example that Ryan gave with dogs and owners:
Dog.find(:all).each do |dog|
#N queries
dog.owner.siblings.each do |sibling|
#N queries per above N query!!
sibling.pets.each do |pet|
#Do something here
end
end
end
You could actually write a single sql statement to get all that data, and you could also 'stitch' that data up into the Dog.Owner.Siblings.Pets object heirarchy of your custom-written objects. But could someone write an ORM that did that automatically, so that the above example would incur a single round-trip to the DB and a single SQL Statement, instead of potentially hundreds? Totally. Just join those tables into one dataset, then do some logic to stitch it up. It's a bit tricky to make that logic generic so it can handle any set of objects but not the end of the world. In the end, tables and objects only relate to each other in one of three categories (1:1, 1:many, many:many). It's just that no one ever built that ORM.
You need a syntax that tells the system upfront what children you want to load for this particular query. You can sort of do this with the 'eager' loading of LinqToSql (C#), which is not a part of ROR, but even though that results in one round trip to the DB, it's still hundreds of separate SQL statements the way it has currently been set up. It's really more about the history of ORMs. They just got started down the wrong path with that and never really recovered in my opnion. 'Lazy loading' is the default behavior of most ORMs, ie incurring another round trip for every mention of a child object, which is crazy. Then with 'eager' loading - loading the children upfront, that is set up statically in everything I am aware outside of LinqToSql - ie which children always load with certain objects - as if you would always need the same children loaded when you loaded a collection of Dogs.
You need some kind of strongly-typed syntax saying that this time I want to load these children and grandchilren. Ie, something like:
Dog.Owners.Include()
Dog.Owners.Siblings.Include()
Dog.Owners.Siblings.Pets.Include()
then you could issue this command:
Dog.find(:all).each do |dog|
The ORM system would know what tables it needs to join, then stitch up the resulting data into the OM heirarchy. It's true that you can throw hardware at the current problem, which I'm generally in favor of, but it's no reason the ORM (ie Hibernate, Entity Framework, Ruby ActiveRecord) shouldn't just be better written. Hardware really doesn't bail you out of an 8 round-trip, 100-SQL statement query that should have been one round trip and one SQL statement.
참고URL : https://stackoverflow.com/questions/503684/ruby-on-rails-scalability-performance
'Programing' 카테고리의 다른 글
Android Studio Gradle 프로젝트 "데몬 프로세스를 시작할 수 없음 / VM 초기화" (0) | 2020.10.28 |
---|---|
Ruby에서 <<로 해시에 키 / 값 쌍 추가 (0) | 2020.10.28 |
포착되지 않은 TypeError : Object.values는 함수 JavaScript가 아닙니다. (0) | 2020.10.28 |
Python의 순환 가져 오기 종속성 (0) | 2020.10.28 |
문자열이 C에서 다른 문자열로 시작하는지 확인하는 방법은 무엇입니까? (0) | 2020.10.28 |