Статьи

Как создать приложение Shortlink с помощью Ruby и Redis

В этом руководстве мы будем создавать быстрое короткое веб-приложение с Ruby, веб-фреймворком Sinatra и базой данных Redis . В конце этого учебного пособия вы получите очень простое, высокопроизводительное шортлинковое веб-приложение, которое очень легко масштабировать.


Чтобы следовать этому уроку, вам потребуется установить Ruby в вашей системе (я использую 1.9.2), а также гемы sinatra и redis и Redis.

Если у вас еще не установлен Ruby в вашей системе, вы сможете установить его относительно легко. Пользователям OS X, Debian или CentOS может потребоваться скомпилировать более новую версию Ruby. Это довольно простой процесс.

Обратитесь сюда, чтобы узнать, как установить Ruby через RVM.

Теперь вам нужно установить необходимые Ruby Gems. Gems — это удобный способ установки практически любой доступной библиотеки Ruby. Просто введите следующее в окне терминала, чтобы установить необходимые гемы:

1
gem install sinatra redis

Нам также нужно будет установить и скомпилировать Redis. Не волнуйтесь, он очень маленький и занимает около 15 секунд для компиляции на моей машине.

1
2
3
4
5
6
wget http://redis.googlecode.com/files/redis-2.0.4.tar.gz
   tar zfx redis-2.0.4.tar.gz
   cd redis-2.0.4
   make
   sudo make install
   cd ..

Вы можете запустить сервер Redis, введя redis-server в свой терминал, и, если вы хотите поиграть с Redis, попробуйте redis-cli .


Одна из замечательных особенностей Sinatra — это то, как быстро и легко она запускает простые маленькие приложения — это почти глупо!

Код самого приложения для коротких ссылок не будет очень длинным, поэтому его должно быть действительно легко понять. Не беспокойтесь, если сначала вы этого не поймете, я вскоре объясню, как все это работает.

Создайте папку для вашего веб-приложения — я назвал мою redis-ruby-shortlink — и поместите в нее следующие файлы.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
require ‘sinatra’
   require ‘redis’
 
   redis = Redis.new
 
   helpers do
     include Rack::Utils
     alias_method :h, :escape_html
 
     def random_string(length)
       rand(36**length).to_s(36)
     end
   end
 
   get ‘/’ do
     erb :index
   end
 
   post ‘/’ do
     if params[:url] and not params[:url].empty?
       @shortcode = random_string 5
       redis.setnx «links:#{@shortcode}», params[:url]
     end
     erb :index
   end
 
   get ‘/:shortcode’ do
     @url = redis.get «links:#{params[:shortcode]}»
     redirect @url ||
   end

Вот и все. Довольно просто, а?

В этом небольшом приложении Sinatra, приведенном выше, я сделал несколько ключевых вещей. В первых двух строках я привожу библиотеки, которые нам нужны — sinatra и redis. В строке 4 я устанавливаю соединение с сервером Redis, прослушивая localhost. Строки после этого, где все это начинает становиться интересным!

В Sinatra вы можете указать помощников, которые запускаются каждый раз, когда выполняется один из ваших маршрутов (те, которые получают и отправляют части). Мы можем поместить все, что нам может понадобиться часто, в блок помощников. В своем блоке помощников я связал h с escape-hhml Rack и определил метод для генерации случайной буквенно-цифровой строки определенной длины.

Далее идут маршруты . Первый маршрут довольно прост. Всякий раз, когда клиент делает GET-запрос к / , он просто отображает страницу index.erbдобавил источник ниже).

Следующий маршрут — это то, где происходят хорошие вещи. Сначала мы удостоверимся, что пользователь действительно ввел URL в поле URL. Если это так, мы генерируем случайный короткий код длиной пять символов, вызывая метод random_string, который мы определили ранее. Затем мы сообщаем Redis setnx ( Установить, если n e x ists), ключ, представляющий наш шорткод для его URL. Redis — это действительно быстрая и простая база данных ключ / значение или база данных NoSQL . Эти базы данных предназначены для очень сложных операций поиска по ключу / значению, и, поскольку они отбрасывают большую часть сложности SQL, они могут делать это намного быстрее. Часть ключа ‘links:’ не обязательна, но рекомендуется разделять ключи Redis на пространства имен, поэтому, если позднее вы решите сохранить больше информации в той же базе данных, вам не придется беспокоиться о конфликтах. , После всего этого мы отображаем ту же страницу index.erb, что и раньше. Обратите внимание, что если пользователь ничего не вводит, этот маршрут делает то же самое, что и предыдущий маршрут.

Окончательный маршрут запускается, когда клиент посещает короткую ссылку. Этот маршрут вводит то, что называется параметром URL . Например, когда клиент посещает / foobar, часть : shortcode маршрута соответствует ‘foobar’. Мы можем получить доступ к параметрам URL так же, как и любой другой параметр — хэш параметров . Мы ищем шорткод в базе данных Redis. Если нет такого ключа, к которому мы пытаемся получить доступ, Redis вернет ноль . Следующая строка перенаправляет либо на URL, который мы выбрали из Redis (если он существует), либо на домашнюю страницу, если нет.

index.erb в основном скучная разметка, хотя в ней есть несколько строк, на которые я хотел бы указать. erb означает встроенный Ruby и позволяет нам смешивать Ruby и HTML, как вы это делаете с PHP.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<!DOCTYPE html>
   <html>
   <head>
       <title>Shortlink App</title>
       <style>
       body {
           font-family:»Gill Sans», «Gill Sans MT», Sans-Serif;
       }
       .container {
           width:400px;
           margin:120px auto 0px auto;
       }
       h1 {
           width:400px;
           margin-bottom:12px;
           text-align:center;
           color:#ff4b33;
           font-size:40px;
           padding-bottom:8px;
           border-bottom:2px solid #ff4b33;
       }
       form {
           display:block;
           width:400px;
       }
       input {
           display:block;
           float:left;
           padding:8px;
           font-size:16px;
       }
       #url {
           width:280px;
           margin-right:12px;
       }
       #submit {
           width:88px;
           border:none;
           background:#ff4b33;
           padding:10px;
       }
       #submit:hover {
           background:#ff7866;
       }
       .clear {
           height:1px;
           width:400px;
           clear:both;
       }
       .result {
           clear:both;
           width:400px;
           margin-top:12px;
           border-top:2px solid #ff4b33;
           padding-top:12px;
           text-align:center;
       }
       .result a {
           font-size:24px;
           display:block;
           margin-top:8px;
           color:#ff2d11;
           background:#ffd2cc;
           padding:8px;
       }
       </style>
   </head>
   <body>
       <div class=»container»>
           <h1>shortlink app</h1>
           <form method=»post»>
               <input type=»text» value=»<%= h(params[:url]) %>» name=»url» id=»url» />
               <input type=»submit» value=»shorten» id=»submit» />
           </form>
           <div class=»clear»></div>
           <% if @shortcode %>
           <div class=»result»>
               Your shortened URL is:
               <a href=»http://my-shortlink-app.com/<%= @shortcode %>»>http://my-shortlink-app.com/<%= @shortcode %></a>
           </div>
           <% end %>
       </div>
   </body>

Одно из различий между erb и PHP, которое вы, возможно, уже заметили (кроме разных языков), заключается в том, где PHP использует <? и <? = , erb использует <% и <? = . Единственное, что интересно в index.erb — это блок if, который отображает только ту часть страницы, на которой показана короткая ссылка, если определена переменная @shortcode . Это позволяет нам использовать один и тот же вид для всего. Еще один момент, который стоит отметить: мы позаботились о экранирующих параметрах HTML [: url] , чтобы не стать жертвой XSS-атаки. Помимо этих пунктов, это по сути стандартная веб-страница.


Одна вещь, которую я кратко упомянул во введении этого урока, — насколько легко мы можем масштабировать, благодаря Redis. В то время как масштабирование до нескольких баз данных SQL является сложным делом, масштабирование Redis на самом деле довольно тривиально . Это прямой результат простоты Редиса. Если вам нужно масштабировать до нескольких Redises, добавьте следующее в вашу конфигурацию Redis:

1
slaveof master-redis-server.my-shortlink-app.com 6379

После того, как вы настроили несколько ведомых устройств, это небольшое изменение в приложении Sinatra выше, чтобы каждый экземпляр Sinatra подключался к случайному серверу Redis (если вы находитесь на этапе, когда вам нужно масштабировать Redis, я собираюсь предположить, что вам уже пришлось развернуть несколько экземпляров Sinatra.;)


Я надеюсь, что это руководство оказалось полезным для вас, хотите ли вы запустить свой собственный сервис коротких ссылок или вы просто интересуетесь новейшими передовыми технологиями, доступными для нас, веб-разработчиков. В этом уроке я рассмотрел довольно красивое программное обеспечение, которое было невероятно полезным не только для меня, но и для тысяч других разработчиков. Приятного времяпровождения!