Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Установка пакета Hacklang и сборка приложения Hack

Оригинал: Install Hacklang and build a Hack app
Автор: Rob Zwetsloot
Дата публикации: 5 июля 2014 г.
Перевод: Н.Ромоданов
Дата перевода: июль 2014 г.

Предисловие переводчика:

Язык Hack — PHP-подобный язык программирования общего назначения со статической типизацией, разработанный компанией Facebook и представленный 21 марта 2014 года. Код, написанный на языке Hack, исполняется на виртуальной машине HHVM (англ. HipHop Virtual Machine), созданной на базе транслятора HipHop, и поддерживающего одновременно и Hack, и PHP.

Является открытым программным обеспечением — исходные коды проекта открыты для участников сообщества.

Давайте изучим, как установить пакет Hacklang, настроить сервер Apache так, чтобы он мог взаимодействовать с экземпляром приложения Hack, а затем соберем приложение Hack.

Некоторое время назад компания Facebook представила миру новый язык программирования. Это язык называется Hack и это именно то, что мы сегодня собираемся расммотреть. Hack уникален тем, что, в отличие от многих новых языков, его первой версий была сразу версия v1. Последние пару лет компания Facebook работает над написанием языка Hack и переносом на него настольной версии своего сервиса, а это означает, что уже доказано, что язык Hack будет той системой, которая вполне способна поддерживать работу огромных сайтов — в настоящее время нет ничего больего, чем сервис Facebook.

Первоначально сервис Facebook был построен с использованием PHP и MySQL, но время шло, сервис рос и эти технологии стали не в состоянии сразу «из коробки» обрабатывать данные и трафик, который необходимы для Facebook. Вместо того, чтобы портировать свой сервис на более низкий уровень или более оптимизированный язык, компания Facebook решила инвестировать время и деньги в создание технологий, которые сразу будут наилучшими. Одним из результатов усилий является язык Hack, который, как сообщает компания Facebook , дает удвоение скорости исполнения его настольной версию без отрицательного влияния на время разработки программного изделия. Язык Hack является следующим шагом в проекте HipHop, разрабатываемым компанией Facebook, изначально представляющим собой инструмент с открытым исходным кодом и предназначенным для преобразования языка PHP в язык C++. Вместо того, чтобы выполнять откомпилированный текст на языке C++, язык Hack компилируется в байт-код JIT-компилятором на виртуальной машине HHVM (HipHop Virtual Machine). На этот раз, мы рассмотрим установку виртуальной машины HHVM и создание интерфейса базы данных для блога почтовых сообщения, который был написан с помощью Hack, PHP5 и MySQL.

Язык Hack уже был опробован в роли системы, на которой могут работать огромные сайты

Начинаем

Первое, что нам нужно сделать, это получить виртуальную машину HHVM. К счастью, это довольно просто в случае, если пользоваться системой пакетов Apt. Давайте для Hackдобавим репозитарий , а затем Apt его установит.

$ echo deb http://dl.hhvm.com/ubuntu saucy main | sudo tee /etc/apt/sources.list.d/ hhvm.list
$ sudo apt-get update
$ sudo apt-get install hhvm

Через пару минут, язык Hack должен быть установлен. Давайте быстро это проверим. Создайте новый файл с именем test.php и вставьте в него следующий текст

<?hh

      echo HHVM_VERSION . "\n";

Теперь, давайте с помощью команды hhvm test.php запустим этот код в терминале. В терминале вы должны увидеть номер версии, например, должно появиться 3.x.x. Если это так, то вы уже готовы настроить язык Hack для работы с сервером Apache.

До версии 3 в пакет Hack/HHVM входил свой собственный сервер, который мог быть запущен в качестве сервиса. Это было удалено из версии 3 в значительной степени потому, что команда, работающая в Facebook, почувствовала, что ее задачей было в большей степени написание языка, а не сервера. Таким образом, Hack теперь работает совместно либо с сервером Apache, либо с сервером Nginx, заменяя обычный интерпретатор языка PHP. Язык Hack общается с этими серверами через прокси с интерфесом FCGI, поэтому давайте сейчас изменим наши конфигурационные файлы так, чтобы это можно было делать. Следующие инструкции будут предназначены непосредственно для сервера Apache, а не для Nginx, хотя настройка последнего в значительной степени такая же самая.

В конце нашей установки интерпретатора Hack нам было предложено, что следует делать дальше. Одним из таких предложений было выполнение следующей команды

$ sudo /usr/share/hhvm/install_fastcgi.sh

Теперь запустите этот скрипт; он сконфигурирует сервер и интерпретатор Hack для использования FCGI, но дополнительно еще нужно передавать ваш трафик с вашего сервера Apache в наш экземрляр Hack. Найдите либо ваш файл httpd.conf, либо файл apache.conf файл - он должен быть найден где-нибудь в каталоге /etc/apache2 - и откройте его для редактирования. Добавьте в конец файла следующую строку:

ProxyPass / fcgi://127.0.0.1:9000/var/www/hack

Сохраните исправления и выйдите из редактора. В результате весь трафик, который получает ваш сервер, будет перенаправлен в каталог /var/www/hack. Если вы хотите перенаправить к экземпляру Hack только определенные виды трафика, то можно с помощью регулярных выражений regex изменить инструкцию ProxyPass, но это на ваше усмотрение, и мы здесь не будем рассматривать что-либо, касающееся этого. Здесь предполагается, что у вас есть каталог в /var/www/hack, если это не так, вы можете либо создать его сейчас, либо строку в файле .conf изменить так, чтобы там было указано, где вы хотели бы разместить каталог вашего проекта.

У нас почти все готово. Скопируйте файл test. php, который мы написали некоторое время назад, во вновь созданный каталог проекта. Если вы попробуете получить доступ к файлу через браузер, вы увидите, что не можете получить номер версиитак, как это предполагалось. Это потому, что виртуальная машина HHVM еще не запущена, и для того, чтобы обрабатывать файлы на языке Hack/PHP, мы должны запустить виртуальную машину HHVM и подать ей эти файлы. Когда мы запускаем виртуальную машину HHVM, она при рендеринге страниц с определенными функциями берет на себя роль обработки PHP - имейте в виду, что язык Hack не полностью совместим с языком PHP, но с выпуском каждого версии совместимость улучшается. На момент написания статьи винтуальная машина HHVM была в таком состоянии, что начала без специального сложного конфигурирования поддерживать некоторые из наиболее популярных фреймворков, например, WordPress или Magento. Чтобы запустить сервер Hack, введите в терминале следующее:

hhvm --mode server -vServer.Type=fastcgi -vServer.Port=9000

Теперь, если вы наберете http://ВАШ_АДРЕС_IP/test.php, вы должны еще раз увидеть номер версии 3.x.x языка Hack. Отлично! Теперь мы готовы начать создание нашего блога.

Работа с базой данных

Кроме различий в исполнении кода, пожалуй, самая большая разница между Hack и PHP состоит в том, как они взаимодействует с языком HTML - язык Hack вообще не взаимодействует с HTML. Даже если вы поставляете обычный PHP с сервером Hack, вам сильно повезет, если какой-нибудь фрагмент кода PHP будет выполнен в документе перед тем, как произойдет его крах, а если вы попытаетесь разнообразить код на языке Hack вставками на HTML, вы, вероятно, будете вознаграждены сообщением об ошибке. То, где язык Hack блистает своими возможностями, это оптимизация данных и их обработка, так что мы собираемся использовать язык Hack для получения, упорядочивания, а затем кодирования сообщений JSON с использованием базы данных SQL.

В каталоге проекта создайте файл с названием connect.php и мы будем создавать подключение к базе данных, вставив в него следующей текст:

<?hh
   $connection = mysqli_connect("SQL SERVER ADDRESS", "USERNAME", "PASSWORD", "DATABASE") or die("DB Error: " . mysqli_error($connection));

... а затем возвратимся в файл index.php и вставим в него код, показанный ниже:

<?hh

   echo " " . HHVM_VERSION . "\n";

   require_once('connect.php');

   $query = "SELECT * FROM posts" or die("DB Query error: " . mysqli_error($connection));

   $result = $connection->query($query);

   while($row = mysqli_fetch_array($result)) {
      echo $row["name"] . "
"; }

Если вы сейчас запустите этот код, ничего не произойдет, поскольку мы еще не создали базу данных SQL. Нужно взять дамп базы данных SQL с некоторым демонстрационным содержимым, импортировать его в базу данных, а затем запустить файл index.php. Теперь вы должны увидеть, как в вашем браузере будет выдан список всех именованных столбцов. Это все хорошо, но это всего лишь рутинный язык PHP (хотя, благодаря виртуальной машине HHVM, слегка оптимизированный). Давайте все разделим и создадим маленький фрагмент хорошего скрипта на языке Hack.

Снова отредактируйте файл index.php и удалите из него все после инструкции require_once, поскольку все это нам здесь не понадобится. Затем вернитесь в файл connect.php и удалите все после символов <?hh, а затем наберите код, показанный ниже:

class Database{

   private boolean $connected = False;
   private Object $connection;

   public function connect(string $addr, string $user, ?string $pw, ?string $db): ?int {

      if($db == null){
         return 0;
      }

      $this->connection = mysqli_connect($addr, $user, $pw, $db) or die("DB Error: " . mysqli_error($connection));

      if($this->connection != null){
         $this->connected = True;
         return 1;
      } else {
         $this->connected = False;
         return 0;
      }
   }
}

Давайте посмотрим на то, что здесь у нас есть. Это объявление класса Hacklang, в нем есть приватные и публичные члены и функции, к которым, если мы пожелаем, мы можем получить доступ и их выполненить. Давайте сначала обратим внимание на строку, где мы объявляем нашу функцию connect(); здесь есть некоторые особенности, которые используются по-другому, поэтому мы собираемся в них разобраться. Если вы знакомы с языком C++, то все будет выглядеть для вас обычным; если вы больше приверженец языка PHP, то, может быть, и нет.

Во-первых, обратите внимание на параметры, которые мы передали; мы объявили типы данных, которые, как мы ожидаем, должны быть в качестве параметров (string / int / float /object / и т.д.). Если мы попытаемся обратиться к функции с неправильными типами данных, то, в зависимости от того, какой вы задали уровень предупреждения в языке Hack, либо будет просто прекращено выполнение нашего файла, либо будет сгенерирована ошибка. Зачем такая возможность? Та часть языка Hack, которая позволяет выполнять код очень быстро, является его интерпретатором. PHP является языком со слабой типизацией, что означает, что мы можем создавать переменные на лету, не беспокоясь слишком сильно о том, что будет храниться в переменной. В переменной $x может сначала быть строка "Hello, World", а затем - значение 5. В языке Hack по-прежнему допускается такая гибкость, но если мы объявим тип данных, который мы ожидаем, виртуальная машина HHVM может без дополнительного привлечения разработчиков начать оптимизировать этот код и выполнять его быстрее, чем обычно (до шести раз быстрее).

Перед переменными $pw и $db указан символ '?', который указывает языку Hack на то, что, хотя мы и ожидаем значение string / int / float / и т. д., мы также можем потенциально получить значение null. Мы можем это использовать везде, где мы, возможно, хотим не очень строго требовать передачу данных, и, как видно, мы это применили в конце строки к нашей переменной :?int. Это тип данных, который, как мы ожидаем, должен возвращать в данном случае целое число или null.

Последний мелочь, на которую здесь стоит обратить внимание прежде, чем мы пойдем дальше, является функция $this. Если мы пытается получить доступ к членам класса, мы должны их инициализировать, но если мы не задали значения, когда мы объявляли эти переменные, то это за нас сделает переменная $this. Если мы написали $connection вместо $this->connection, то переменная должна существовать в той области видимости, в которой она была вызвана, и поэтому она недоступна для других функций, которым она, возможно, требуется доступ к объекту.

Добавьте функцию из кода, приведенного ниже, в наш класс Database в файле connect.php; это прекрасный небольшой фрагмент кода будет с помощью функции connection, которую мы создали, когда мы впервые инициализировали класс, обрабатывать любые запросы SQL в нашей базе данных.

public function makeQuery(string $q): void{

   if($this->connected == True){

   $result = $this->connection->query($q);

   return $result;

   }

}

Делаем первый запрос

Так что давайте посмотрим, что случится сейчас. Вернитесь к файлу index.php и после нашей инструкции require_once добавьте следующий код:

$db = new Database();

$db->connect("127.0.0.1", "USER", "PASSWORD", "DATABASE NAME");

//var_dump($db);

$q = $db-> makeQuery("SELECT * FROM posts");

$data = array();

while($row = mysqli_fetch_array($q)) {

   $object = array("name" => $row["name"], "tag" => $row["tagline"], "content" => $row["content"], "date" => $row["date"]);
   array_push($data, $object);

}

echo json_encode($data);

Если вы на вашем сервере вызовите файл index.php, вы должны снова увидеть содержимое сообщений на форуме в нашей базе. Ура! Но это всего лишь статика. Давайте с помощью нескольких параметров GET и POST сделаем небольшие изменения.

Обработка запросов GET и POST

Все, что описывалось выше, несовместимо с определенными возможностями языка PHP. В эту категорию попадают запросы $_GET и $_POST. Код на языке Hack ничего не знает ни о $_GET, ни о $_POST (хотя, если вы запустили интерпретатор Hack не в строгом режиме, вы все еще можете пользоваться этой возможностью). Здесь мы будем считать, что мы работаем в строгом режиме, и будем отображать запросы GET и POST так, чтобы язык Hack мог их использовать.

Настало время добавить еще один новый файл. Еще раз в каталоге проекта создайте новый файл с именем requests.php, а затем вставьте в него и сохраните код, показанный ниже:

function fetchGET(): Map {
   return Map::fromArray($_GET);
}

function fetchPOST(): Map {
   return Map::fromArray($_POST);
}

function postType(): string {

   if($_SERVER['REQUEST_METHOD'] === 'GET'){
      return "GET";
   } else {
      return "POST";
   } 

}

В этих функциях определены глобальные переменные $_SERVER, $_GET и $_POST для нашего кода Hack, так что если нам нужно будет вызвать функцию fetchGET(), мы воспользуемся новым отображаемым объектом $_GET. Теперь мы можем заняться обработкой запросов, хотя есть одно небольшое замечание.

Проверка типов параметров

В языке Hack желательно знать, какой используется тип данных (это уже известная фишка), т. к. он просто получает доступ к переменной GET, что нам не слишком поможет. Все, что мы сможем получить, это проанализированные строки, и пока мы продолжаем работать только со строками, мы теряем все преимущества, связанные с проверкой типов данных в виртуальной машине HHVM. Поэтому, давайте для обработки целочисленных значений напишем быстрый анализатор. Добавьте в файл requests.php следующий код:

abstract class ServerRequest {
abstract public function getParams(): Map;
public function intParam(string $name): ?int {
$params = $this->getParams();if (!$params->contains($name)) {return null;}
$param = $params[$name];
if (!is_numeric($param)) {return null;}
return (int)$param;
}}
final class getRequest extends ServerRequest {public function getParams(): Map {return fetchGET();}
}
function int_check_for_parameter(string $parameter): int {if (postType() == “GET”) {return (new getRequest())->intParam($parameter);}}

Затем вернитесь в файл index.php и измените его так, чтобы он выглядел следующим образом:

$db->connect(“127.0.0.1″, “USERNAME”, “PASSWORD”, “DATABASE NAME”);
$limit = int_check_for_parameter(“limit”);
$q;
if($limit > 0){$q = $db->makeQuery(“SELECT * FROM posts LIMIT ” . $limit);} else {$q = $db->makeQuery(“SELECT * FROM posts”);}worxwhile($row = mysqli_fetch_array($q)) {echo $row["name"] . ““;}

Давайте посмотрим на класс ServerRequest, он отличается от класса Database, который мы написали в файле connections.php, тем, что мы объявили его как абстрактный. Это одна из возможностей, добавленная в язык PHP5; абстрактный класс является классом, который не может быть создан, его можно использовать только в качестве некоторого шаблона для других классов, которые его расширяют. Он довольно красиво согласуется с нашим классом GetRequest. Обратите внимание, что перед определением стоит ключевое слово final. Класс final является классом, который расширяет абстрактный класс, но он сам не может быть расширен; если бы мы попытались это сделать, язык Hack выдал бы фатальную ошибку.

Теперь, если вы в конце строки вашего запроса добавите ?limit=5, вы должны увидеть только первые пять результатов - что само по себе не является чем-то особенным, но то, что мы здесь видим, является вызовом функции intParam(). Во-первых, нам нужно знать, есть ли в нашем запросе GET параметр, который мы ищем. Как только мы определили, что он там есть, нам затем нужно проверить, является ли он числом и, если он пройдет нашу проверку, преобразовать его в целое число. Если нет, то должно быть возвращено значение null. В случае, когда дело доходит до обработки параметра GET, это может выглядеть слишком педантичным, но иначе нам потребуется забыть о мощи JIT-компилятора Hack.

Когда происходит первое обращение, виртуальная машина HHVM/Hack может мало что сделает для немедленного увеличения скорости, но по мере того, как идет время и увеличивается нагрузка, виртуальная машина HHVM оптимизирует процессы, вызываемые чаще всего, и, кроме того, закэширует байт-код, который она сгенерирует. Это лишь часть красоты языка Hack: он более многогранен, чем язык PHP, которого, давайте признаем, не обладает репутацией краткого языка, но благодаря дополнительным усилиям, мы можем выжимать из языка PHP каждую каплю мощности, на которую он способен.

Подведем итог

И это лишь основы языка Hack. Язык Hack может показаться несколько сложным в настройке и, если вы из тех разработчиков, которые любят учиться на примерах кода, то на данный момент с этим проблема - но не это должно останавливать вас! Язык Hack все еще находится в зачаточном состоянии; ему едва исполнился год и его выигрыш в скорости уже стал просто феноменальным. Правда, у него есть недостатки, обусловденные таким повышением производительности, но важно помнить, язык Hack не предназначен для рендеринга HTML (хотя он может с помощью движка рендеринга XHP, имеющегося в еHack , генерировать код на HTML или другие Node-подобные структуры). Напротив, он предназначен для супербыстрого перемалывания данных, поэтому остальные веб-сервисы могут работать настолько быстро, насколько это возможно. Это позволяет языку Hack быть на отличном счету в случае, если рассматривать вопросы повышения производительности или даже замены текущих сервисов, связанных с обработкой больших наборов данных, среди которых наиболее очевидным претендентом являются масштабируемые API.