...

суббота, 4 июня 2016 г.

Как я ловил Wi-Fi принтер по OSPF, корпоративная сеть на MikroTik часть 2

Всем привет! Наконец я решил внести обещанное дополнение к статье: Резервирование внутренних и внешних каналов связи, статическая маршрутизация, корпоративная сеть на MikroTik.

В данной статье хочу поделиться с вами решением некоторых дополнительных задач, которые предстали передо мной во время реализации проекта. Среди таких задач была организация доступна к серверам в офисе для устройств сотрудников отдела ревизии, которые перемещаются из магазина в магазин (Часть 1). А так-же о том, как я ловил гуляющий по магазинам Wi-Fi принтер при помощи протокола динамической маршрутизации OSPF (Часть 2).

Как и прежде, надеюсь что данное решение поможет кому-то либо из новичков решить аналогичные задачи. Буду рад критике со стороны профессионалов.

image

Кого заинтересовал заголовок — прошу под кат!

Часть 0. Что дано


Позвольте немного вкратце напомнить о том, что было сделано в предыдущей статье. Ко мне обратилась организация – сеть торговых магазинов с просьбой организовать им сегментированную сеть с возможностью резервирования и ограниченным бюджетом.

Передо мной поставлена задача сделать из плоской территориально распределённой по городу сети: сегментированную сеть, с иерархической адресацией и главное с возможностью резервирования.
Связь между всеми магазинами по городу организовывает местный ISP, путем предоставления предприятию отдельного VLAN внутри своей сети. Таким образом, вся сеть во всех магазинах и в офисе находилась в одном большом Layer2 Broadcast-домене.

У такой модели есть ряд недостатков:

  1. Все устройства в сети могут видеть друг друга на Layer-2.
  2. Отсутствие каких-либо политик фильтрации трафика.
  3. Единый Broadcast домен, результатом которого является то, что любой широковещательный пакет от каждого из 400 устройств, обязательно будет передан всем этим 400 устройствам, расположенным в разных концах города.

Краткую, упрощенную схему расположения серверов приведу на рисунке 1 ниже:

И краткое описание того, что имеем:

  1. На предприятии имеются разные серверы выполняющие разные роли.
  2. Есть специальные терминалы сбора данных (ТСД), на рисунке я их назвал TABLETS.
    • Есть стационарные ТСД привязанные к конкретному магазину и не покидающее его пределов. Они имеют IP-адреса из пула устройств в магазине.
    • Есть ревизионные ТСД и отдельный сервер ревизии, с которым они взаимодействуют. Эти ТСД постоянно мигрируют из магазина в магазин где выполняют ревизию.

Часть 1. «Упс, а у нас тут ревизия»


После того как началось внедрение в сети маршрутизаторов Mikrotik, в первом из магазинов, в тот же день там проходит ревизия.

Организация работы отдела ревизии очень интересна и своеобразна. Во всех магазинах имеются Wi-Fi точки доступа с одинаковыми SSID и ключами шифрования. Таким образом, ревизионные ТСД имеют статический IP-адрес из своего отдельного пула (192.168.3.0/24).

Так как изначально сеть была плоской, то любой ревизионный ТСД попадая в любой из магазинов оказывался в единой плоской сети и без проблем подключался к серверу ревизии расположенном где угодно.

Сервер-ревизии представлял из себя RDP-сервер с особой базой данных. Которая перед ревизией синхронизировалась с основным сервером БД. Сервер ревизии также подгружал нужные для работы файлы с сервера-хранилища. Терминалы сбора данных (ТСД – Tablets), взаимодействовали в основном только с сервером ревизии. Однако, иногда, в крайних случаях, когда на сервере ревизии что-то шло не так, они взаимодействовали напрямую с RDP-сервером расположенном в офисе. Все остальные ТСД (находящиеся постоянно в магазинах и привязанные к ним) взаимодействовали только с основным RDP-сервером.

Итак, вроде-бы понятно и просто. Есть мобильная группа устройств, периодически гуляющая из магазина в магазин и выполняющая страшную для работников магазина вещь – ревизию.
Ей просто необходимо получать динамически IP из пула в магазине и подключаться к серверу ревизии находящемуся в офисе или в крайнем случае к основному RDP-серверу.

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

Поэтому исторически сложилось так, что сервер ревизии путешествовал вмести с ТСД из офиса по магазинам. Обычно это происходило вечером на кануне дня ревизии. Администратор привозит в магазин сервер, подключает его в любой свободный порт на любом из коммутаторов в магазине (помним, что сеть плоская и все порты соединены единым L2-доменом). Ставит ТСД на зарядку и уезжает.

Далее, ночью по расписанию сервер ревизии подключается к другим серверам находящимся в основном офисе и выполняет разные синхронизации и репликации данных. Важно заметить, что инициатором подключения всегда является сервер ревизии.

Возвращаемся к внедрению распределенной сегментированной сети в первом магазине. Там будет установлен маршрутизатор, который разделит L2-сегмент от общего офиса, а также в случае чего обеспечит резервирование каналов связи провайдера.
Позвольте привести изображение из предыдущей статьи чтобы было понятно, что изменилось в магазине.

image

Из рисунка понятно, что установленный в магазине маршрутизатор лишает мобильности ревизионную группу устройств.
Позвольте напомнить, как выглядит адресация в магазинах после внедрения маршрутизаторов:

  1. 192.168.1.0/24 – сеть центрального офиса
  2. 192.168.2.0/24 – 192.168.13.0/24 локальные сети каждого из 12 магазинов
  3. 10.10.10.0/24 – сеть, приходящая в главный офис через основной Ethernet канал
  4. 10.10.20.0/24 – сеть, приходящая в главный офис через резервный канал (PON)
  5. 10.20.30.0/24 – сеть внутри VPN, для магазинов, цепляющихся через внешнюю сеть на IP от ISP-1
  6. 10.30.40.0/24 – сеть внутри VPN, для магазинов, цепляющихся через внешнюю сеть на IP от ISP-2

Теперь, по прибытию в конкретный магазин, сервер ревизии, как и прежде подключается к любому свободному порту в коммутаторе, ТСД подключается к Wi-Fi точке доступа. После чего, ТСД могут свободно общаться с сервером ревизии находящимся с ними территориально в одном магазине, однако они не могут подключится к основному RDP-серверу в офисе. А сам сервер ревизии находясь вне офиса, не может выполнить синхронизацию данных.

Так как, это был первый переводимый магазин, и вся сеть полностью не была переведена на новый режим работы. График работы команды ревизии уже расписан: сегодня они здесь, а завтра уже в другом магазине, а потом снова здесь и т.д.

Требуется срочное решение задачи по обеспечению связности ревизионной группы (диапазон IP-адресов которой статичен: 192.168.3.0/24)

Как уже писал выше, в данной схеме инициализатором синхронизации является сам сервер ревизии: он сам подключается к другим серверам и выполняет нужные ему задачи. Ревизионные ТСД, если необходимо, тоже являются инициализаторами RDP-сессии с основным RDP-сервером в офисе.

Моя задача обеспечить IP-связность мобильных устройств, находящихся в любом из магазинов с офисом. При этом адресация устройств остается неизменной. Варианта получения ими адресов по DHCP в конкретном из магазинов нет.

Поэтому, первое решение, которое пришло мне в голову как временное (и, похоже оставшееся там постоянным) это реализация NAT.

Я уточнил у системных администраторов, точно ли, никаким из устройств, кроме ТСД сотрудником отдела ревизии, нет необходимости подключаться к серверу ревизии? Ответом было нет. Правда, иногда необходимо удаленно подключаться программистам по RDP. Однако, они это могут делать, подключившись к какому ни будь из PC в магазине, и с него уже подключиться к серверу. Если, конечно, PC в магазине смогут видеть сервер.

Итак, приступим к выполнению поставленной задачи.

Первым делом, я прошу администраторов установить нас всех ревизионных ТСД и на сервере адрес основного шлюза: 192.168.3.2
На маршрутизаторе, расположенном в магазине, добавляем этот IP-адрес на интерфейсе смотрящем в сторону магазина:

[s@VERTOLET-GW] > ip address export 
# jun/03/2016 21:22:19 by RouterOS 6.32.3
#
/ip address
add address=192.168.3.2/24 interface=bridge-VERTOLET network=192.168.3.0

Таким образом, данная сеть ревизии (192.168.3.0/24) будет добавлена абсолютно во все магазины, это позволит мобильной группе устройств при переезде между магазинами, без перенастройки параметров видеть роутер магазина, а значит знать где расположены устройства в офисе.
Но, если мы будем иметь 12 магазинов с одинаковыми адресами, откуда серверам в офисе знать куда отправлять пакеты?
Тут, нам на помощь приходит NAT, целью которого является изменить IP-адреса с которых обращается мобильная группа.

Для этого, я выясняю к каким конкретно серверам необходим доступ устройств мобильной группы и создаю для них отдельный address-list:

[s@VERTOLET-GW] > ip firewall address-list export
# jun/03/2016 21:32:00 by RouterOS 6.32.3
#
/ip firewall address-list
add address=192.168.1.2XX list=REVISION-Servers
add address=192.168.1.2XX list=REVISION-Servers
add address=192.168.1.2XX list=REVISION-Servers

Теперь, делаем правило для трансляции NAT, чтобы скрыть адреса источников обращения мобильной группы:

[s@VERTOLET-GW] > ip firewall nat  export
# jun/03/2016 21:42:00 by RouterOS 6.32.3
/ip firewall nat
add action=masquerade chain=srcnat comment=FROM-REVISION dst-address-list=REVISION-Servers src-address=192.168.3.0/24

Данное правило NAT меняет адреса источников (192.168.3.0) на адреса роутера в транзитных сетях (10.0.0.0/8) при обращении к нужным серверам в офисе.
Итак, задача уже частично решена, т.к. мобильная группа может свободно приезжать в любой магазин, подключаться к сети, где ее уже ждет заранее готовый шлюз и инициализировать соединения с центральным офисом.

Напомню с этой задачей я столкнулся в первый день внедрения решения, и сеть в целом была не готова к изменениям, сложилась ситуация: когда сервера ничего еще не знали об адресации между магазинами. И шлюзом для них был Kerio сервер, на котором статически был прописан маршрут в сеть переводимого магазина на отдельный, скромно стоящий маршрутизатор Mikrotik в офисе.
Которому позже предстояло стать главным роутером.

Это означает, что в офисе нам потребовалось сделать еще одну NAT трансляцию чтобы скрыть от серверов ( к которым обращается мобильная группа) транзитные сети (10.0.0.0/8):
Аналогично, как в магазине добавляем адрес-лист

[s@MAIN-BORDER-ROUTER] > ip firewall address-list export
# jun/03/2016 21:52:12 by RouterOS 6.32.2
#
/ip firewall address-list
add address=192.168.1.2XX list=REVISION
add address=192.168.1.2XX list=REVISION
add address=192.168.1.2XX list=REVISION


А также правило трансляции:
[s@MAIN-BORDER-ROUTER] > ip firewall nat export
# jun/03/2016 21:52:12 by RouterOS 6.32.2
#
/ip firewall nat
add action=masquerade chain=srcnat comment=NAT-KOSTUL-REVISION dst-address-list=REVISION src-address=10.0.0.0/8

Как видите, так и пришлось по-честному подписать данное правило – костыль, ибо по-другому у меня назвать данное решение мыслей не пришло.
На данном этапе, задача по обеспечению связности мобильной группы устройств с серверами в офисе из любого магазина выполнена.
Удаленный доступ к серверу ревизии для программистов, при необходимости можно получить, подключившись на любой PC в магазине, который пойдет в сеть 192.168.3.0/24 через роутер магазина, знающий об этой сети, как о своей direct-connected сети.

Часть 2. Мой Wi-Fi принтер отказывается печатать ценники!


С момента внедрения сети в первый магазин и переводом на данную схему последнего магазина прошло около 3х недель. В это время всплывали мелкие недочеты, которые спешно исправлялись. В целом все жило хорошо, как и планировалось. Забавно, что после переключения первого магазина на новый режим работы, у ISP случилась авария оставившая именно этот магазин без связи и система отлично отработала переключение на резерв.

Когда происходило внедрение в последнем магазине, системные администраторы поведали мне с неуверенностью об еще одном нюансе, который руководство выставило как задачу необходимую к решению.
Оказывается, среди мобильной группы есть отдельный сотрудник, который также имеет ТСД из диапазона (192.168.3.0/24), с которым он ходит по разным магазинам, однако его задача заключается в переоценке товаров, срок годности которых подходит к концу.
Со своего ТСД он подключается к основному RDP серверу, расположенному в офисе и работает с базой данных. Сканирует товары и печатает новые ценники.

Все хорошо, сотрудник спокойно приходит в тот или иной магазин, цепляется к сети Wi-Fi как и раньше, без проблем подключается к RDP-серверу в офисе, делает что необходимо, запускает печать на принтер, но… Принтер, на котором выполняется печать ценников мобильный! Ранее имевший IP-адрес из диапазона 192.168.1.0/24 и при плоской сети с единым L2, оставался доступным находясь в любом из магазинов.

Также доставляло некоторые неудобство то, что при подключении из офиса к серверу ревизии, один из компьютеров в магазине где происходила ревизия был занят программистами из-за того, что сервер ревизии находился за NAT, и для доступа к нему требовалось занимать один из компов расположенных в магазине.

В общем, передо мной поставлена новая задача:

  1. Обеспечить возможность печати из офиса на мобильный принтер
  2. Обеспечить возможность подключения к серверу ревизии по RDP из офиса напрямую

Что-же, теперь нам от внедрения протокола динамической маршрутизации, от которого я решил уйти в первой части не отвертеться.

Welcome to OSPF!

Тут, правда пришлось опять-же сделать очередной костыль, так как, я писал в первой статье, что через сеть ISP-1 пакеты OSPF не проходили. Ни через multicast, ни через unicast, потому что CPE (xPON-терминалы фирмы Huawei) просто дропали протокол 89.

Поэтому, OSPF я решил внедрить на туннельных интерфейсах, которые предназначались прежде всего для резервирования.
OSPF в данной ситуации необходим для двух вещей:

  1. Динамически указывать роутеру в офисе где искать Wi-Fi принтер, для того чтобы передать на него небольшой файл для печати
  2. Динамически указывать роутеру в офисе где искать сервер ревизии, для того, чтобы передавать туда команды управления RDP (обратный трафик от сервера ревизии в офис будет идти как задумывалось в первой статье)

Выходит, нам нет никакой необходимости передавать по OSPF всю сеть мобильной группы (192.168.3.0/24), более того, мы не может этого делать, т.к. человек занимающийся переоценкой и группа ревизии зачастую находится в разных местах, а связность должна быть с севером и с Wi-Fi принтером одновременно.

Поэтому, я решил, что наиболее оптимальным решением данной задачи, будет передача more specific address /32 конкретно этих двух устройств – принтера и сервера.

Для этого нам потребуется следующие инструменты из богатого функционала OSPF:

  1. Point-to-Point network-type
  2. Redistribution static routes
  3. Filtering

В начале определимся с алгоритмом, как мы будем передавать информацию о Wi-Fi принтере и сервера от магазинов в офис.
Для этого необходимо, чтобы протокол OSPF знал о том, что к данному роутеру подключены эти сети и выполнял анонсирование этих маршрутов центральному роутеру.
Протокол OSPF анонсирует сети двумя способами:
  1. Анонсирование всех сетей, принадлежащих интерфейсу, на котором включен OSPF, если этот интерфейс не Passive
  2. Анонсирование сетей, через редистрибуцию других протоколов динамической маршрутизации, подключенных напрямую маршрутов, статических маршрутов

Итак, я решил поступить следующим образом:
  1. Запуск процесса OSPF во всех магазинах и центральном роутере
  2. Создание статических маршрутов /32, для сервера и принтера во всех магазинах
  3. Фильтрация ненужных статических маршрутов (а их много) при редистрибуции в OSPF
  4. Средствами NetWatch отслеживание реального наличия устройств в том или ином магазине и управления статическим маршрутом

Вроде бы все понятно, приступаем к реализации.
Запускаем OSPF процессы на маршрутизаторах в магазинах и в офисе.
Все магазины будут в одной default area 0.
Состояния соседства между роутерами OSPF будет происходить в туннельных интерфейсах, их у нас между каждым магазином и офисом – 2.
На маршрутизаторах Mikrotik стоимость point-to-point интерфейса по умолчанию равна – 10. Так как, между каждым магазином и офисом у нас 2 VPN канала, устанавливаем на 2-м канале стоимость 20.
[s@KREDO-MAIN-BORDER-ROUTER] > routing ospf export 
# jun/03/2016 22:42:36 by RouterOS 6.32.2
#
/routing ospf instance
set [ find default=yes ] router-id=255.255.255.255
/routing ospf interface
add cost=20 interface=2.VERTOLET-VPN-RESERVE network-type=point-to-point
/routing ospf network
add area=backbone network=10.20.30.0/24
add area=backbone network=10.30.40.0/24


Аналогичные действия делаем на маршрутизаторах в магазинах плюс, указываем на необходимость редистрибуции статических маршрутов, я решил анонсировать их как Type-1:
[s@KREDO-VERTOLET-GW] > routing ospf export 
# jun/03/2016 22:50:17 by RouterOS 6.32.3
#
/routing ospf instance
set [ find default=yes ] redistribute-static=as-type-1 router-id=192.168.15.2 in-filter=ospf-in out-filter=ospf-out
/routing ospf interface
add cost=20 interface=VPN-OFFICE-RESERVE network-type=point-to-point
add interface=VPN-OFFICE network-type=point-to-point
/routing ospf network
add area=backbone network=10.20.30.0/24
add area=backbone network=10.30.40.0/24

В приведенном конфиге приведены команды отвечающие за редистрибуцию статических маршрутов, как type-1, данный тип являеется более приоритетным нежели type-2, а также его метрика изменяется при анонсировании между маршрутизаторами. Также, я указал в настройках OSPF два фильтра: ospf-in и ospf-out, данные фильтры в Mikrotik играют аналогичную с Route-map роль в роутерах Cisco.

Предлагаю рассмотреть данные фильтры:

[s@VERTOLET-GW] routing filter export 
# jun/03/2016 23:01:57 by RouterOS 6.32.3
#
/routing filter
add action=discard chain=ospf-in ospf-type=external-type-1
add action=discard chain=ospf-in ospf-type=intra-area
add action=accept chain=ospf-out prefix=192.168.3.3 protocol=static
add action=accept chain=ospf-out prefix=192.168.3.252 protocol=static
add action=discard chain=ospf-out protocol=static

Фильтр ospf-in фильтрует любые маршруты, которые могут прилететь по OSPF на роутер.
Фильтр ospf-out фильтрует все возможные маршруты, которые могут анонсироваться через редистрибуцию, за исключением more-specific /32 маршрутов для сервера и Wi-Fi принтера.

Теперь, остается добавить статические /32 маршруты для мобильных устройств, о расположении которых мы должны знать.

[s@VERTOLET-GW] > ip route export 
# jun/03/2016 23:08:46 by RouterOS 6.32.3
#
/ip route
add comment=MOBILE-WiFi-PRINTER disabled=yes distance=1 dst-address=192.168.3.3/32 gateway=bridge-VERTOLET
add comment=Revision-SERVER disabled=yes distance=1 dst-address=192.168.3.252/32 gateway=bridge-VERTOLET

Обратите внимание, что данные статические маршруты я добавляю с параметром disabled=yes, то есть – эти маршруты будут выключенными, недоступными, а значит не попадут в анонсирование через OSPF.

Почему? Потому-что, если я добавлю активные маршруты сразу во всех магазинах, то на главном роутере они будут видны через все магазины, и мы вернемся на исходную. Когда нам не известно, где конкретно ловить Wi-Fi принтер, т.к. данные маршруты существуют во всех магазинах.
Поэтому статические маршруты выключены по умолчанию, и никто о них не говорит до тех пор, пока устройство реально не появится в конкретном магазине.

Понять это мы сможем по доступности устройства через ping, а поэтому создаем два правила NetWatch с простенькими скриптами:

[s@KREDO-VERTOLET-GW] >tool netwatch expoart 
# jun/03/2016 23:15:59 by RouterOS 6.32.3
#
/tool netwatch
add down-script="/ip route set [find comment=\"MOBILE-WiFi-PRINTER\"] disable=yes" host=192.168.3.3 interval=10s timeout=2s up-script="/ip route set [find comment=\"MOBILE-WiFi-PRINTER\"] disable=no"
add down-script="/ip route set [find comment=\"Revision-SERVER\"] disable=yes" host=192.168.3.252 interval=10s timeout=2s up-script="/ip route set [find comment=\"Revision-SERVER\"] disable=no"

Данные правила играют очень простую роль, что кстати напоминает ip sla + track из мира Cisco.

Мы пингуем сервер и Wi-Fi принтер каждые 10 секунд с таймаутом в 2 секунды. Если ping успешен, включаем статический маршрут, который моментально благодаря редистрибуции переходит в OSPF и главный роутер в офисе узнает где находятся устройства.

Таким образом, Wi-Fi принтер теперь снова печатает, как и прежде, а программисты могут работать по RDP напрямую с сервером ревизии. Словно у нас сохранилась плоская сеть.

Статью написал спустя полгода, с момента окончательного запуска проекта в работу на полную. За эти полгода, все работает прекрасно и без сбоев. Wi-Fi принтер успешно ловится, аварии у ISP к сожалению случаются, но магазины больше этого не замечают.

Статья снова получилась большой, благодарю за внимание и терпение. Буду рад критике и замечаниям. Если есть вопросы задавайте с удовольствием отвечу.

Комментарии (1)

    Let's block ads! (Why?)

    [Перевод] Как настроить двухфакторную аутентификацию для логина и sudo

    Марсоход Opportunity более чем в 40 раз превысил запланированный срок службы

    пятница, 3 июня 2016 г.

    Динамический blur на Android

    Security Week 22: Microsoft против паролей, судебные неувязки с Tor, криптолокер атакует клиентов Amazon

    Device Lab от Google: Android TV

    Комментарии (0)

      Let's block ads! (Why?)

      Основатель Uber Трэвис Каланик — «мятежник в элите Кремниевой долины»

      image

      Основатель и генеральный директор такси-сервиса Uber Трэвис Каланик впервые посетит Россию.

      Каланик приедет в Москву в воскресенье 5 июня и вечером того же дня выступит в Институте медиа и дизайна «Стрелка» с лекцией, посвященной вопросам развития транспорта в XXI веке. Каланик расскажет аудитории, «сможет ли каршеринг и усовершенствованный общественный транспорт вытеснить личные автомобили, и заменят ли гибридные и электрические машины привычные бензиновые и дизельные», говорится в сообщении на сайте «Стрелки».

      Сервис для вызова частных водителей Uber — самая быстрорастущая компания в истории. Uber привлек от государственного фонда Саудовской Аравии $3,5 миллиарда. По подсчетам The Wall Street Journal, оценка самого дорогого стартапа в мире приблизилась к $68 миллиардам.

      К своим 39 годам Каланик стал одним из самых богатых предпринимателей с состоянием в $6,2 миллиарда. Личность основателя Uber вызывает противоречивую реакцию как у общественности, так и у людей, знакомых с ним лично: некоторые его ненавидят, а некоторые им восхищаются.

      Счастливое бизнес-детство


      Трэвис Каланик вырос в районе Нортридж на окраине Лос-Анджелеса. У него есть брат, ставший пожарным, и две сводные сестры. Отец работал инженером, мама продавала рекламу в газете Los Angeles Daily News. В детстве Каланик мечтал стать шпионом. Каким был бы его путь на этом поприще — неизвестно. Но никто не станет спорить, что у Трэвиса с самого детства были задатки продавца. В школьные годы он уже ходил по подъездам и продавал ножи марки Cutco.

      «У меня было чувство, что он постоянно пытается что-нибудь мне продать», вспоминает одноклассница Каланика. Другая одноклассница вспоминает о нем как о великолепном рассказчике, энергичном и ищущем выгоды любой ценой.

      image

      Первый бизнес


      В 18 лет Каланик запустил первый бизнес — курсы по подготовке к тесту SAT «Академия нового мышления». SAT состоит из трех частей — математика, анализ текста и грамматика. За каждый давалось максимум 800 баллов, итого 2400 за три.

      Каланик утверждал, что первый прошедший его курс «1500 и больше» ученик улучшил результат на 400 баллов. Сам Каланик набрал 1580 по первым двум частям. Его подвели два вопроса по лингвистике, пишет Business Insider. В цифрах, как любит прихвастнуть Каланик, он разбирается куда лучше, чем в словах, и может за восемь минут решить математическую часть SAT.

      Закончив школу, Каланик поступил на программирование в Калифорнийский университет в Лос-Анжелесе, получив на SAT практически максимальные баллы.

      Первый провал


      В университете он познакомился с первыми партнёрами Майклом Тоддом и Винсом Бусамом, с которыми начал работу над Scour — сервисом для обмена файлами. Шон Фэннинг, один из первых пользователей Scour, через 18 месяцев запустил похожий стартап — Napster. Каланик больше остальных занимался маркетингом и рекламой. Для продвижения продукта Scour Exchange (SX) он даже подвесил на дверные ручки комнат в общежитии бутылочки с лубрикантом, наклеив на них стикеры с логотипом Scour и фразой «Не открывай, SX работает».

      image

      «Каланик вёл переговоры так, что все вокруг забывали о том, что ему всего 20 лет», — говорит бывший глава компании Disney Майкл Овитц, купивший вместе с миллиардером Роном Берклом 51% акций Scour. Позже, наблюдая за тем, как Каланик общается с властями, Овитц скажет, что глава Uber — человек, которого «отправляешь на ринг, и он всегда побеждает».

      Scour существовал три года, пока не получил иск от 30 крупных медиакомпаний, обвинявших сервис в нарушении авторских прав, на сумму в $250 миллиардов. Компании пришлось объявить о банкротстве. Каланик воспринял это как личное поражение и долгое время не ходил в кино, чтобы не видеть на экране логотип Universal Pictures и других корпораций, убивших его детище.

      RedSwoosh и Jam Pad


      Выступая на конференции FailCon, где предприниматели рассказывают о своих неудачах, Каланик сообщил о новом проекте. С ним был связан хитроумный план мести «убийцам» его прошлого проекта. Идея состояла в том, чтобы заставить 30 компаний, засудивших Scour, платить ему. Он рассчитывал распространять бесплатный или лицензионный контент и получать деньги с каждой компании, подавшей иск к Scour. Так появился файлообменник RedSwoosh — сервис, позволяющий дёшево передавать большие по объёму файлы вроде качественного фото и видео.

      По данным The Fortune, в конце концов 23 из 29 судившихся со Scour компаний либо стали клиентами RedSwoosh, либо периодически распространяли с ее помощью свой контент. Но вскоре деньги у Каланика кончились: ему нечем было даже платить зарплату семерым сотрудникам.

      В 2007 году Akamai заплатил за RedSwoosh $23 миллиона. На вырученные деньги Каланик купил большой дом в Сан-Франциско с теннисным кортом и хорошим видом, назвал его Jam Pad и стал проводить там так называемые jam-сессии, в ходе которых предприниматели обсуждали свои идеи. Каланик часто принимал у себя стартаперов.

      Предлагая своё жильё участникам IT-конференции, он описывал его как «место, где предприниматели регулярно зависают, высказывают идеи и едят фантастические блюда, приготовленные поваром Jam Pad». Он много инвестировал. «Если ты нравился Трэвису, он вкладывался в твою компанию и помогал бесплатно», — вспоминает Грег Кречмар: когда он искал деньги для стартапа Livefyre, Каланик представил его 45 инвесторам менее чем за неделю и вложился сам.

      Uber


      В 2008 году Каланик встретился на одной из конференций с основателем сервиса StumbleUpon Гарретом Кэмпом. Тот рассказал, как в Новый год нанял с друзьями лимузин с водителем за $800. Кэмпу цена показалась грабительской. Ему в голову пришла идея разработать приложение, которое позволит делить машину с другими желающими из Кремниевой долины.

      В 2009 году они вместе с Калаником создали Ubercab — мобильное приложение, позволявшее одним кликом вызывать личного водителя. Тогда сервисом пользовались друзья в Сан-Франциско, мало кто относился к нему серьёзно. Когда Камп спросил Каланика, будет ли он заниматься им постоянно, тот ответил отрицательно — полностью посвящать себя такой авантюре было рискованно.

      Год назад основателя Трэвиса Каланика обвинили в краже идеи и технологий. Якобы Кевин Халперн из Калифорнии создал прототип сервиса для заказа такси через мобильное приложение много лет назад. Предприниматель требовал возместить ущерб на сумму в один миллиард долларов.

      Халперн утверждал, что свой прототип он разработал еще в 2002 году, в своей компании Celluride Wireless. Они познакомились с Калаником в 2006 году. Тогда Халперн и продемонстрировал ему свои наработки. Каланик якобы воспользовался ими для создания собственного проекта. Заслуживает внимания упоминание об их повторной встрече в 2008 году. Именно тогда он раскрыл Каланику детали проекта. А через год после этого был запущен сервис Uber. Представители компании убеждены, что претензии безосновательны.

      О будущем Ubercab много спорили. Одни говорили, что сервис нужно сфокусировать на сегменте люкс, добавив функции заказа вертолётов и самолётов. Другие предлагали делать Ubercab массовым, позволяющим ездить на дорогих чёрных машинах дешевле, чем в целом по рынку. Так считал и Каланик. Он рассуждал: «Чем больше людей захотят этим пользоваться, тем больше водителей будет готово предоставить такие услуги. Конкуренция вырастет, стоимость снизится, а время подачи машины уменьшится».

      image

      Родители Трэвиса Каланика были первыми пассажирами Uber, запустившегося в Лос-Анджелесе.
      В октябре 2011-го Каланик привлёк к проекту внимание ведущих венчурных инвесторов, включая сооснователя Netscape Марка Андриссена, который вошёл в совет директоров сервиса. Шервин Пишевар из Menlo Ventures купил долю и инвестировал $20 миллионов. В сервис вложился Джефф Безос, глава Amazon. Uber стали пользоваться голливудские звёзды, с которыми Каланик был знаком: Эштон Катчер, Jay Z, Эдвард Нортон и другие.

      Благодаря этому Uber стал известным. За пять лет компания получила $8,21 миллиарда от ведущих венчурных фондов, наняла 3000 сотрудников и открыла офисы в десятках стран. Каланику удалось то, что не удавалось Facebook и Google, — выйти на китайский рынок и завоевать аудиторию, несмотря на сопротивление местных игроков.

      В Uber нелегко попасть, но еще труднее его покинуть


      На текущий момент в составе Uber работает около 6700 сотрудников, а количество ушедших за последние годы минимально по меркам крупного стартапа. Причина проста — Uber усложнила процесс выхода для сотрудников за счет выдачи опционов на потенциально большие суммы.

      Например, при выдаче 0,5% акций в качестве бонуса на старте и последующих инвестициях в районе $11 миллионов, а также оценочной стоимости в $60 миллионов по состоянию на 2011 год, этот пакет акций стоил бы $300 тысяч. При росте капитализации до $60 миллиардов такой пакет акций вырос бы в цене до $299,7 миллиона. Но при выходе из Uber сотрудник обязан в течение 90 дней выплатить налог в размере $119,8 миллиона. Причём обязанность выплатить налог вступает в силу сразу после ухода из Uber.

      Со своей стороны Uber накладывает ограничения на продажу пакетов акций на третьем рынке, запрещая передавать их в венчурные фонды или частным инвесторам.

      Ранее сам Каланик продал часть своих акций Uber. Один из журналистов спросил предпринимателя, рассматривает ли он возможность продажи всей компании. Однако гендиректор Uber заявил, что продажа части акций была спланирована в рамках стратегии развития стартапа.

      «Какую вы ожидаете реакцию, если спросить счастливого в браке мужчину, кто будет его следующей женой?», задал встречный вопрос основатель компании. «У меня были жены», продолжил он с улыбкой. – «Но сейчас я сосредоточен только на одной (Uber)», заявил Каланик.

      «За прошедшие 1,5 года мы привлекли более $10 миллиардов, поэтому у нас есть деньги. Наши партнеры привлекают миллиарды долларов и попадают в долги. Однако наша задача – быть дисциплинированными при создании бизнеса», добавил он.

      image

      Стиль руководства


      «Мне нравится думать о себе как о Вульфе из Криминального чтива», — сказал однажды Каланик группе чикагских предпринимателей. Он считает себя холодным и рациональным человеком, который никогда не останавливается.

      Каланик обожает спорить. Когда CTO Uber Туан Фам устраивался в компанию в 2012 году, Каланик звонил ему каждый день две недели подряд, спрашивая, как лучше всего общаться с инженерами. Они много дискутировали. В итоге Фам понял, что Каланик хочет, чтобы сотрудники не соглашались с каждым его словом, а высказывали свои предложения. В конце концов побеждают лучшие идеи.

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

      Личная жизнь


      С 2015 года Трэвис встречается со скрипачкой и колумнисткой Huffington Post Габи Хольцварт.

      image

      Личные качества


      «Он не спит. Он не теряет фокуса. Он иногда даже забывает, что голоден. Он пробует снова и снова, вдохновляя окружающих своей страстью до самого конца игры. Так, если Трэвис решил, что он хочет сделать более чистый, безопасный и простой сервис такси, чем тот, что сейчас есть, он сделает эту работу. Если он нацелился на реформирование коррумпированной, проникающей повсюду и направленной против потребителей системы регулирования, увидите, скоро она рухнет, увлекая за собой тех, кто своими бесчестными сделками призвал ее к жизни. Если он хочет убить расизм, который удерживает людей разных цветов кожи от получения доступа к такси, он добьется желаемого», – так пишет о Каланике его знакомый, Крис Сакка.

      Ему упрямство не знает границ. Однажды он девять часов подряд провел в офисе Google, уговаривая одного из сотрудников перейти к нему.

      Каланик всегда был амбициозным. Это помогло ему к 37 занять 13-е место в списке предпринимателей Fortune «40 до 40»: издание назвало его «мятежником в элите Кремниевой долины».

      «Меня спрашивают: дела идут так хорошо, чувствуешь ли и ты себя великолепно? Но мой подход к жизни таков, что я всегда тяготею к некоторому дискомфорту, — признавался Каланик — Я всегда чувствую себя так же, как 15 лет назад».

      Знакомые Каланика говорят, что двойственность — часть его характера, и, возможно, одна из причин успеха. Идеология — противоречивость.

      Однажды ночью он ждал у клуба своего друга Шона и повздорил c охранником. Тот попросил его уйти. «Я не нарушаю закон», — повторял Каланик, не двигаясь с места. Охранники вызвали полицию, Паркеру пришлось заплатить $2000, чтобы спасти друга. В другой Каланик с сотрудниками RedSwoosh прилетел в Мексику. Он сел в такси, но решил, что его хотят обсчитать, и отказался платить. Водитель заблокировал дверь, предпринимателю пришлось выпрыгивать из машины на ходу.

      Советы основателя от Трэвиса Каланика


      В январе издание «Секрет фирмы» опубликовало фрагменты лекции Каланика в Индийском институте технологий в Мумбаи:

      Суть стартапа в постоянном решении проблем. Вот почему я так люблю инженеров — никто лучше них не умеет преодолевать трудности. Именно этим они и занимаются каждый день: превращают сломанные вещи в работающие.

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

      Умные стартаперы знают, что даже если их идея не сработает, найдётся тысяча компаний, которые возьмут их на работу, но они всё равно будут лучше и умнее, потому что попытались сделать то, что никто не пытался.

      Вы должны быть не победителем, а чемпионом. Если вы упали, поднимайтесь снова и снова, пока не достигните успеха. Неудача — это состояние души. В моей жизни был период, когда я терпел неудачи шесть лет подряд, но каждый раз я начинал всё сначала.

      С другой стороны, нужно уметь вовремя переключаться. Если вы тратите все свои силы на то, чтобы заставить идею работать, и взамен получаете только физические или эмоциональные страдания и совсем не продвигаетесь вперёд, лучше переключитесь на что-нибудь ещё.

      У большинства людей есть хорошие идеи, но они редко их реализуют. Uber — это хорошая идея. Я не знаю, были ли мы первыми, кто это придумал, но мы точно были первыми, кто это сделал.

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

      Основная задача предпринимателя — стать экспертом по шахматам и предсказывать ходы соперника. В этом случае, когда инвестор что-то предложит вам, вы скажете: «Это интересно, но я могу назвать 1800 причин, почему это не работает. Вот 3650 причин для правильного хода».

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

      Путь предпринимателя часто связан с одиночеством. Иметь партнёра очень полезно, особенно в тяжелые времена (которые поначалу наступают слишком часто). Веселье начинается только после пяти лет тяжелого труда.

      Комментарии (0)

        Let's block ads! (Why?)

        IBM представляет первую в мире память PCM с записью трёх бит в ячейку

        [Из песочницы] World of Tanks: от чего же зависит винрейт танков?

        Как мы разработали чат-фреймворк для Android приложения — Chateau

        [Из песочницы] Событийная модель на основе async и await

        В далеком 2012, когда цена на нефть еще была трехзначной, а трава зеленее, майкрософтом был выпущен .NET 4.5, а с ним и конструкция async/await. Про неё написано уже довольно много статей (Async в C#), а большинство разработчиков C# хорошо её изучили. Но все ли варианты использования были рассмотрены, можно ли выжать из await немного больше?

        Самым очевидным вариантом использованием этой конструкции является ожидание завершения некой асинхронной операции. Первое, что приходит на ум — это ожидание ввода-вывода. Например, мы послали запрос клиенту и ожидаем ответа, тогда используя await мы сможем продолжить выполнение кода после получения ответа, а сам код при этом будет выглядеть синхронным. Но что если во время ожидания возникнет необходимость прервать выполнение этой операции? Тогда нам придется использовать CancellationToken, причем если таких операций несколько, то токены необходимо будет линковать или использовать один общий токен. При этом причина отмены будет скрыта от кода, использующего этот CancellationToken. Кроме отмены, код должен поддерживать обработку потери соединения, таймаута, возвращаемых ошибок и т.д.

        В классическом варианте это выльется в использование CancellationToken для обработки отмены, try catch для обработки разрыва соединения и код анализа возвращенных данных, для оценки результата запроса. Но можно ли уместить всё это в единой парадигме? В этот статье я предлагаю рассмотреть альтернативный подход, основанный на событийной модели с использованием синтаксического сахара async/await.

        Библиотека Eventing.


        Всё необходимое для событийной модели на async/await было оформлено в виде библиотеки Eventing и выложено на GitHub под лицензией MIT.

        Библиотека протестирована и успешно используется на боевой системе более двух лет.

        Использование


        Описанный в начале пример с использованием Eventing будет выглядеть так:
        var @event = await this.EventManager.WaitFor<MessageReceived, CancelRequested>(TimeSpan.FromSeconds(50));
        
        if (@event == null)
            Log.Info("timeout");
        else if (@event is CancelRequested)
            Log.Info("Cancelled, reason: {0}", ((CancelRequested) @event).Reason);
        else
            Log.Info("Message received");
        
        

        Здесь мы используем EventManager — менеджер событий реализующий интерфейс IEventManager, для ожидания событий MessageReceived и CancelRequested с таймаутом в 50 секунд. С помощью вызова WaitFor мы формируем подписку на указанные события, а вызов await блокирует дальнейшее исполнение кода(но не потока). Оно останется заблокированным до тех пор, пока не произойдет одно из указанных событий или истечет время таймаута, после чего выполнение продолжится в текущем контексте синхронизации. Но что если связь с клиентом будет потеряна во время формирования подписки? В этом случае код зависнет на 50 секунд, так как событие отключения клиента будет упущено. Исправим это:
        // Создание подписки
        var eventAwait = this.EventManager.WaitFor<MessageReceived, ClientDisconnected, CancelRequested>(TimeSpan.FromSeconds(50), 
                    e => !(e is ClientDisconnected) || ((ClientDisconnected)e).id == client.Id); // Фильтр события
        
        if (!client.Connected || cancelRequested) {
            // Случай отключения клиента или запроса на отмену во время создания подписки
            Log.Info("Client disconnected or cancel requested");
            return;
        }
        
         //  Прерывание кода до наступления события
         var @event = await eventAwait;
         ...
        
        

        Здесь мы добавили событие ClientDisconnected и разделили создание awaitable переменной eventAwait и непосредственно ожидание события. Если бы мы не разделили их, то клиент мог бы отключиться после проверки client.Connected и ожиданием события, что привело бы к потери события. Также был добавлен фильтр событий, который исключает события ClientDisconnected не относящиеся к текущему клиенту.

        Как создать событие?


        Для этого надо создать класс, имплементирующий IEvent:
        class CancelRequested : IEvent {
            public string Reason { get; set; }
        }
        
        

        А затем вызвать IEventManager.RaiseEvent, например:
        this.EventManager.RaiseEvent(new CancelRequested()). 
        
        

        Наследование от IEvent отделяет события от остальных классов и предотвращает использование неподходящих экземпляров в методе RaiseEvent. Также поддерживается наследование:

        class UserCancelRequested : CancelRequested {
        }
        
        class SystemCancelRequested : CancelRequested {
        }
        
        var @event = await this.EventManager.WaitFor<CancelRequested>();
        if (@event is UserCancelRequested)
            ...
        
        

        Если у вас сложная система в которой множество одновременно ожидаемых событий, использование события CancelRequested вместо токенов отмены, позволит избежать прокидывания и линкование глобального и локального CancellationToken. Это важно, так как сложное линкование повышает вероятность пропустить утечку памяти из-за удержания токенов.

        Как подписаться на событие?


        Некоторые события носят периодический характер, такие события можно получать методом IEventManager.StartReceiving:
        void StartReceiving<T>(Action<T> handler, object listener, Func<T, bool> filter = null, SynchronizationContext context = null) 
                               where T : IEvent;
        
        

        Обработчик handler будет вызван в контексте синхронизации context при каждом событии T, которое удовлетворяет фильтру filter, если он задан. Если контекст синхронизации не задан, то будет использован SynchronizationContext.Current.

        Как это работает?


        Используется всё тот-же механизм тасков, на котором основан async/await. При вызове WaitFor менеджер событий создает таск используя TaskCompletionSource и формирует подписку по выбранным типам событий в шине сообщений.
        // EventManager.cs, создание подписки
        var taskCompletionSource = new TaskCompletionSource<IEvent>();
        
        var subscription = new MessageSubscription(
                    subscriptionId,
                    message => {
                        var @event = message as IEvent;
                        if (filter != null && !filter(@event))
                            return;
        
                        // Устанавливаем результат исполнения задачи
                        if (taskCompletionSource.TrySetResult(@event))
                            this.trace.TraceEvent(TraceEventType.Information, 0, "Wait ended: '{0}' - '{1}'",
                                subscriptionId, message.GetType());
                    },
                    this, UnsubscribePolicy.Auto, this.defaultContext, eventTypes);
                    
        this.messageBus.Subscribe(subscription);
        ...
        return taskCompletionSource.Task;
        
        

        При генерации события вызывается метод RaiseEvent, который передает событие в шину, а она в соответствии с типом события выбирает подписки, в которых eventTypes включает в себя этот тип. Далее вызывается обработчик подписки и если он удовлетворяет фильтру, то устанавливается результат исполнения задачи и разблокирует вызов await.
        // EventManager.cs, генерация события
        public void RaiseEvent(IEvent @event) {
            this.trace.TraceEvent(TraceEventType.Information, 0, "Event: {0}", @event);
        
            this.messageBus.Send(@event);
        }
        
        // MessageBus.cs, отправка сообщения
        public void Send(object message) {
        var messageType = message.GetType();
        IMessageSubscription[] subscriptionsForMessage;
        
        lock (this.subscriptions) {
            subscriptionsForMessage = this.subscriptions
                .Where(s => s.MessagesTypes.Any(type => messageType == type || type.IsAssignableFrom(messageType)))
                .ToArray();
        }
        
        ...
        
        foreach (var subscription in subscriptionsForMessage)
            subscription.ProccessMessage(message);
        
        this.UnsubscribeAutoSubscriptions(subscriptionsForMessage);
        ...
        
        // MessageSubscription.cs
        public void ProccessMessage(object message) {
            var messageHandler = this.handler;
            this.SynchronizationContext.Post(o => messageHandler(message), null);
        }
        
        

        В MessageSubscription.ProccessMessage сообщение передается в заданный пользователем контекст синхронизации, что позволяет избежать задержок при отправке сообщения.

        Избавь мой класс от многопоточности!


        Каждый, кто работал с async/await знает, что после завершения await код продолжает свое исполнения не в текущем потоке, а в текущем контексте синхронизации. Это может быть проблемой, если вы подпишетесь на событие с помощью StartReceiving, а затем вызовите WaitFor, что приведет к тому, что код класса будет исполняться одновременно в разных потоках(обработчик событий из StartReceiving и код после await // как страшно жить!). Это легко исправить однопоточным контектстом синхронизации, входящим в библиотеку:
        this.serverSynchronizationContext = new SingleThreadSynchronizationContext("Server thread");
        this.clientSynchronizationContext = new SingleThreadSynchronizationContext("Client thread");
        
        this.serverSynchronizationContext.Post(async o => await this.RunServer(), null);
        this.clientSynchronizationContext.Post(async o => await this.RunClient(), null);
        
        

        Таким образом у нас клиент всегда будет выполняться в потоке «Client thread», а сервер в «Server thread». Вы сможете писать многопоточный код не задумываясь о race condition. В качестве бонуса это позволит максимально утилизировать отдельно взятый поток.

        В чем преимущество?


        Главным преимуществом является простота и тестируемость кода. Если насчет первого можно спорить, простоту каждый понимает по своему, то со вторым пунктом всё очевидно. Многопоточное приложение можно протестировать в одном потоке, эмулируя любую последовательность событий, причем для этого не требуется создавать mock объекты, любое взаимодействие можно свести к событиям, а их проверку к вызову RaiseEvent. Пример NUnit:
        /// <summary>
        ///     This test demonstrates how to test application that uses Eventing
        ///     All code executes sequently in one thread
        /// </summary>
        [TestFixture]
        public class TestCase : TestBase {
            [Test]
            public async Task ClientDoesWork() {
                var client = new Client(this.EventManager);
                var doWorkAwaitable = client.DoWork();
        
                this.EventManager.RaiseEvent(new Connected());
        
                // We can debug and step into 
                this.React();
        
                await doWorkAwaitable;
        
                Assert.AreEqual(true, client.Connected);
            }
        }
        
        

        Как это можно использовать?


        Чтобы не переполнять статью листингами, приведу лишь краткое текстовое описание одной из системы, где используется Eventing. Это горизонтально масштабируемая распределенная система, состоящая из четырех типов узлов, один из которых является мастером. Мастер непрерывно общается со всеми узлами и управляет выполнением на них различных операций. Каждую операцию можно представить в виде конечного автомата, где переход это наступление события(в том числе таймаут или отмена). Хотя для каждой операции и можно было автомат реализовать в его классическом виде(что мы изначально и сделали), намного проще оказалось представить его используя Eventing, где текущее состояние определялось точкой выполнения кода, а не отдельной переменной. При это на каждом шаге были явно перечислены все ожидаемые события, что упрощало тестирование белого ящика.

        Заключение


        В статье рассмотрены ключевые возможности и варианты использования библиотеки Eventing. Библиотека не претендует на универсальность и поддержку высоконагруженных систем, но призывает немного по другому взглянуть на привычные вещи, позволяет писать безопасный и легко тестируемый с точки зрения многопоточности код.

        Комментарии (0)

          Let's block ads! (Why?)

          Быстрое клонирование объектов в JavaScript

          Как перенести центр разработки из России в Чехию

          Шестое чувство Facebook

          Расширение для Chrome показывает, когда кто-то набирает текст


          Некоторые люди слишком много времени проводят в социальных сетях. Настолько много, что у них уже возникает зависимость. Один из таких — программист Александр Кирзенберг (Alexandre Kirszenberg), который к тому же любит копаться во внутренностях Facebook — в коде JavaScript, отвечающем за пользовательский интерфейс и коммуникации.

          «Пару месяцев назад я задумался о маленьком статусном индикаторе, который показывает, когда один из ваших друзей набирает вам текст, — пишет Александр. — Такое маленькое расширение UI выдаёт много информации о собеседнике. Если индикатор несколько раз загорается и тухнет, это говорит о нерешительности. Если он загорелся надолго, кто-то пишет вам большое эссе. И нет ничего хуже того мучительного чувства, когда индикатор тухнет и больше не загорается».

          Первым делом Александр решил найти, присылает ли Facebook уведомления о том, что кто-то набирает сообщения в Facebook Messenger, даже если у вас не запущен этот Facebook Messenger. Оказалось, что присылает.

          Всем френдам рассылается событие typ длинного опроса /pull. Небольшое исследование показало, что событие действительно рассылается для каждого чата, даже если получатель не открывал его и никогда не получал.

          Так появилось расширение Facebook Sixth Sense для браузера Chrome. Оно показывает прямо в браузере, когда кто-то набирает сообщение в Facebook.

          Для создания этого расширения программист использовал недокументированные Facebook API. Пришлось разбираться с кодом JavaScript, который Facebook безжалостно минифицирует, превращая в мешанину символов.

          Сначала он выяснил, какие модули Facebook импортирует через программный интерфейс системы организации модулей Asynchronous Module Definition для асинхронной загрузки (у Facebook собственная реализация AMD). Модули и зависимости определяются стандартной функцией __d(name, dependencies, factory). Есть также require и requireLazy для импорта модулей.

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

          Но мы всё-таки осмелимся.

          Как видим, Facebook всегда загружает последнюю версию React — отличной библиотеки компонентов пользовательских интерфейсов. Facebook довольно интенсивно использует React по всему сайту. В коде Facebook более 15 000 компонентов React (по состоянию на октябрь 2015 года).

          В исходном коде можно поискать __d( и посмотреть список модулей, доступных для импорта. Для главной страницы там всего-то 3000 модулей.

          В чате Facebook Messenger, разумеется, тоже используются компоненты React. Нам нужно перехватить нотификации о наборе текста. Для более детального изучения кода Александр Кирзенберг рекомендует использовать инструмент React Developer Tools.

          После установки этого расширения в инструментах разработчика Chrome появляется новая вкладка React. На ней выделяем чат.

          Здесь среди различных компонентов Facebook Messenger ищем индикатор набора текста, он находится между <ChatTabComposerContainer /> и <MercuryLastMessageIndicator />.

          Поиск __d('ChatTyping в кодовой базе React находит два модуля: ChatTypingIndicator.react.js и ChatTypingIndicators.react.js. Это именно то, что нам нужно, пишет Кирзенберг. Он замечает, что некоторые модули подгружаются по мере необходимости, так что ChatTypingIndicators.react.js можно обнаружить только со второго раза.

          Вот его код.

          function() {
            var k = c('MercuryThreadInformer').getForFBID(this.props.viewer)
              , l = c('MercuryTypingReceiver').getForFBID(this.props.viewer);
            this._subscriptions = new (c('SubscriptionsHandler'))();
            this._subscriptions.addSubscriptions(
              l.addRetroactiveListener(
                'state-changed',
                this.typingStateChanged
              ),
              k.subscribe(
                'messages-received',
                this.messagesReceived
              )
            );
          },
          

          А именно, нас интересует вызов c('MercuryTypingReceiver').

          В консоли можно посмотреть, как он работает.

          > MercuryTypingReceiver.getForFBID
          // function (i){var j=this._getInstances();if(!j[i])j[i]=new this(i);return j[i];}
          > MercuryTypingReceiver.get
          // function (){return this.getForFBID(c('CurrentUser').getID());}
          

          Для проверки, как работает статусный индикатор, Александр использовал приложение Messenger на собственном смартфоне, чтобы отправить себе на ПК соответствующие события и словить их в консоли.

          Более подробно изучив код, он нашёл ещё два полезных модуля MercuryThreads и ShortProfiles. Первый получает всю информацию о треде Messenger по его идентификатору, второй делает то же самое по профилю.

          В общем, после всех изысканий вот как выглядит окончательный код расширения для Chrome, всего 40 строчек.

          function getUserId(fbid) {
            return fbid.split(':')[1];
          }
          
          requireLazy(
            ['MercuryTypingReceiver', 'MercuryThreads', 'ShortProfiles'],
            (MercuryTypingReceiver, MercuryThreads, ShortProfiles) => {
          
              MercuryTypingReceiver
                .get()
                .addRetroactiveListener('state-changed', onStateChanged);
          
              // Called every time a user starts or stops typing in a thread
              function onStateChanged(state) {
          
                // State is a dictionary that maps thread ids to the list of the
                // currently typing users ids'
                const threadIds = Object.keys(state);
          
                // Walk through all threads in order to retrieve a list of all
                // user ids
                const userIds = threadIds.reduce(
                  (res, threadId) => res.concat(state[threadId].map(getUserId)),
                  []
                );
          
                MercuryThreads.get().getMultiThreadMeta(threadIds, threads => {
                  ShortProfiles.getMulti(userIds, users => {
                    // Now that we've retrieved all the information we need
                    // about the threads and the users, we send it to the
                    // Chrome application to process and display it to the user.
                    window.postMessage({
                      type: 'update',
                      threads,
                      users,
                      state,
                    }, '*');
                  });
                });
          
              }
            }
          
          );
          

          Неплохой такой хак, слегка раскрывающий внутренности Facebook.

          Исходный код расширения опубликован на Github.

          Кстати, по временным меткам из мессенджера Facebook можно даже отслеживать режим сна своих френдов (исходный код).

          Комментарии (1)

            Let's block ads! (Why?)

            Делаем собственный сервис по определению WHOIS любого домена

            четверг, 2 июня 2016 г.

            Schneider Electric получила премию DCS Awards за инновационные решения

            Google I/O 2016: развитие платформы Firebase

            Привет, Хабр! Полтора года назад команда разработчиков Firebase вошла в наш дружный Google-коллектив. С тех пор наш BaaS (backend-как-сервис) вырос больше чем в четыре раза — со 110 до 450 тысяч разработчиков. И всё это время мы предоставляли всё те же услуги —  БДРВ (базы данных реального времени), авторизацию пользователей, хостинг — делая разработку приложений проще. Настало время двигаться дальше, так что мы рады представить вам крупное расширение возможностей Firebase.

            Firebase становится универсальной платформой для построения Android-, iOS- и мобильных веб-приложений. Новые инструменты, направленные на упрощение разработки, привлечения пользователей и монетизации, а также новый продукт в области аналитики ждут вас под катом.

            Мы всегда сохраняли верность тем принципам, которые были заложены в Firebase изначально:

            • Разработчик — наш пользователь, а пользовательский опыт очень важен. Лёгкость применения, качественная документация, интуитивно-понятные API делают разработчика счастливым;
            • Кростплатформенность. Нам в равной степени важны iOS, Android и мобильный веб;
            • Интеграция продуктов там, где это возможно. У Firebase один SDK, одна консоль, и одно место, в котором вы можете получить ответы на интересующие вас вопросы, поддержку и всю необходимую документацию. Вы выбираете, что из наших возможностей и в какой комбинации сочетать, наша задача — обеспечить максимально быструю и комфортную работу с данными везде, где это возможно.

            Firebase Analytics


            Firebase Analytics – это новый бесплатный инструмент для… анализа мобильных приложений. Отчасти он унаследовал кое-что от Google Analytics, но имеет ряд существенных отличий:

            Во-первых, Firebase Analytics работает вокруг пользователя и событий. Сессии, просмотры страниц и экранов приложений — это хорошо, но это уже есть у Google. Наш новый продукт ацентрирует внимание на том, что именно пользователь делает в вашем приложении. Также вы сможете узнать, откуда именно приходят к вам пользователи — отслеживание платной рекламы и каналов привлечения пользователей выдаёт наглядные графики и таблицы.

            Во-вторых, мы уже говорили про принцип разумной интеграции — здесь он реализован на полную катушку. FA предоставляет достоверную информацию об активности пользователей внутри приложения, что позволило реализовать новую функцию — Аудитории. Аудитории позволяют вам выявить различные группы пользователей со схожим свойствами. Впоследствии вы сможете получать раздельную информацию для различных Аудиторий внутри единой среды Firebase.

            Ускоряем разработку с функциями Messaging, Storage и Config


            Современные приложения очень часто в той или иной мере используют интерактивные взаимодействия — поэтому мы расширяем наши backend-сервисы. Google Cloud Messaging — самый популярный сервис по доставки push-уведомлений из облака на девайсы теперь интегрирован в Firebase и азывается FCM — Firebase Cloud Messaging. Он полностью бесплатен, не имеет ограничений, отлично оптимизирован, бережёт батарейку клиентских устройств и прекрасно работает на iOS, Android и в современных браузерах. В самой основе FCM лежит масштабируемость — уже сегодня через него отсылается более 170 млрд.(!) сообщений ежедневно на ~ 2 млрд. различных устройств.

            Нас давно просили добавить возможность хранить изображения, видеоролики и просто научиться передавать файлы — теперь, благодаря Google Cloud Storage, мы предоставляем и такую возможность. Firebase Storage позволит разработчикам легко и безопасно организовывать загрузку и хранение файлов, а надёжная платформа и технологии Google обеспечивают непревзойдённые доступность, интеграцию в Google-сервисы и масштабируемость. Мы также уделили внимание продвинутой логике в клиентском SDK для Firebase Storage, так что наш сервис отлично работает даже в условиях нестабильного интернет-соединения.

            Firebase Remote Config позволяет разработчикам подстраивать и обновлять элементы приложения на лету без необходимости обновлять пакет приложения и ждать, пока он станет доступен в магазине приложений, а затем обновится у пользователей. Вы можете включать и выключать определённые элементы приложений, распространять апдейт на конкретные Аудитории пользователей — и всё это буквально в пару кликов.

            Разумеется, мы не забыли и про уже имеющиеся продукты — БДВР, хостинг и аутентификацию пользователей. Хостинг получил новый интерфейс и бесплатную поддержку сторонних доменов для всех разработчиков. База данных получит крупное обновление в ближайшее время, но пока мы не можем ничего о нём рассказать. Ждите, апдейт вас не разочарует. Самое крупное обновленип получила Firebase Authentication — здесь и новый SDK, и переработанная backend-структура — всё, что нужно для улучшений в области безопасности, надёжности и масштабируемости. Внутри используются те же технологии, что и в других Google-продуктах, работающих с аккаунтами Google-пользователей. Мы также добавили связанные учётные записи и подтверждение владения электронной почтой — то, о чём нас просили уже давно.  

            Упрощаем отладку: Test Lab и Crash Reporting


            Падающие приложения — это плохо. Пользователи недовольны, пишут всякие гадости в отзывах, ставят одну звезду, уходят к конкурентам. FIrebase Crash Reporting собирает и отсылает вам самую важную информацию, которая может помочь в поиске проблем iOS / Android приложений после релиза. Разумеется, здесь также работает функция Аудитории, которая ищет схожие признаки — вы сразу увидите, есть ли что-нибудь общее у пользователей, которые сталкиваются с аналогичной проблемой: одинаковое устройство, локаль, конкретный регион использования приложения, или, может быть, определённые сценарии использования приложения.

            На прошлом I/O (в 2015 году) мы представили Cloud Test Lab — облачное тестирование ваших приложений на реальных девайсах, которые расположены в наших дата-центрах. Теперь этот сервис будет называться Firebase Test Lab и получит все преимущества интеграции с инструментами Firebase.

            Расширяем возможности приложений


            Даже самые полезные приложения рано или поздно сталкиваются со снижением интереса пользователей. У Firebase есть пять эффективных инструментов, которые помогут вам вернуть внимание ваших клиентов.

            Firebase Notifications — новый интерфейс, построенный на базе API Firebase Cloud Messaging, дополненный возможностями Firebase Analytics и Аудиториями. Он позволяет таргетированно разослать уведомления пользователям вашего приложения не прикасаясь к редактору исходного кода. Рассказать о новых акциях, скидках, предложить персональные условия, обратить внимание людей на новые возможности теперь стало проще.

            Firebase Dynamic Links улучшает работу со ссылками сразу по двум направлениям. Во-первых, ссылки стали «надёжными». То есть они ведут в конкретное место приложения (например, на какой-нибудь конкретный проект, событие, компанию, что угодно), даже если пользователь перешёл по ней и только что впервые скачал ваше приложение приложение из Google Play. Больше никаких вопроов «я скачал приложение, что дальше» или повторных переходов по ссылкам. Подобный «тёплый приём» показал отличные результаты по части вовлечения пользователей в работу с приложением.

            Во-вторых, ссылки могут динамически менять своё назначение в зависимости от окружения, в котором они запущены: разные устройства, браузеры, клиенты — что-то вроде продвинутого &utm_source.

            Firebase Invites позволяет вам в два счёта построить реферальную сеть — пусть ваши клиенты приводят новых. Минимум усилий, максимум результата.

            Firebase App Indexing, (бывший Google App Indexing) позволяет находить пользователям Google результаты непосредственно из вашего приложения. Учитывая новые возможности Android N по запускую приложений без установки, ускоренную установку (если она всё ж потребовалась пользователю) и новые возможности Dynamic Links вы будете регулярно пополнять пользовательскую базу теми, кто реально заинтересован в ваших продуктах.

            AdWords, наша рекламная платформа, теперь интегрирована в Firebase. Firebase отслеживает прогресс вашей кампании в AdWords и автоматически заполняет соответствующие разделы в Firebase Analytics. Как вы уже, наверное, догадались, здесь тоже присутствует интеграция Аудиторий и отслеживания событий: таким образом вы сможете настраивать параметры AdWord для достижения максимальной эффективности рекламных кампаний.

            Монетизация приложений с AdMob


            Процесс интеграции различных продуктов было не остановить. :) Так что рекламная площадка Google теперь таже является частью эксосистемы Firebase. Мы упростили работу с AdMob: как только вы начинаете использовать Firebase SDK в своём проекте — AdMob к вашим услугам. Различные рекламные форматы (в том числе и нативная реклама), качественная статистика, интеграция с другими элементами Firebase — уже в комплекте.

            Новая консоль, документация и SDK


            В самом начале поста мы говорили, что у Firebase один SDK, одна консоль, и одно место, в котором вы можете получить ответы на интересующие вас вопросы, поддержку и всю необходимую документацию. Это место — firebase.google.com.

            Ну а так как у Firebase теперь новый дом, то и интерьер мы выбрали самый что ни на есть современный. Новая консоль получила переработанный интерфейс, тесно интегрированный с другими продуктами Google, такими, как Google Play, Google Cloud и теми проектами, которые перебрались под крыло Firebase.

            Интеграция с Google Cloud проведена на очень глубоком уровне. Например, Firebase Analytics может экспортировать сырые данные в BiqQuery для дальнейшего анализа. Мы продолжим налаживать мосты между Google Cloud и Firebase, и расширять ваши возможности по использованию нашего облака. Ещё одним хорошим примером интеграции стала привязка вашего аккаунта разработчика в Google Play к учётной записи в Firebase — таким образом консоль становится центром, в который стекаются данные обо всём: начиная с непладок у пользователей, покупок внутри вашего приложения и особенностями использования у различных групп пользователей, заканчивая финансовыми данными.

            Наконец, мы рады представить вам бета-версию нового C++ SDK. Вся документация и необходимый «стартовый пакет» уже доступны на нашем сайте.

            Ценовая политика


            Большая часть новых продуктов, включая Analytics, Crash Reporting, Remote Config, и Dynamic Links — полностью бесплатны и не имеют каких-либо ограничений. Платные же сервисы — Test Lab, Storage, БДРВ и хостинг — обзавелись упрощённой ценовой сеткой. На сегодняшний день мы предлагаем:
            • Бесплатный тариф SPARK с некоторыми ограничениями, отлично подойдёт для первых шагов, прототипа приложения, курсовой или дипломной работы, начала стартапа;
            • Фиксированную ставку на тарифе FLAME для тех, кому нужна предсказуемая ежемесечная стоимость на ранних этапах развития приложения;
            • Оплату потребляемых ресурсов — конфигурируемый тариф BLAZE для самых крупных клиентов.

            Постоянство прекрасного


            После Google I/O 2016 многое изменилось, но основные принципы Firebase остались прежними. Наша основная цель — простая и комфортная разработка с нашими API, интуитивно-понятные интерфейсы, всеобъемлющая документация и тесная интеграция продуктов. Мы преданы делу кросс-платформенной разработки для iOS, Android и веба, и если вы столкнётесь с трудностями — мы с радостью окажем вам посильную поддержку.

            Если вы уже используете наши продукты — для вас ничего не изменится, пока вы сами того не захотите. Мы будем продолжать поддержку старых клиентов и их продуктов, но советуем ознакомиться с обновлениями и оценить новые возможности Firebase, не зря же мы старались?! :)

            Планы на будущее


            Мы проделали огромную работу, но нам есть, что ещё улучшать в Firebase. На сегодняшний день JavaScript SDK пока что поддерживает не все новые возможности. Мы бросили все силы на то чтобы сократить разрыв в данных технологиях, и мы будем рады услышать ваши отзывы — наверняка, нам есть что ещё улучшить. Оставить мнение о новых возможностях Firebase, сообщить об ошибке или предложить идею можно здесь.

            Ну а пока вы можете лично попробовать новые возможности. Посмотрите наш новый сайт, оцените документацию и попробуйте использовать Firebase в своих продуктах, как уже делают такие крупные проекты, как Shazam, SkyScanner и PicCollage.

            Комментарии (0)

              Let's block ads! (Why?)

              PHD VI: как у нас угнали дрона

              Хаордическая организация Visa (Часть 3)

              В какой бы стране ни оказался сегодня, перед какой бы аудиторией ни выступал, если я покажу кредитную карту NBI и спрошу: «Кто из вас знает, что это такое?» — в ответ поднимется лес рук. Но стоит мне спросить: «А скажите-ка мне, кто владеет NBI, кто ею управляет и где можно купить ее акции?» — как в зале наступит гробовая тишина. Все чувствуют, что речь идет о чем-то необычном, да только не могут выразить словами, что и как. В этом нет ничего удивительного. Результаты деятельности хаордической организации всегда на виду, а вот ее структура, управление и процессы скрыты

              Ди Хок

              Уважаемые читатели, мы продолжаем цикл статей об истории зарождения самой крупной финансовой организации в мире — Visa. Как и в предыдущей части, цитаты из книги Ди Хока “One from Many: VISA and the Rise of Chaordic Organization” выделены курсивом. Важные цитаты выделены жирным шрифтом. Эти моменты мы и обсудим в 4-ой заключительной части.

              <<Хаордическая организация Visa (Часть 2)

              Когда я вышел из леса с блокнотом в кармане и кленовой тростью в руке, я уже принял решение. Оно далось мне тяжело, но было простым. Либо я говорю «нет» и отказываюсь от своей мечты, либо говорю «да» со всеми вытекающими отсюда последствиями. С тяжелым сердцем, однако понимая правильность своего решения, я вернулся домой и засел за письмо к Сэму Стюарту. У меня было два пожелания. Во-первых, мне хотелось получать жалованье, пускай достаточно скромное с учетом задачи, которую мне предстоит решить. И еще мне хотелось, чтобы это жалованье было немного выше того, какое я получал до сих пор, и чтобы оно было мне гарантировано в течение трех лет — на тот случай, если мне предложат уйти в отставку или поселиться где-нибудь по другую сторону Скалистых гор. Не требуя многого, я давал понять, что работаю не за деньги, а за идею. Я был уверен, что Сэм и члены комитета собираются предложить мне гораздо более щедрые условия. Что касается трехлетнего срока, то я знал: отлаживая новую систему, мне придется быть жестким и многие от меня отвернутся. Иными словами, я боялся, что не продержусь так долго на своей должности.

              Через месяц я встретился с Сэмом, чтобы обсудить мое письмо. Сэм много лет проработал в BofA, он был частью культуры этого банка. Амадео Джаннини, основатель Ваnk оf Аmeriса, прославился тем, что всю жизнь прожил в небольшом загородном доме и получал очень скромное жалованье. Именно этот человек установил ставки заработной платы в банке, сохранившиеся и по сей день. Никто не знает, почему Джаннини платил людям так мало: то ли чтобы снизить затраты, то ли просто из принципа. В любом случае это было несправедливо, потому что сам он, в отличие от своих сотрудников, получал огромную прибыль и имел прекрасные условия для работы. Как бы там ни было, когда в начале века штат Калифорния начал процветать, BofA стал самым богатым банком в мире, но при этом славился чудовищно низким жалованьем. Сэм выложил мне все как есть:

              — Ди, поскольку ты будешь президентом NBI и членом организационного комитета, размеры твоей зарплаты станут достоянием гласности. Такое жалованье, какое ты запрашиваешь, в банке получают всего несколько человек. Если ты будешь столько зарабатывать, мне грозят неприятности. Поэтому давай остановимся на $44 тыс. в год, которые ты будешь получать со дня регистрации NBI. Кроме того, мы готовы единовременно выплатить тебе $10 тыс. в знак признания твоих заслуг за эти полтора года и последующие несколько месяцев, пока ты будешь собирать банки воедино и запускать NBI.

              Он что, серьезно? Всего $44 тыс. в год, без всяких премий и дополнительных доходов? И это притом, что мне придется разгребать кучу в $2 млрд? Всего $10 тыс. за два года новаторской, изматывающей работы в тяжелейших условиях? Неужели у них в банке только несколько человек получают $60 тыс. в год? Но если даже и так, ведь есть еще акционерные опционы и другие бонусы и привилегии, есть, наконец, пожизненные гарантии? Но нет, Сэм не шутит. Видя, как я расстроился, он пытается смягчить удар.

              — Ди, потерпи. Много лет назад я сам долго не мог получить повышение. Это трудно, но со временем все окупится.
              — Сэм, эта ошибка тянется с самого начала. Ты обсуждал этот вопрос с другими потенциальными членами комитета?
              — Нет, они предоставили мне самому в этом разобраться. Если ты хочешь заручиться их согласием на вступление в NBI, ты должен дать ответ прямо сейчас.

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

              — Сэм, я сделаю, как ты скажешь. И все же ты не прав. Твоя ошибка бьет по моему карману, но я это переживу. Скажи членам комитета, что все в порядке, и заручись их согласием. Через неделю я представлю программу действий.

              И я уехал в Сиэтл, оставив Сэма в превосходном расположении духа. Через неделю я показал Сэму программу действий. Она ему не понравилась.

              — Ди, это невозможно. Нам не уговорить 3 тысячи банков отказаться от лицензий и вступить в NBI, а потом проводить ежегодные собрания и выбирать директоров. Все это надо провернуть за 3 месяца. Это невыполнимо.
              — Сэм, мы не узнаем, выполнимо это или нет, пока не попробуем. Мы заручились поддержкой 13 влиятельных людей. Десятки специалистов работали на этой ниве полтора года. Наша концепция достаточно убедительна. Время пришло. Сейчас самый подходящий момент! Если мы правильно построим взаимоотношения с банками, воодушевим людей, предоставим им свободу, они сотворят чудо. Я наблюдал это неоднократно. Правда, не в таких масштабах. И все же стоит попытаться. Если будем тянуть, мы все упустим. Я чувствую, что Сэм начинает сдаваться.

              Ди попросил от BoFa выделить 6-8 преданных делу людей на две недели, 10-12 опытных специалистов из отдела кредитных карт на шесть-восемь месяцев, кредит на 2 млн $. А разместиться NBI должен был в пустующем здании BofA с умеренной арендной платой.

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

              — Сэм, нет времени пробовать. Рабочие комитеты поручили мне довести дело до конца. Если хочешь, чтобы они начали действовать, решай сразу, на месте.

              Сэм смеется: он тоже может кое-что мне припомнить.
              — Хорошо, мы все сделаем. Комментировать не буду. Но не требуй, чтобы я с тобой согласился. Потому что ты не прав. Все это нельзя провернуть за три месяца. Передай своим рабочим комитетам, что я согласен, пусть берутся за дело. Через неделю у тебя будет программа нашего участия в работе.

              В тот же день я обзвонил всех членов организационного комитета и обратился к ним с дерзкой просьбой: встретиться с директорами всех региональных банков-лицензиатов и обсудить с ними содержание и основные направления нашей работы. На каждом совещании буду присутствовать я сам, а также председатели местных рабочих комитетов. Расходы должен будет оплатить банк, все это организовавший. «Очень интересно», — сказали они и согласились.

              Все сдержали свое слово. В течение десяти дней они созванивались, договаривались, и в результате было запланировано 12 совещаний, которые должны были проводиться последовательно в городах, расположенных друг от друга в двух часах лета. Через десять дней я сел в самолет и включился в бешеный график работы. Одно совещание следовало за другим. Меня засыпали вопросами, люди сомневались, загорались идеей, критиковали, путались, убеждали друг друга. Потом я снова несся в аэропорт, спал урывками — и так 12 дней подряд: 12 городов, 200 банков, сотни людей.

              Представители банков-лицензиатов получили копии официального разрешения на создание NBI, уставные документы, договоры об отказе от лицензии, о вступлении в NBI и другие рабочие материалы. Они обсуждали документы с нужными людьми, посылали свои предложения в рабочий комитет, а тот, в свою очередь, сводил их воедино и вносил изменения. В результате был создан пакет уставных документов членов — собственников NBI. Согласно одному из пунктов, документы должны были быть одобрены в течение месяца после их получения. В готовом пакете документов нельзя было изменить ни одного слова, ни одной запятой. Банки должны были либо принять документы, либо отказаться от них. Третьего было не дано. При этом после образования NBI любой банк, удовлетворяющий определенным требованиям, мог вступить в организацию в любое время.

              Каждый входящий в NBI банк должен был подписать короткий стандартный договор, подтверждающий, что все документы приняты с обязательством выполнять их «в настоящей формулировке со всеми последующими поправками и изменениями». Было утверждено минимальное число голосов, достаточных для принятия решения о немедленном вступлении в силу договоров о членстве и контрактов между NBI и BofA. Как предполагалось, если при голосовании необходимое число голосов не будет набрано, договоры не получат законной силы. В случае положительного решения будет назначен срок выборов совета управляющих и проведения первого совещания членов — собственников NBI.

              У каждого члена совета управляющих будет один голос на каждую $1 тыс. объема операций клиентов Ваnk оf Аmeriса в предыдущем году. Сервисная плата составит 0,25% от 1% объема операций. Таким образом, сервисная плата и представительство будут взаимосвязаны.

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

              Членство в организации не сможет быть передано и не будет связано с количеством выпускаемых кредитных карт и выручкой. Бизнес-портфель можно будет купить или продать, но покупать и продавать права членов—собственников организации, а также права на использование торговой марки и других аналогичных активов будет нельзя. Эти права можно будет получить лишь после вступления в организацию в соответствии с требованиями, предъявляемыми к членам NBI. Тем не менее NBI не будет закрытым клубом. Управляющие смогут определять условия приема новых членов, но не будут вправе отклонять заявления соискателей, удовлетворяющих этим условиям. Равно как и принимать в организацию банки, не отвечающие этим требованиям.

              Хотя право голоса будет зависеть от участия в программе, будет строго соблюдаться принцип «один банк — один директор (один голос)». Независимо от количества голосов, полученных пропорционально объему операций, члены совета управляющих не смогут использовать свои голоса для избрания в совет других представителей своего банка. Каждый член совета управляющих будет отвечать не перед собственным банком и теми, кто его избрал, а перед всей организацией. В процессе принятия решений на заседаниях совета управляющих каждый его член будет иметь только один голос.

              Члены совета управляющих будут иметь разные полномочия. Страна будет поделена на регионы, и каждый из них будет избирать члена совета управляющих. Правом участвовать в выборах региональных управляющих будут обладать только банки данного региона. От каждого региона на основе кумулятивной процедуры голосования будут избираться не более пяти членов совета управляющих. Один управляющий будет избираться мелкими банками. Каждый банк, доля которого в объеме операций будет превышать 15%, сможет избрать управляющего.

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

              Президент, назначаемый советом, будет его главным исполнительным директором, но не председателем совета. Председатель совета директоров, избираемый советом, не будет иметь исполнительных или оперативных полномочий. Президент станет отвечать за подготовку повестки заседания. Любой член совета сможет включать в повестку дня вопросы для обсуждения. Председатель будет вести заседания, обеспечивая возможность открытого обмена мнениями и равные права членов. Кроме того, от него будет зависеть соответствие принимаемых решений уставным целям и политике NBI, а также действующему законодательству и нормативным документам. Председатель совета управляющих сможет не разделять мнения членов совета, но не будет вправе оказывать давление на членов совета.

              Visa не могла быть куплена, не могла стать объектом поглощения или продажи, потому что владение этой организацией осуществлялось в форме пожизненного неотчуждаемого права участия. Однако бизнес каждого из участников, принадлежащий только NBI, находил свое отражение в ценах на акции и мог быть продан любому другому члену организации. Иными словами, имел место активный и весьма обширный рынок.

              Каждый член Visa получал бессрочные права — для этого ему достаточно было выпустить хотя бы одну кредитную карту Visa. Право выпускать какое угодно количество карт когда угодно и где угодно, полная свобода определения вида услуг, цен и маркетинговых условий требовали только соблюдения простейших требований, необходимых для обеспечения системы пользования кредитками.

              Несмотря на то что источником инноваций служили отдельные, часто периферийные банки, организация в целом стремительно развивалась. Если и были какие-то ошибки, банки справлялись с ними на месте. Зато успешные ходы сразу брались на вооружение и по цепочке распространялись на всю систему. Центральный аппарат мог продвигать лишь тот продукт и те услуги, которые предлагались членами Visa, а не наоборот, поэтому ошибки центра ликвидировались так же быстро, как и ошибки периферийных банков.

              Продукты под маркой Visa получали мировое признание. Хотя организация была абсолютно прозрачной для конечных потребителей, ее филиалы и даже некоторые члены NBI и представления не имели, на чем она держится и по какому принципу работает. Центр, в свою очередь, тоже не был в курсе всего происходящего и никак не мог влиять на многочисленные филиалы. Внутри Visa как единого юридического лица работало множество советов директоров, и ни один из них не был главнее другого, потому что каждый пользовался неотъемлемым правом самостоятельно решать все вопросы в своих регионах или в своей функциональной области.

              Части не знали, что представляет собой целое, а целое не знало, что представляют собой его части, потому что в этом не было необходимости. Это целостное образование, как и миллионы других хаордических образований (например, человеческий организм, наш мозг, леса, океан и биосфера), существовало само по себе, на основе самоуправления.
              Работу NBI координировали менее 500 человек, разбросанных по десяткам стран и четырем континентам.

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

              Мне не хватило ни опыта, ни характера, чтобы полностью отстоять свои убеждения, не опускаясь до компромиссов. Я пытался без изменений воплотить свои замыслы в жизнь, но так и не смог утихомирить в людях дракона с четырьмя головами — эгоизмом, завистью, алчностью и тщеславием. Я и сегодня борюсь с ним. Надеюсь, у многих это получается лучше, чем у меня.

              Начальный этап создания NBI подходил к концу. Наступил последний день ежегодного собрания членов NBI. Повестка дня была исчерпана, я чувствовал себя вконец измученным. На заключительном заседании я задал риторический вопрос:
              — Итак, все вопросы решены?
              Но тут поднялся Сэм Стюарт. Он был серьезен и даже суров. Его бас эхом разнесся по залу:
              — Есть один нерешенный вопрос.
              «О, Боже!» — подумал я. Сэм поднялся и заговорил:
              — Когда ВоfА поддержал идею создания NBI, мы были уверены, что четверть банков-лицензиатов не захочет участвовать в этом начинании. Когда Ди утверждал, что мы должны создать некую идеальную организацию, переориентировав весь бизнес кредитных карт за три месяца, я сказал ему, что это невозможно, — он сделал многозначительную паузу и с пафосом воскликнул: — Я и до сих пор так думаю!

              Зал разразился смехом. Все-таки Сэм — чудо! Только что созданный совет избрал Сэма председателем, а меня — президентом и главным исполнительным директором. Так для меня начался трехлетний период работы в организации, по истечении которого я планировал вернуться в свою тихую заводь, перебравшись обратно в Сиэтл. Если бы я знал тогда что эти три года растянутся на 14 долгих и трудных лет! Если бы я знал, я бы немедленно подал в отставку.

              Как выяснилось, ВоfА вел многомесячные переговоры с American Express, и эти две компании уже разработали план создания собственной системы авторизации кредитных карт. В то время банк American Express был самым крупным в мире эмитентом кредитных карт для оплаты путешествий и отдыха. ВоfА, в свою очередь, был самым крупным эмитентом банковских карт. В новой системе должны были участвовать и другие банки-эмитенты, прежде заплатив кругленькую сумму, которая обеспечила бы финансовые ресурсы для развития системы. При этом банки не были бы ее владельцами. План собирались обнародовать в ближайшие дни.

              Я почувствовал себя обманутым. Эта система была абсолютно чуждой духу NBI и могла серьезно навредить нам. Пока шла предварительная работа, все потенциальные банки-участники, в том числе и ВоfА, согласились, что важнейшим основанием для создания National BankAmericard Incorporated является разработка эффективной системы авторизации операций по кредитным картам. А начинание двух банковских гигантов навязывало остальным банкам роль прислуги. Я успокаивал себя тем, что вся эта история могла быть затеяна еще до переговоров о создании NBI.

              На заседании совета управляющих мы предложили, чтобы NBI объявила о создании собственной конкурентоспособной электронной системы авторизации операций, взаиморасчетов и платежей. 22 влиятельных банкира схлестнулись в жесткой дискуссии. Речь шла о том, чтобы принять архиважное решение. В случае неудачи мы рисковали репутацией, финансовой стабильностью, возможностью привлечения новых членов и освоения новых направлений бизнеса.

              На следующий день мы произвели фурор, объявив о создании собственной электронной системы авторизации карт. Мы уже прыгнули с обрыва в океан, и пути назад не было. Осталось только благополучно погрузиться в воду.

              Но упали мы, как говорится, на пузо. Это был провал. Не хватало специалистов, и мы наняли программиста со стороны. За несколько дней ему удалось склонить нас к традиционным действиям. Он предложил организовать тендер для ведущих компьютерных компаний. Поначалу это показалось вполне разумным. Но прошло несколько недель, и я забеспокоился. Наш «эксперт» уверял, что все идет хорошо, но ничего не объяснял. Что ж, оставалось только доверять его опыту.

              Наконец к нам поступило предложение от одной крупной компьютерной компании. Названная ею сумма была в несколько раз выше, а срок выполнения заказа — в два раза больше, чем ожидал совет. Ни одна из компьютерных компаний не давала никаких гарантий: они, как и наш «эксперт», полагали, что это не их проблема. Нам предстояло просить совет об увеличении бюджета и продлении сроков. Ох уж эти компьютерщики, у них всегда так! Но нас это не устраивало. Мы это уже проходили, и не раз. Как замечательно выразился Эмерсон: «Верь себе! Эта струна способна затронуть любое сердце».

              Мы собрали всех, кто был задействован в проекте, и из NBI, и со стороны. Разговор был коротким.
              — Нам сказали, что в отведенное время и в рамках принятого бюджета система не может быть создана. К тому же часть денег уже потрачена. Если мы хотим уложиться в установленные сроки и бюджет, то должны действовать сами. Подсказки со стороны мы не получили. Значит, будем искать ее в нашей компании. Подсказка — в нас самих. Либо мы просим у совета отсрочки и дополнительных ресурсов, либо полагаемся на свои силы и талант. Предлагаю устроить мозговую атаку. Мы выйдем отсюда, когда найдем ответ на вопрос: как без лишних расходов уложиться в установленное время?

              Разгорелась дискуссия. Мы искали выход из создавшегося положения. В комнате собралось достаточно людей, преданных своему делу. А вот наш «эксперт», кстати, куда-то исчез. Ну и ладно: были люди из других компьютерных компаний, и они загорелись идеей. Мы проторчали в комнате до тех пор, пока не нашли решения, устраивающего всех. Так появилась на свет экспериментальная система авторизации банковских операций (ВАSЕ 1). Это были самые волнующие месяцы в истории нашей молодой компании. Мы решили, что во главу угла следует поставить не амбиции программистов, а нужды членов NBI и держателей карт. Поэтому всю ответственность компания должна взять на себя. Мы решили стать одновременно заказчиками и исполнителями, то есть сформулировать задачу нашим программистам, координировать их работу и пользоваться ее результатами. Такой метод создания электронной системы коммуникаций противоречил всякому здравому смыслу.

              Люди быстро организовали свою работу. Доска, куда кнопками прикреплялись бумажки с хроникой каждого дня, занимала всю стену. Кто-то у кого-то стащил немытую кофейную чашку и продел через ручку веревку, натянутую через все помещение. Чашка служила бегунком, с его помощью мы отмечали наши успехи. Все задания записывались на клочках бумаги, с фамилией ответственного лица и сроками исполнения. Каждый мог делать замечания, вносить предложения, менять сроки. Подойдя к стене, каждый мог видеть, как идут дела, как его работа влияет на работу организации в целом и как она связана с работой других сотрудников. Народ собирался у доски, обсуждал текущие вопросы, спорил, сбивался в группы. Когда задание выполнялось, бумажка убиралась с доски, а кофейная чашка победоносно продвигалась вперед.

              Каждый полностью отдавал себя работе, потому что у всех был одинаковый настрой.
              Деньги немногое значили. Происходил какой-то сплошной обмен нематериальными ценностями: каждый соглашался поработать за другого, ничего не требуя взамен. У нашей компании словно была одна душа, одно сердце. Люди целиком отдавали себя делу, а вознаграждение нельзя было измерить в деньгах. Те, кто не выдерживал, уходили, а их место занимали десятки других. Никто не говорил лишних слов, никто ничего не записывал и не подсчитывал. Все чувствовали и понимали, что надо делать, и все любили свою работу.

              Вдоль стены ездила грязная кофейная чашка, которую никто так и не догадался вымыть. Еще много лет в компании рассказывали о том, как создавалась «система грязной кофейной чашки», а если точнее — ВАSЕ 1. Мы уложились в бюджет, система была создана в срок, а ее операционные возможности превысили все ожидания. Она опровергла тезис о естественной монополии, и после этого в банковской отрасли стали создаваться другие инновационные системы. ВАSЕ 1 стала тем фундаментом, на котором и была построена глобальная система коммуникаций Visa. Так провал обернулся головокружительным успехом.

              Одновременно с этим NBI вводит запрет на двойное членство. Т.е. банки участники NBI не могли вступать в другие подобные организации. MasterCharge (MasterCard), главный конкурент NBI, который в то время был гораздо крупнее NBI, заявлял о своем несогласии с нашей точкой зрения. MasterCharge не собирался вводить запрет на двойное членство.

              В доводах «за» и «против» был свой резон. Банки, изъявившие желание войти в обе системы, утверждали, что мораторий NBI на двойное членство ущемляет их свободу, лишая возможности по собственному усмотрению предлагать потребителям и торговым предприятиям кредитные карты. Но в этом случае конкуренция велась исключительно между банками. Никто не спорил с тем, что запрет на двойное членство накладывает определенные ограничения на действия банков. Однако эти ограничения были необходимы, чтобы возникли новые системы и появился стимул для конкуренции. Именно так считал я сам и многие мои сторонники.

              Запрет на участие в двух или нескольких конкурирующих системах — важный стимул к появлению других систем, которые смогли бы конкурировать между собой.
              — Если мы сейчас не приостановим двойное членство, мы останемся всего лишь с двумя системами банковских карт. Они постоянно будут пытаться ослабить конкуренцию и, возможно, постараются объединиться. И все дело закончится дебетовыми картами и другими сходными платежными системами. Здесь не нужны обоснования. Это подсказывает здравый смысл.
              Но антимонопольный отдел министерства юстиции США не поддержал Ди Хока и его единомышленников.

              Все идет к тому, что в мире укоренятся две, в крайнем случае три платежные системы, а управлять ими будут всего несколько финансовых институтов— членов этих систем. Такого развития событий можно было избежать. Это не должно было стать реальностью. В будущем все может быть еще хуже. Но так не должно быть!

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

              Комментарии (0)

                Let's block ads! (Why?)