• Как разбить транзакцию по микросервисам сохранив консистентность данных?

    @stratosmi
    1) Это некорректное разбиение на микросервисы, вообще-то. Так как приводит к серьезной проблеме с производительностью. И то, ради чего на микросервисы разбивали - горизонтальное масштабирование - получается и что бесполезно.

    2) Если всё же вы решили забить на предупреждение из пункта 1), то - одно из решений - решается двухфазной транзакцией https://docs.microsoft.com/ru-ru/dotnet/framework/...
    Ответ написан
    Комментировать
  • Как разбить транзакцию по микросервисам сохранив консистентность данных?

    angrySCV
    @angrySCV
    machine learning, programming, startuping
    то что вы описали называется двухФазным комитом, раньше очень часто использовался.
    сейчас активнее используют похожий но немного другой подход, тоже связанный с тем что резервируют определенные ресурсы (например деньги на счету, и товар на складе) потом проверяют промежуточный статус операции, и потом проводят и подтверждают операцию - разница в том что ничего не перезаписывается а непрерывно все запросы логируется, и любые откаты операции идут через добавление новых записей-запросов в лог (он же и очередь сообщений)
    ----
    там много тонкостей, например вы говорили про время-метки, в целом метки времени добавляют - если нужно контролировать очередность промежуточных шагов (но обычно это не так важно, поэтому метку времени не всегда добавляют), но добавляют уникальный айди операции, тк в случае сбоя запроса (при например длительном ожидания ответа), может произойти "переотправка" запроса, и нам эта метка с уникальным айди позволяет не дублировать одну и туже операцию.
    =====
    есть тонкости например с тем, каким образом разделены эти микросервисы, может это просто дублирование одного и того же сервиса но например каждый из них обрабатывает запросы от разных сегментов пользователей, поэтому не требуется согласовывать какие-то операции между этими микросервисами.
    ====
    на мой взгляд - это вобще разводные вопросы не имеющие правильного ответа, схемы подбираются конкретно под проект и задачи, тем более если вы не разрабатывали какую-нибудь платежную систему, типа яндекс.денег то вообще бесполезно что-то обсуждать.
    это не камень в ваш огород, этим вообще обычно мало кто реально занимается, уверен те кто у вас это спрашивал сами мало что в этом понимают, а спрашивают такие вещи чтоб вас слить.
    Ответ написан
    3 комментария
  • Вывод видеопотока в интернет

    KiLEX
    @KiLEX
    Добрый вечер!
    Я делаю вот так с одной камеры.
    /usr/bin/cvlc -d --loop --repeat rtsp://*.*.*.*/mpeg4/media.amp --http-reconnect --no-sout-audio --sout '#transcode{vcodec=FLV1,vb=4096,fps=30,sfilter=logo}:std{access=http{mime=video/x-flv},dst=*.*.*.*:8080/live.flv,mux=ffmpeg{mux=flv}}'
    Ответ написан
    5 комментариев
  • Как настроить OpenVPN клиент на Mikrotik?

    Вот ссылка на настройку опенвпн на микротике, из неподдерживаемого:
    UDP,
    LZO,
    TLS,
    Auth without login/pass

    У меня клиент опенвпн на mikrotik настроен через сертификат и работает без проблем 2 года.
    Ниже мой конфиг:

    ovpn client config
    client
    proto tcp-client
    dev tun
    ca <...>.crt
    cert <...>.crt
    key <...>.key
    remote xxx.xxx.xxx.xxx 1194
    cipher AES-256-CFB
    verb 2
    mute 20
    keepalive 10 120
    persist-key
    persist-tun
    float
    resolv-retry infinite
    nobind
    Ответ написан
    Комментировать
  • Зачем нужна jwt стратегия?

    devellopah
    @devellopah
    Справка(упрощённо).
    Аутентификация - вход в систему.
    Авторизация - получение доступа к инфе из базы данных.

    Если ты создаёшь сессию для пользователей своего приложения, то когда юзер залогинился на сервере инициируется сессия и сервер в куках отправляет на клиент session id.
    В последующих запросах к базе данных сервер читает этот session id из кук, обращается к некой внутренней базе ( обычно имеет форму ключ-значение, где ключ - это session id, значение - mail пользователя, к примеру ) затем обращается к базе данных, достаёт данных для пользователя ( мы определили его на предыдущем шаге ) и возвращается в response.
    Такая система называется stateful ( поскольку мы вынуждены хранить инфу об аутентифицированных пользователях на сервере ). Это не вяжется с концепцией RESTful API, подразумевающей, что сервер должен быть stateless ( не хранить инфу аутентифицированных пользователях ).
    Добиться этого помогает json web token, поскольку он хранит всю необходимую для авторизации пользователя инфу. Это позволяет тебе написать RESTful API(stateless)

    Что почитать: session-based authentication, token-based authentication
    Ответ написан
    Комментировать
  • Хотите задать вопрос администрации Тостера?

    На счет уведомлений. При подписке на какой-либо вопрос/при комментарий на ваш ответ/при ответе на ваш вопрос и т.д. появляются уведомления. И они очень полезны. Так вот, при переходе по какому-либо уведомлению, остальные, относящиеся к тому же ответу/вопросу и т.д., остаются активными, что очень раздражает. Нужно потыкать на каждое из уведомлений, чтобы они отметились прочитанными. Либо же переходить на страницу со всеми уведомлениями, что тоже не особо удобно, и там отмечать "Прочитать всё". Но тогда отмечаются прочитанными вообще все, что логично, а не только те, которые относятся к конкретному ответу/вопросу и т.д. Возможно ли это исправить? Спасибо.
    Ответ написан
    Комментировать
  • Какой примерно код должен быть в скрипте для NodeJS для выполнения серверного рендеринкга SPA на React?

    Anubis
    @Anubis
    Люблю корейскую кухню и веб-разработку
    https://redux.js.org/docs/recipes/ServerRendering.html
    Я по этому гайду смог достичь желаемого функционала. Вместо Express заюзал более современный Koa. Суть в том, чтобы при обращении к нужной к рендерингу страницы, (если нужно, асинхронно) заполучить некие данные, выстроить на их основе первоначальное состояние store, выполнить renderToString из 'react-dom/server', полученный html внедрить в основной html, также внедрить в основной html состояние стора после рендеринга (см. window.__PRELOADED_STATE__ по ссылке) и выдать итоговый ответ в браузер. Далее на клиенте заюзать createStore, используя содержимое переменной стора, полученной от сервака, и юзать не ReactDOM.render, а ReactDOM.hydrate.
    Ответ написан
    Комментировать
  • SPA и REST API - как грамотно построить аутентификацию?

    liveunit
    @liveunit
    Думаю jwt аутентефикации хватит с головой.
    Вот тут написано хорошо обо всех токенах и как они работают.
    https://auth0.com/blog/refresh-tokens-what-are-the...
    Ответ написан
    2 комментария
  • Как заменить switch case паттерном стратегия?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Switch
    public enum DamageType { Melee, Range, Magic }
    public class Monster
    {
        public double Health { get; private set; }
        public double MeleeDamage { get; private set; }
        public double RangeDamage { get; private set; }
        public double MagicDamage { get; private set; }
        public DamageType FavoriteDamageType { get; private set; }
    
        public Monster(double health, double meleeDamage, double rangeDamage, double magicDamage, DamageType favoriteDamageType)
        {
            Health = health;
            MeleeDamage = meleeDamage;
            RangeDamage = rangeDamage;
            MagicDamage = magicDamage;
            FavoriteDamageType = favoriteDamageType;
        }
    
        public void AttackTo(Monster monster, DamageType damageType)
        {
            switch (damageType) // используется switch
            {
                case MonsterType.Melee: monster.Health -= MeleeDamage; break;
                case MonsterType.Range: monster.Health -= RangeDamage; break;
                case MonsterType.Magic: monster.Health -= MagicDamage; break;
            }
        }
    
        public void AttackTo(Monster monster)
        {
            AttackTo(monster, FavoriteDamageType);
        }
    }


    То же самое, но со стратегией
    public class Monster
    {
        public double Health { get; set; }
        public double MeleeDamage { get; private set; }
        public double RangeDamage { get; private set; }
        public double MagicDamage { get; private set; }
        public IDamageStrategy FavoriteDamageStrategy { get; private set; }
    
        public Monster(double health, double meleeDamage, double rangeDamage, double magicDamage, IDamageStrategy favoriteDamageStrategy)
        {
            Health = health;
            MeleeDamage = meleeDamage;
            RangeDamage = rangeDamage;
            MagicDamage = magicDamage;
            FavoriteDamageStrategy = favoriteDamageStrategy;
        }
    
        public void AttackTo(Monster monster, IDamageStrategy damageStrategy)
        {
            damageStrategy.Attack(this, monster); // не используется switch
        }
    
        public void AttackTo(Monster monster)
        {
            AttackTo(monster, FavoriteDamageStrategy);
        }
    }
    
    
    public interface IDamageStrategy
    {
        void Attack(Monster attacker, Monster defender);
    }
    public class MeleeDamageStrategy : IDamageStrategy 
    {
        public void Attack(Monster attacker, Monster defender)
        {
            defender.Health -= attacker.MeleeDamage;
        }
    }
    public class RangeDamageStrategy : IDamageStrategy 
    {
        public void Attack(Monster attacker, Monster defender)
        {
            defender.Health -= attacker.RangeDamage;
        }
    }
    public class MagicDamageStrategy : IDamageStrategy 
    {
        public void Attack(Monster attacker, Monster defender)
        {
            defender.Health -= attacker.MagicDamage;
        }
    }

    Отличие класса Monster только в коде первого метода AttackTo. Ну и свойства FavoriteDamageType или FavoriteDamageStrategy.

    Стратегия может быть полезна, если код атаки, в зависимости от типа, сильно отличается, используя внешние данные (не из класса монстра), например, день или ночь, ясно/дождь и пр. Использование стратегии переносит часть кода из класса монстра (и так сложного класса) в несколько простых классов.
    Ответ написан
    1 комментарий
  • Откуда берётся событие update:foo?

    Это название события, можно хоть updateBaz, хоть helloWorld его обозвать.

    А что до двоеточия, это вроде namespace'а. Vue в данном случаем сам генерирует название события.

    Согласно документации

    <comp :foo.sync="bar" :baz.sync="xyz"></comp>

    будет преобразовано в

    <comp :foo="bar" @update:foo="val => bar = val" :baz="xyz" @update:baz="val => xyz = val"></comp>


    И т.д.
    Ответ написан
    2 комментария
  • 4 вариации метода Main в с#?

    C# 7.1
    public static void Main();
    public static int Main();
    public static void Main(string[] args);
    public static int Main(string[] args);
    public static Task Main();
    public static Task<int> Main();
    public static Task Main(string[] args);
    public static Task<int> Main(string[] args);
    Ответ написан
    Комментировать
  • Сервис голосования с защитой от накруток?

    webinar
    @webinar Куратор тега Веб-разработка
    Учим yii: https://youtu.be/-WRMlGHLgRg
    На любую защиту, есть ее обход. Самый простой способ обхода и сложный для его закрытия - это сервисы типа www.wmmail.ru . Платишь копейки и получаешь десятки тысяч голосов от реальных людей с разными ip, браузерами и т.д. Так как это, реальные люди.
    Так что прежде чем думать о какой-то защите, придется найти их все и мониторить там задачи на наличие ссылки на Ваш ресурс. Но многие делаю заказ так, что бы ссылка была на другом сайте, а на него ссылка из задачи. Так что это адски невозможно.
    Разве что сделать голосование мега сложным (введите паспортные данные и т.д.), но тогда и реальные люди нихрена не будут участвовать.
    Другой вариант если голосов ожидается оооочень много, больше, чем людей в таких системах, тогда шанс есть.

    Вывод, 100% защиты нет, сделайте элементарно заглушку, что бы с одного ip нельзя было голосовать n раз в x минут + рекапча. Это просто и достаточно от простого робота. Остальное все равно не победить.

    ПС: Русские хакеры президента в США выбрали, что тут говорить теперь )))
    Ответ написан
    4 комментария
  • Не работает функция !important?

    @Nazi
    Ответ написан
    Комментировать
  • Почему jquery не подключается?

    kulakoff
    @kulakoff Куратор тега Vue.js
    Vue.js developing
    Подключайте через webpack типа вот такого:
    new webpack.ProvidePlugin({
        $: "jquery",
        jQuery: "jquery",
        "window.jQuery": "jquery"
    })
    Ответ написан
    4 комментария
  • Vue как указать динамическое свойство?

    vicodin
    @vicodin
    Имею некоторый опыт
    Читайте официальную документацию, она изумительно хорошо написана.

    https://vuejs.org/v2/guide/computed.html

    var vm = new Vue({
      el: '#example',
      data: {
        message: 'Hello'
      },
      computed: {
        // a computed getter
        reversedMessage: function () {
          // `this` points to the vm instance
          return this.message.split('').reverse().join('')
        }
      }
    })
    Ответ написан
    Комментировать
  • Можете объяснить пару строк кода?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    С первой строкой Вы разобрались правильно

    Во второй строке используется метод массива reduce, предназначенный для свертки массива
    Этот метод принимает 2 аргумента, функцию и инициализирующее значение, притом 2й аргумент не обязателен, если он отсутствует, то в качестве инициализирующего значения будет взят 0й элемент массива, а массив будет обрабатываться начиная с элемента с индексом 1.
    Важно! для пустого массива метод reduce просто вернет инициализирующее значение, а если оно опущено - выкинет ошибку. Но здесь это не критично, так как метод строки split никогда не вернет пустой массив, а метод массива map всегда вернет массив той же размерности, что и исходный.
    Функция переданная первым аргументом будет вызываться для каждого элемента массива, в нее передается 4 аргумента (в Вашем примере 2 последних опущены за ненадобностью):
    1. Результат предыдущего вычисления (или инициализирующее значение для первого вызова)
    2. Текущий элемент массива
    3. Индекс текущего элемента
    4. Исходный массив
    Функция должна вернуть результат вычисления для текущего элемента, последний результат будет возвращен методом reduce

    В третьей строке используется тернарный оператор, формат которого:
    <условие> ? <результат при истине условия> : <результат при лжи>
    То есть, если sum > 1 - в target запишем 0, иначе 1

    Метод массива indexOf производит поиск в массиве по точному совпадению (проверяет оператором ===) с переданным аргументом и возвращает индекс первого найденного элемента или -1 если ничего не нашел

    P.S. я бы решил так:
    function iqTest(numbers) {
      return numbers
        .split(' ')
        .map((v, i) => ({v: v % 2, i: i + 1}))
        .find(({v}, i, arr) => i !== 0 && v !== arr[i - 1].v)
        .i;
    }
    Ответ написан
    3 комментария
  • Наклейки на ноутбук

    michaelkl
    @michaelkl
    Ответ написан
    Комментировать
  • Одновременные запросы в nodejs?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    на 8 гигах оперативы и 4 ядрах по 3.6ггц кластер из 4х процессов ноды спокойно обрабатывает порядка 20-30тыс полноценных (с обращением к редису и бд) запросов в секунду.
    Надо смотреть Ваш код, что-то вы делаете не так
    Ответ написан
  • Чем отличаются директивы root и alias в nginx "на пальцах"?

    @inkvizitor68sl
    Linux-сисадмин с 8 летним стажем.
    Не совсем.
    Делают они одно и то же только для location /.

    Если у вас, например, location /img, то при
    root /var/www ссылка /img/1,jpg будет вести в файл /var/www/img/1.jpg

    а при alias /var/www та же ссылка будет вести в /var/www/1.jpg.
    Ответ написан
    2 комментария