init() вызывается в зависимости от используется ли package в котором находится файл с функцией init(). если создать файл в используемом package - то init() вызовется, если создать новый верхнеуровневый package, который нигде не используется - он не будет вызван.
Правильная мысля приходит опосля: 1. в базовом клиенте к RESTful сервису есть мьютекс, который на самом деле не нужен, так как есть встроенный scheduler в Golang. 2. Все функции init() во всех файлах, всех пакетов которые используются, точно вызовутся до вызова main() (спасибо дружественному чатику Go-Go!, ссылка в описании)
1. А если мютекс оставить, то все запросы в один сервис последовательно выполнялись бы? Какая идея у вас была при его добавлении, защититься от изменения состояния http клиента двумя параллельными запросами? Спасибо
xoroshoye video pocherknul dlya seba momenti no yest nyuans structuri ispuzuyetsa bez pointerov eta privodit k kopirivaniyu structuri v parametrax + v retrurnax
Если микрофон стерео, то лучше выравнивать как-то каналы по звуку, потому что в наушниках неприятно слушать, постоянно громкость перетекает между ушами.
Добрый день, спасибо за видео! Очень круто! Есть пару вопросов: 1. По поводу микросервисов в целом: Такой кейс, наши заметки взлетели и мы хотим их монетезировать. Схема такая: пользователь покупает уровень подписаки "Базовая", "Профи". Базовая позволяет создать 10 записок, профи - безлим. Как правильно делать запрос? Из микросервиса записок через гейтвей получать информацию о пользователе и проверять уже может ли он создавать новые записи? А если у нас большая система, и нам надо проверить юзера, оплату, какое-нибуть наличие, и тд, в итоге от 1 микросервиса будет делать запрос на 10 разных, собирать ответ и готовить инфу? Или в таком кейсе мы понимаем что не правильно разбили наши приложение? 2. По поводу рефреш токена. Если угоняют, то угоняют куку, где есть рефреш токен, т.е. доступ будет не на 1 час, а пока владелец не перелогинится и не перезапишет ревреш токен. Но и в таком случае у нас проблема с разными девайсами\мобилками и тд, т.к. логинясь на новом устройстве мы будем разлогинивать на других (т.кк. будет перезаписываться рефреш токен)
1. На фронте лочим методы в зависимости от подписки (не даем создать больше 10 подписок). На беке в нужных местах делаем проверки (при создании новой заметки - проверяем количество заметок пользователь я его подписку (это в отдельном сервисе)) 2. тут вопрос где хранить рефреш токен, можно ведь не в куках его хранить а в local storage.
Мне показалось что чуть замудрено у вас. GIN вроде норм (роутер). Можете показать как разбить например данное приложение на микросервисы - было бы полезно тоже.
Зачем держать в кеше refresh_token? При рестарте в течение часа 100% пользователей разлогинит. Его же точно так же можно сгенерить как jwt и не хранить вообще ничего
Если не ошибаюсь микро сервисы это когда поднимается несколько серверов на разных портах, и каждый сервер отвечает за одну какую-то деятельность. А в видео это уже просто разные пакеты. Поправьте если ошибаюсь ...
Из пользовательских данных я формирую DTO (там же должна быть валидация этих данных), далее DTO отдаю в слой бизнес логики, где я уже с этим DTO делаю то что мне нужно и по итогу создаю модель данных, которую уже отдаю в слой DAO/Repository и работаю с БД.
@@TheArtofDevelopment валидация dto не помеха (пакет подрубить, да теги прописать). Я не понял зачем структуру в мапу перегонять, а потом в json чтоб получить байты. Почему сразу не маршалить?
@@TheArtofDevelopment кажется вспомнил, я тоже подобным занимался, когда проксю api'шки делал - анмаршалил риквест в структуру, потом валидировал, но не нашел пакет structs и вручную refelct'ом собирал мапу, чтоб засунуть в другой риквест и передать серверу. Но мне это надоело, поэтому вынес эту логику в методы)) Потом мне это снова надоело и сделал обёртку - структуру с полем, содержащим сырые данные и методом, возвращающим модель.
я тоже не понял смысл маневра. к сожалению, даже после прочтения ветки и попытки переварить информацию понимания не прибавилось. почему нельзя к примеру просто выполнить dataBytes, err := json.Marshal(dto)?
@@TheArtofDevelopment init() вызывается до main(), а по поводу условий прав. The init function ¶ Finally, each source file can define its own niladic init function to set up whatever state is required. (Actually each file can have multiple init functions.) And finally means finally: init is called after all the variable declarations in the package have evaluated their initializers, and those are evaluated only after all the imported packages have been initialized. Besides initializations that cannot be expressed as declarations, a common use of init functions is to verify or repair correctness of the program state before real execution begins.
Спасибо за такое полезное разъяснение. Есть, что почерпнуть. Кроме того, у меня возник ряд вопросов и я бы с удовольствием подискутировал на их счёт. 1. Почему выбрана (на первый взгляд) такая сложная система проксирования запросов? Если я правильно понял, этот сервис является гейтвеем для всех остальных частей приложения. Не понимаю, почему нам надо дублировать все действия/эндпоинты и их сигнатуры(по большому счёту). Не будет ли проще сделать такую систему, которая будет просто полноценно прокидывать запрос дальше на нужный сервис в зависимости от урла. Например, можно сделать урл example.com/api/mcs// и даже не заморачиваться о каких-то валидациях или обработках ошибок, сам целевой сервис это сделает. Но при этом гейтвей мог бы взять на себя проверку токена и прокидывания пользователя в целевой сервис. 2. Говоря об аутентификации пользователя. Вероятно, я что-то упустил, но не очень понял, почему регистрацией и авторизацией пользователя занимается гейтвей. Понимаю, что он точно должен проверять токен и отшивает запрос, если всё плохо. Но почему он вообще знает про логику авторизации (не считая миддлвары для токенов). По большому счёту сейчас понял, что второй вопрос непосредственно связан с первым. Не будет ли проще сделать публичный доступ к каким-то эндпоинтам user service и просто так же прокидывать все запросы дальше, нежели делать пересборку всего запроса перед обращением в целевой сервис? Да, это выглядит логичным при допущении, что user service должен бы рулить регистрацией/аутентификацией пользователя. Это бы в какой-то степени решило вопросы модулярности. Сам гейтвей знал бы только урлы сервисов, к которым ему нужно было бы обратиться, знал бы, что для публичных запросов не нужны данные пользователя из токена, а для приватных - надо чекать токен и прокидывать данные из него. Например: example.com/api/mcs//access/:(public|private)/ if access == 'private' parseToken(), ну ты понял. Более того, обработка ошибок тоже в каком-то смысле упрощается, их вообще не надо обрабатывать на стороне гейтвея, клиенту можно сообщать результат обработки ошибок целевого сервиса. Ну и конечно же, не надо будет на каждый чих по расширению целевого сервиса расширять и гейтвей. Микросервисы же про распределение работы по командам. Да и связность меж сервисами лучше уменьшить. Значит, добавление новой ручки в любой из целевых сервисов не должно приводить к дополнительной работе в гейтвее. Или я в целом не прав в подходе? Вопросы подняты только с целью развития. Спасибо тебе и твоим трудам, что эти вопросы вообще появились. Было бы классно заобщаться с целью поиска "правды". =)
с удовольствием отвечу на все вопросы, заходите в телеграмм группу (ссылка в описании), копируйте все вопросы - там удобней будет общаться. если коротко: 1. на будущее (обвязка вокруг проксирования) 2. в api сервисе нет логике, где вы ее нашли?
Работа с Golang, все подробно, детально и пошагово, отличный обзор, их очень мало...
Спасибо за фидбек!
Продолжай снимать по Golang, в интернете мало емких и подробных разборов по шагам.
Благодарю!
Спасибо за фидбек. Будем!
Полный разбор микросервиса мне качественно помог, и мне стоит продолжить эфективно работать
Спасибо за фидбек!
Было интересно посмотреть на разбор микросервиса спасибо за информацию автору канала лайк и респект.
Спасибо за фидбек!
Артур, спасибо, такой формат видео очень понравился! И суть, и детальный разбор. Спасибо за работу!
Спасибо за фидбек и поддержку!
Хорошо, что на примере реального проекта. Так более доступно.
Спасибо за фидбек!
Круто, спасибо!! Получилось очень живо и познавательно.init() вызывается при импорте, насколько я помню ))
init() вызывается в зависимости от используется ли package в котором находится файл с функцией init(). если создать файл в используемом package - то init() вызовется, если создать новый верхнеуровневый package, который нигде не используется - он не будет вызван.
Правильная мысля приходит опосля:
1. в базовом клиенте к RESTful сервису есть мьютекс, который на самом деле не нужен, так как есть встроенный scheduler в Golang.
2. Все функции init() во всех файлах, всех пакетов которые используются, точно вызовутся до вызова main() (спасибо дружественному чатику Go-Go!, ссылка в описании)
1. А если мютекс оставить, то все запросы в один сервис последовательно выполнялись бы? Какая идея у вас была при его добавлении, защититься от изменения состояния http клиента двумя параллельными запросами? Спасибо
Практика хороша, но теории надо знать побольше!) Мне))
Спасибо за фидбек!
xoroshoye video pocherknul dlya seba momenti no yest nyuans structuri ispuzuyetsa bez pointerov eta privodit k kopirivaniyu structuri v parametrax + v retrurnax
Факт, что init вызовется до main. Более того все init функции во всех транзитивных пакетах будут вызваны до начала исполнения программы.
Огонь спасибо
Главное теперь не останавливаться на достигнутых результатах, думаю эти наработки позволят сделать проект очень популярным.
Спасибо за фидбек!
Если микрофон стерео, то лучше выравнивать как-то каналы по звуку, потому что в наушниках неприятно слушать, постоянно громкость перетекает между ушами.
Исправлю в следующих видео! Спасибо за фидбек!
Замечательно разрабатываете !!!
Спасибо за фидбек!
Добрый день, спасибо за видео! Очень круто! Есть пару вопросов:
1. По поводу микросервисов в целом:
Такой кейс, наши заметки взлетели и мы хотим их монетезировать. Схема такая: пользователь покупает уровень подписаки "Базовая", "Профи". Базовая позволяет создать 10 записок, профи - безлим. Как правильно делать запрос? Из микросервиса записок через гейтвей получать информацию о пользователе и проверять уже может ли он создавать новые записи? А если у нас большая система, и нам надо проверить юзера, оплату, какое-нибуть наличие, и тд, в итоге от 1 микросервиса будет делать запрос на 10 разных, собирать ответ и готовить инфу? Или в таком кейсе мы понимаем что не правильно разбили наши приложение?
2. По поводу рефреш токена. Если угоняют, то угоняют куку, где есть рефреш токен, т.е. доступ будет не на 1 час, а пока владелец не перелогинится и не перезапишет ревреш токен. Но и в таком случае у нас проблема с разными девайсами\мобилками и тд, т.к. логинясь на новом устройстве мы будем разлогинивать на других (т.кк. будет перезаписываться рефреш токен)
1. На фронте лочим методы в зависимости от подписки (не даем создать больше 10 подписок).
На беке в нужных местах делаем проверки (при создании новой заметки - проверяем количество заметок пользователь я его подписку (это в отдельном сервисе))
2. тут вопрос где хранить рефреш токен, можно ведь не в куках его хранить а в local storage.
Мне показалось что чуть замудрено у вас. GIN вроде норм (роутер).
Можете показать как разбить например данное приложение на микросервисы - было бы полезно тоже.
GIN отличный, только это не роутер, а целый фреймворк.
Так это и есть микросервис, его уже не надо разбивать.
@@TheArtofDevelopment показали бы как разбивать на микросервисы что нибудь ... c бд, докером
Пионерский код. Логер без закрытия в defer c потерей данных логирования
а систему прав юникса стоило бы подучить
top
Зачем держать в кеше refresh_token? При рестарте в течение часа 100% пользователей разлогинит. Его же точно так же можно сгенерить как jwt и не хранить вообще ничего
Да, так сделать можно.
Все не очень понятно по первой но уверен дальше будет проще.
Спасибо за фидбек! Подписывайтесь и будет проще!
Если не ошибаюсь микро сервисы это когда поднимается несколько серверов на разных портах, и каждый сервер отвечает за одну какую-то деятельность. А в видео это уже просто разные пакеты. Поправьте если ошибаюсь ...
В видео разбор одного микросервиса, который проксирует запросы в другие сервисы
Благодарю за пояснение 👍
Если бы сейчас была необходимость сделать такой сервис с нуля, что бы вы изменили?
Не понял смысл маневра: struct (dto) -> map -> json -> []byte
Почему сразу dto не замаршалить? easyjson, например, если быстро надо.
Из пользовательских данных я формирую DTO (там же должна быть валидация этих данных), далее DTO отдаю в слой бизнес логики, где я уже с этим DTO делаю то что мне нужно и по итогу создаю модель данных, которую уже отдаю в слой DAO/Repository и работаю с БД.
@@TheArtofDevelopment валидация dto не помеха (пакет подрубить, да теги прописать). Я не понял зачем структуру в мапу перегонять, а потом в json чтоб получить байты. Почему сразу не маршалить?
@@TheArtofDevelopment кажется вспомнил, я тоже подобным занимался, когда проксю api'шки делал - анмаршалил риквест в структуру, потом валидировал, но не нашел пакет structs и вручную refelct'ом собирал мапу, чтоб засунуть в другой риквест и передать серверу. Но мне это надоело, поэтому вынес эту логику в методы))
Потом мне это снова надоело и сделал обёртку - структуру с полем, содержащим сырые данные и методом, возвращающим модель.
я тоже не понял смысл маневра. к сожалению, даже после прочтения ветки и попытки переварить информацию понимания не прибавилось.
почему нельзя к примеру просто выполнить dataBytes, err := json.Marshal(dto)?
@@user-kk1ic4eu8qо не ни в коем случае
Клиенты хранятся в pkg
да, но в тот момент казалось что клиент к моему же сервису должен храниться в internal...
APIGateway может запускать серверы как это сделано в Roadrunner? что бы он отвечал за их работоспособность если упадет поднимет заново
Roadrunner запускать их n и балансирует при этом еще
нет. такой функционал лучше предоставить куберу, номаду и иже с ними
@@TheArtofDevelopment спс кубер еще не учил Докере только и работаю.
docker --restart= "XXXX" и поток кубером размножить.
Привет! Какой у тебя уровень? Senior?
не берусь называть свой уровень
А що там вище?
Бо сеньйорів тьма тьмуща
Странный обзор. В документации явно написано, что init() пакетов вызывается после импорта пакета, т.е. до функции main и тем более getLogger
а вот и не до функции main и при некоторых условиях, который я выявил пока эксперементировал
@@TheArtofDevelopment init() вызывается до main(), а по поводу условий прав.
The init function ¶
Finally, each source file can define its own niladic init function to set up whatever state is required. (Actually each file can have multiple init functions.) And finally means finally: init is called after all the variable declarations in the package have evaluated their initializers, and those are evaluated only after all the imported packages have been initialized.
Besides initializations that cannot be expressed as declarations, a common use of init functions is to verify or repair correctness of the program state before real execution begins.
музыка невыносима ....
миссия невыполнима
Бес попутал 🤣
Как именно? )
@@TheArtofDevelopment эт тебя спросить надо, твоя реплика ближе к концу где-то)
бывает =)
Спасибо за такое полезное разъяснение. Есть, что почерпнуть.
Кроме того, у меня возник ряд вопросов и я бы с удовольствием подискутировал на их счёт.
1. Почему выбрана (на первый взгляд) такая сложная система проксирования запросов?
Если я правильно понял, этот сервис является гейтвеем для всех остальных частей приложения. Не понимаю, почему нам надо дублировать все действия/эндпоинты и их сигнатуры(по большому счёту). Не будет ли проще сделать такую систему, которая будет просто полноценно прокидывать запрос дальше на нужный сервис в зависимости от урла. Например, можно сделать урл example.com/api/mcs// и даже не заморачиваться о каких-то валидациях или обработках ошибок, сам целевой сервис это сделает. Но при этом гейтвей мог бы взять на себя проверку токена и прокидывания пользователя в целевой сервис.
2. Говоря об аутентификации пользователя.
Вероятно, я что-то упустил, но не очень понял, почему регистрацией и авторизацией пользователя занимается гейтвей. Понимаю, что он точно должен проверять токен и отшивает запрос, если всё плохо. Но почему он вообще знает про логику авторизации (не считая миддлвары для токенов).
По большому счёту сейчас понял, что второй вопрос непосредственно связан с первым.
Не будет ли проще сделать публичный доступ к каким-то эндпоинтам user service и просто так же прокидывать все запросы дальше, нежели делать пересборку всего запроса перед обращением в целевой сервис?
Да, это выглядит логичным при допущении, что user service должен бы рулить регистрацией/аутентификацией пользователя.
Это бы в какой-то степени решило вопросы модулярности. Сам гейтвей знал бы только урлы сервисов, к которым ему нужно было бы обратиться, знал бы, что для публичных запросов не нужны данные пользователя из токена, а для приватных - надо чекать токен и прокидывать данные из него.
Например: example.com/api/mcs//access/:(public|private)/
if access == 'private' parseToken(), ну ты понял.
Более того, обработка ошибок тоже в каком-то смысле упрощается, их вообще не надо обрабатывать на стороне гейтвея, клиенту можно сообщать результат обработки ошибок целевого сервиса.
Ну и конечно же, не надо будет на каждый чих по расширению целевого сервиса расширять и гейтвей. Микросервисы же про распределение работы по командам. Да и связность меж сервисами лучше уменьшить. Значит, добавление новой ручки в любой из целевых сервисов не должно приводить к дополнительной работе в гейтвее.
Или я в целом не прав в подходе?
Вопросы подняты только с целью развития. Спасибо тебе и твоим трудам, что эти вопросы вообще появились.
Было бы классно заобщаться с целью поиска "правды". =)
с удовольствием отвечу на все вопросы, заходите в телеграмм группу (ссылка в описании), копируйте все вопросы - там удобней будет общаться.
если коротко:
1. на будущее (обвязка вокруг проксирования)
2. в api сервисе нет логике, где вы ее нашли?