Eu preciso escrever um gerente de sistema de notificação.
Aqui estão os meus requisitos:
Preciso enviar uma Notificação em plataformas diferentes, que podem ser totalmente diferentes (por exemplo, preciso enviar um SMS ou E-mail).
Às vezes, a notificação pode ser a mesma para todos os destinatários de uma determinada plataforma, mas às vezes pode ser uma notificação por destinatários (ou vários) por plataforma.
Cada notificação pode conter carga útil específica da plataforma (por exemplo, uma lata MMS contém um som ou uma imagem).
O sistema precisa ser escalável , preciso enviar uma quantidade muito grande de notificações sem travar o aplicativo ou o servidor.
É um processo de duas etapas, primeiro o cliente pode digitar uma mensagem e escolher uma plataforma para a qual enviar, e as notificações devem ser criadas para serem processadas em tempo real ou posteriormente.
Em seguida, o sistema precisa enviar a notificação ao provedor da plataforma.
Por enquanto, acabo com alguns itens, mas não sei quão escalável será ou se é um bom design.
Eu pensei nos seguintes objetos (em uma pseudo linguagem):
um Notification
objeto genérico :
class Notification {
String $message;
Payload $payload;
Collection<Recipient> $recipients;
}
O problema com os seguintes objetos é o que acontece se eu tiver 1.000.000 de destinatários? Mesmo se o Recipient
objeto for muito pequeno, será necessária muita memória.
Também pude criar uma notificação por destinatário, mas alguns provedores de plataforma exigem que eu a envie em lote, o que significa que preciso definir uma notificação com vários destinatários.
Cada notificação criada pode ser armazenada em um armazenamento persistente como um DB ou Redis.
Seria bom agregar isso mais tarde para garantir que seja escalável?
Na segunda etapa, preciso processar esta notificação.
Mas como distinguir a notificação do provedor de plataforma certo?
Devo usar um objeto como MMSNotification
estender um abstract Notification
? ou algo assim Notification.setType('MMS')
?
Para permitir processar muitas notificações ao mesmo tempo, acho que um sistema de filas de mensagens como o RabbitMQ pode ser a ferramenta certa. É isso?
Isso me permitiria enfileirar muitas notificações e ter vários trabalhadores para enviar notificações e processá-las. Mas e se eu precisar agrupar os destinatários como visto acima?
Então imagino que um NotificationProcessor
objeto para o qual eu poderia adicionar NotificationHandler
cada um NotificationHandler
seria responsável por conectar o provedor da plataforma e realizar a notificação.
Também posso usar um EventManager
para permitir um comportamento conectável.
Quaisquer feedbacks ou idéias?
Obrigado por dedicar seu tempo.
Nota: Estou acostumado a trabalhar em PHP e é provavelmente o idioma de minha escolha.
Editar (de acordo com a resposta de morphunreal)
- Quantas mensagens por segundo você está enviando (Defina os níveis atuais / iniciais, defina um nível máximo que o sistema deve manipular antes de ser redesenhado)
- Quais restrições de hardware o sistema possui (memória, CPU etc disponíveis para o sistema)
- Como o hardware será escalado (por exemplo, adicionando mais servidores, computação em nuvem etc.)
- Quais idiomas / sistemas gerarão notificações?
É por minha conta, sou responsável por criar a notificação programaticamente, mas construída a partir de uma interface do usuário.
- O gerador conhece os destinatários da mensagem (?) Ou são fornecidos por outros meios (por exemplo, regras de negócios para certos tipos de alerta vão para determinados destinatários)
Deve ser possível criar uma notificação para um destinatário específico, um grupo de destinatários (por exemplo, usando um sistema de tags) ou para uma plataforma inteira.
- Existem regras de negócios para adicionar recibos CC / BCC / Leitura
Sim. Observe que isso é realmente específico da plataforma e o read ou cc não está disponível em todas as plataformas.
- O gerador sabe o tipo de mensagem que está enviando (por exemplo, SMS / email) ou se baseia no destinatário
É baseado no destinatário, no entanto, como o destinatário está relacionado à plataforma e as plataformas têm uma maneira diferente de lidar com dados, é provável que a interface do usuário seja específica da plataforma para permitir a configuração de imagens, um som ou algo assim.
- O gerador exige confirmação de envio / recebimento / leitura de mensagens (envio assíncrono x envio síncrono)
Bem, o sistema deve estar propenso a erros, mas gostaríamos de lidar com o erro para definir um conjunto de regras, por exemplo, se o servidor estiver inacessível, a notificação deverá ser colocada novamente na fila para processo adicional, mas se a notificação estiver incorreta (ou tiver sido definido como está pelo provedor da plataforma), ele não deve ser colocado na fila novamente, mas notificado.
- Existem requisitos para armazenar um histórico de fontes / destinatários de mensagens (por quanto tempo?)
Sim, provavelmente queremos fazer algumas estatísticas e relatórios. * Definir pontos finais de notificação
Quais serviços estão sendo usados para enviar mensagens? Depende, alguns são webservices REST clássicos, outros são alguns protocolos exóticos, realmente depende do provedor.
Que feedback / confirmação é fornecida (sincronização / assíncrona)
Depende, alguns são síncronos e respondem com um erro, enquanto outros precisam ser extraídos posteriormente para verificar se há erros.
- É provável que adicione novos pontos finais?
Sim, na verdade, nosso aplicativo está crescendo e provavelmente queremos adicionar um novo provedor, mas é uma proporção de algo como 1 ou 2 por ano.
Respostas:
Comece separando seus requisitos funcionais e não funcionais e definindo-os cuidadosamente. É muito fácil projetar um sistema com base em requisitos ambíguos.
Por exemplo, seus requisitos não funcionais em relação à escalabilidade são bastante ambíguos. Pode aliviar muita carga mental se você colocar números reais no seu sistema. Por exemplo,
Agora que você tem isso fora do caminho, pode configurar alguns testes para garantir que o design / arquitetura dos sistemas seja capaz de atender aos seus requisitos não funcionais.
Quanto aos requisitos comerciais / funcionais do envio de notificações / mensagens, as seguintes dicas podem ajudar (se você fornecer mais informações, posso adicionar a esta resposta):
Definir fontes de notificação
Definir pontos finais de notificação
Hesito em fornecer um exemplo concreto de arquitetura, pois dependeria fortemente dos fatores envolvidos; mas geralmente os sistemas de mensagens mais simples envolvem uma fila básica, na memória / aplicativo, no-SQL, disco ou banco de dados relacional. Em seguida, um processo separado (ou vários processos separados, se distribuídos) pode pesquisar na fila seus tipos de mensagens [isto é, um trabalho cron]; e enviar conforme necessário.
Isso também pode ser aprimorado usando algumas técnicas baseadas em push (por exemplo, PostgreSQL NOTIFY / LISTEN) se houver um requisito para que as mensagens sejam enviadas imediatamente.
A vantagem de uma fila simples é que o sistema que gera a mensagem tem pouco trabalho a fazer e o sistema de processamento pode ser equilibrado com base nos requisitos de hardware / desempenho.
fonte
Você já considerou o padrão de design de peso mosca para seus objetos de notificação? Não tenho muita certeza disso, pois nunca implementei o padrão, mas lembro que isso envolve compartilhar algum estado entre os objetos flyweight. Eu também acho que os membros com mais redundância tiveram maior impacto se compartilhados. Portanto, depende se você enviar apenas algumas mensagens para muitas pessoas ou vice-versa.
fonte