Предисловие
В недавнем рабочем сценарии PHP-проекту необходимо использовать стороннюю функцию, и, как оказалось, библиотека классов написана на golang . Итак, вопрос в том, как добиться общения между разными языками? Давайте посмотрим.
Обычное решение
1. Напишите службу HTTP/TCP в golang, и PHP будет взаимодействовать с golang через HTTP/TCP
2. После дополнительной инкапсуляции golang используется в качестве расширения PHP.
3. PHP вызывает исполняемый файл Golang с помощью системной команды
Существующие проблемы
1. HTTP-запрос, сетевой ввод-вывод займет много времени
2. Необходимо инкапсулировать большое количество кодов
3. Каждый раз, когда PHP вызывает программу golang, ее необходимо инициализировать, что отнимает много времени
Цели оптимизации
1. Программа golang инициализируется только один раз (поскольку инициализация занимает много времени).
2. Всем запросам не нужно выходить в Интернет
3. Старайтесь не изменять большое количество кодов
Решение
1. Простая инкапсуляция golang, компиляция библиотеки классов сторонних разработчиков в исполняемый файл
2. PHP и golang взаимодействуют через двусторонний конвейер
Преимущества использования двухстороннего трубопроводная связь
1: требуется лишь небольшая инкапсуляция оригинальной библиотеки классов golang
2: лучшая производительность (IPC-связь-лучший способ межпроцессной связи)
3: не нужно заходить в сеть для запроса, сэкономьте много времени
4: Программу нужно инициализировать только один раз и она остается в памяти
Конкретные шаги по реализации
1: Оригинальная демонстрационная версия вызова в библиотеке классов
package main
import (
"fmt"
"github.com/yanyiwu/gojieba"
"strings"
)
func main() {
x := gojieba.NewJieba()
defer x.Free()
S: = "Xiaoming graduated from the Institute of computing, Chinese Academy of Sciences, and later studied in Kyoto University, Japan"
words := x.CutForSearch(s, true)
fmt.Println(strings.Join(words, "/"))
}Сохраните файл как основной.перейдите к запуску
2: Скорректированный код является:
package main
import (
"bufio"
"fmt"
"github.com/yanyiwu/gojieba"
"io"
"os"
"strings"
)
func main() {
x := gojieba.NewJieba(
"/data/tmp/jiebaDict/jieba.dict.utf8",
"/data/tmp/jiebaDict/hmm_model.utf8",
"/data/tmp/jiebaDict/user.dict.utf8"
)
defer x.Free()
inputReader := bufio.NewReader(os.Stdin)
for {
s, err := inputReader.ReadString('\n')
if err != nil && err == io.EOF {
break
}
s = strings.TrimSpace(s)
if s != "" {
words := x.CutForSearch(s, true)
fmt.Println(strings.Join(words, " "))
} else {
fmt.Println("get empty \n")
}
}
}Для этого требуется всего несколько простых строк настройки: получить строку из стандартного ввода, а затем вывести ее после сегментации слов
Тест:
# go build test # ./test #"// wait for user input, input" this is a test" #This is a test // program
3: Использование cat для связи с golang для простого теста
//Prepare a title.txt with one sentence per line # cat title.txt | ./test
Нормальный вывод указывает на то, что cat может нормально взаимодействовать с golang
4: Связь PHP и golang
Кот, показанный выше, связывается с голангом с помощью односторонней трубы. То есть данные могут передаваться только из cat в golang, и данные, выводимые golang, не возвращаются в cat, а выводятся непосредственно на экран. Но требование в этой статье таково: PHP взаимодействует с golang. То есть, если PHP хочет передать данные в golang, golang также должен вернуть результат выполнения в PHP. Поэтому необходимо ввести двухсторонние трубы.
Использование каналов в PHP: popen("/путь/тест") , я не буду подробно говорить об этом, потому что этот метод не может решить проблемы, описанные в статье.
Двусторонняя труба:
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w")
);
$handle = proc_open(
'/webroot/go/src/test/test',
$descriptorspec,
$pipes
);
Fwrite ($pipes ['0 '], "this is a test text \ n");
echo fgets($pipes[1]);Пояснение: Используйте proc_open Откройте процесс и вызовите программу golang. В то же время он возвращает массив двунаправленных трубопроводов, PHP $pipe['0'] Запись данных из $pipe['1'] Данные среднего чтения.
Ну, как вы, возможно, уже поняли, я-файл заголовка, и дело здесь не только в том, как PHP взаимодействует с golang. Речь идет о способе общения на любом языке с помощью двустороннего конвейера. (все языки реализуют контент, связанный с конвейером)
Тест:
С помощью сравнительного теста рассчитывается время каждого процесса. В title.txt файл, упомянутый ниже, содержит 1 миллион строк текста. Каждая строка текста-это название продукта, взятое с платформы B2B
1: Общая трудоемкость процесса
time cat title.txt | ./test > /dev/null
Время: 14,819 секунды, включая:
Процесс чтения текста котом
Передача данных в голанг
Golang обрабатывает данные и возвращает результаты на экран
2: Для вычисления функции сегментации слов требуется время. Схема: удалите вызов функции сегментации слов, то есть закомментируйте код строки сегментации слов вызова в исходном коде golang
time cat title.txt | ./test > /dev/null
Время: 1,817 секунды, включая:
Процесс чтения текста котом
Передача данных в голанг
Golang обрабатывает данные и возвращает результаты на экран
Время сегментации слов = (время первого шага) – (выше времени выполнения команды)
Время сегментации: 14,819 –0,002 секунды
3: Проверьте время связи между процессом cat и процессом golang
time cat title.txt > /dev/null
Потребление времени: 0,015 секунды, включая:
Процесс чтения текста котом
Передача данных в голанг
Go обрабатывает данные и возвращает результаты на экран
Потребление времени на связь по трубопроводу: (потребление времени на втором этапе) – (потребление времени на третьем этапе)
Время связи по трубопроводу: 1,817 –0,802 секунды
4: Время, затрачиваемое на связь между PHP и golang
Напишите простой PHP – файл:
Процесс в основном такой же, как и выше. Прочитайте содержание title.txt, передайте сегментацию слов процесса golang по двустороннему конвейеру, а затем верните его в PHP (на один шаг больше, чем в приведенном выше тесте: данные возвращаются по конвейеру)
time php popen.php > /dev/null
Время: 24,037 секунды, включая:
Процесс PHP чтение текста
Передача данных в голанг
Голанг обрабатывает данные
Golang записывает возвращенный результат в конвейер, а PHP получает данные через конвейер
Возврат результатов на экран
Вывод:
1: Распределение по времени во всем процессе сегментации слов
Использование логики управления cat занимает 14,819 секунды
Использование логики управления PHP занимает 24,037 секунды (на один конвейер больше, чем у cat).
Время связи по трубопроводу в одну сторону: 1,8 секунды
Время функции сегментации слов в golang: 13,002 секунды
2: Производительность функции сегментации слов: один процесс, сегментация 1 миллиона слов в названии продукта, 13 секунд
Указанное выше время включает только время сегментации слов, исключая время загрузки словаря. Но в этой схеме словарь загружается только один раз, поэтому время загрузки можно игнорировать (около 1 секунды).
3: PHP работает медленнее, чем cat
Медленный уровень владения языком: (24.037 – 1.8 – 14.819)/%
Для теста сравнения одного процесса не должно быть языка быстрее, чем cat.
Связанные с этим вопросы:
1: Приведенный выше исходный код golang представляет собой цикл, то есть он всегда будет считывать данные из конвейера. Таким образом, возникает проблема: будет ли процесс golang по-прежнему существовать после завершения процесса PHP?
Механизм трубопровода сам по себе может решить эту проблему. Конвейер предоставляет два интерфейса: чтение и запись. Когда процесс записи заканчивается или неожиданно зависает, процесс чтения также сообщает об ошибке. Логика ошибок в приведенном выше исходном коде golang будет выполнена, и процесс golang завершится. Но если процесс PHP не завершается, но данные временно не передаются, процесс golang будет все время ждать. Процесс golang не завершается автоматически до тех пор, пока PHP не будет завершен.
2: Могут ли несколько процессов PHP параллельно читать и записывать один и тот же конвейер, и процесс golang обслуживает его одновременно?
может, и нет. Трубопровод односторонний. Если несколько процессов одновременно записывают данные в конвейер, возвращаемое значение golang будет сбито с толку. Вы можете открыть еще несколько процессов golang для реализации. Каждый процесс PHP соответствует одному процессу golang.
Наконец-то, все это чушь собачья. Если вы знаете трубы и двухсторонние трубы, приведенное выше объяснение мало вам поможет. Но если вы не понимаете конвейер, вы можете отладить приведенный выше код без каких-либо проблем, но если вы его слегка измените, он может провалиться в яму.
резюме
Выше приведено все содержание этой статьи. Я надеюсь, что содержание этой статьи может быть полезно вам для изучения или использования golang. Если у вас есть какие-либо вопросы, вы можете оставить сообщение и связаться с нами. Спасибо вам за вашу поддержку разработчиков.