V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
phpdever
V2EX  ›  问与答

[请教] 微服务模式下,如何校验用户是否为新用户?

  •  
  •   phpdever · 2021-07-02 09:42:09 +08:00 · 1868 次点击
    这是一个创建于 1239 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题描述

    A 服务负责提供营销活动功能,某个活动仅允许新用户参加,那么 A 服务如何校验授权进来的用户是新用户呢?授权是由 B 服务提供,B 服务的授权逻辑是:如果该用户已注册,则直接登录成功,否则创建该用户。

    由于授权登录操作是在 B 服务完成的,到了 A 服务之后并没有办法知道这个用户是新用户还是旧用户,如果是单体应用反而好解决,我只要在 A 服务查询一下 user 表即可。

    新用户定义

    用户首次注册

    我能想到的解决方法

    • 加入时间维度,在 A 服务校验,如果是当天注册的则为新用户?
    • B 服务授权登录之后抛一个事件出来? A 服务接收?但这中间似乎会有时间差
    • B 服务授权登录之后,将新用户丢到一个池子里面? A 服务去取?
    hotcool100
        1
    hotcool100  
       2021-07-02 09:47:22 +08:00
    微服务内部有 RPC 调用啊
    phpdever
        2
    phpdever  
    OP
       2021-07-02 09:49:13 +08:00
    @hotcool100 是有 RPC 调用的,但问题就在于,用户参加活动的时候,前端会先去调用 B 服务的登录接口,如果是个新用户,它那边就自动创建了,然后前端再来调 A 服务的活动参加接口 (校验是否为新用户),那么这个时候用户已经创建了,就不好校验了
    timethinker
        3
    timethinker  
       2021-07-02 09:51:45 +08:00   ❤️ 1
    要确定这个“是否为新用户”是如何定义的,比如 3 天以内注册的都是新用户?活动推出以后注册的玩家才算是新用户?又或者是在某一个渠道条件下引入注册(创建)的用户才算是新用户?

    不同的需求有不同的做法。
    tabris17
        4
    tabris17  
       2021-07-02 09:54:13 +08:00
    那你要改接口,B 服务应该返回用户是否是新创建的信息
    johnsona
        5
    johnsona  
       2021-07-02 09:57:39 +08:00 via iPhone   ❤️ 1
    @phpdever 所以你这个新用户要怎么定义?假如参加活动的时候 不去创建 那叫新用户吗?这时候这个用户在你们系统都不存在

    以套路云为例,你注册了你就就是新用户 你参加过一次优惠活动 我就把你变成老用户
    frandy
        6
    frandy  
       2021-07-02 09:58:04 +08:00   ❤️ 1
    3 楼说得对,需要具体区分怎么定义新的用户.
    如果是没有参与营销活动的都算新用户,那么在 A 服务这边记录下该用户是否参与过,就不需要牵动到 B 用户
    frandy
        7
    frandy  
       2021-07-02 09:59:18 +08:00
    @frandy #6 不需要牵动到 B 服务
    phpdever
        8
    phpdever  
    OP
       2021-07-02 09:59:22 +08:00
    @tabris17 目前 B 服务有返回给前端,然而前端再将这个是否为新用户带参数给 A 服务嘛?这个并不安全
    tabris17
        9
    tabris17  
       2021-07-02 10:01:01 +08:00
    @phpdever 你这个叫前端接口,不是微服务了
    hakr
        10
    hakr  
       2021-07-02 10:02:53 +08:00
    @johnsona #5 是的, 新用户定义很难说
    phpdever
        11
    phpdever  
    OP
       2021-07-02 10:03:10 +08:00
    @johnsona 需求方提出这个需求的目的是为了拉新,已经注册的用户再参加活动,也算旧用户,不能参加的,只能是从来都没有在平台注册过的用户才可以
    frandy
        12
    frandy  
       2021-07-02 10:09:06 +08:00   ❤️ 1
    再给个思路,定义一个营销活动功能上线的时间,如果 B 服务给到这个用户的注册时间,那么直接和促销时间做对比,这样做的好处是如果营销活动功能下线,也不需要牵动到 B 服务.
    sunjiayao
        13
    sunjiayao  
       2021-07-02 10:10:56 +08:00   ❤️ 2
    你的问题目前看和微服务无关,建议先清晰下新用户的定义。
    我举个例,比如你现在没用微服务。就是一个普通的 web 项目,那用户参加活动报名之前是否需要注册登录?这时候是不是得跳到注册页面,那登陆成功后到活动页面他也是一个已注册的用户了。
    你的解决方案「加入时间维度,在 A 服务校验,如果是当天注册的则为新用户?」其实就是在给新用户做定义。
    比如说新用户属性为:
    1. 注册时间 < 24 小时
    2. 未参加过活动
    3. 没有过其他自定义行为
    本质上是对能参与活动的用户进行资质校验
    timethinker
        14
    timethinker  
       2021-07-02 10:11:15 +08:00   ❤️ 1
    我再来帮你梳理一下什么是新用户

    1 、该用户之前不存在,那么肯定要从不存在变为已存在,也就是说,区分新用户是以注册用户的这个事件为准。
    2 、如果一个新用户注册了,领取了你的活动奖励,那么这个已领取的状态应是在 A 服务进行记录的,换句话来说,一个新用户应该不会领取两次奖励,再结合第 1 点以及活动推出的时间,任何创建时间大于这个活动推出时间并且该用户没有领取过奖励的就算新用户。

    第一点和第二点我认为是等价的,你认为呢?
    phpdever
        15
    phpdever  
    OP
       2021-07-02 10:12:40 +08:00
    @frandy 你的意思是这样吗?活动上线之后 & 在某个渠道下注册的用户 = 新用户
    frandy
        16
    frandy  
       2021-07-02 10:14:41 +08:00   ❤️ 1
    @phpdever #8 A 服务调用 B 服务的查询用户信息接口(若有的话),得到注册时间,不要让前端传你是否为新用户
    phpdever
        17
    phpdever  
    OP
       2021-07-02 10:15:22 +08:00
    @frandy 明白了
    timethinker
        18
    timethinker  
       2021-07-02 10:46:38 +08:00   ❤️ 2
    另外说个题外话,微服务并不是指这种类似 RPC 调用把服务拆分开了就算的,起码有一点,用类似 Dubbo 这种 RPC 就已经就跟 Java 绑定了(虽然可以更改为 HTTP 协议来进行传输,但它终究不过是一个 RPC )。每一个微服务可以有自己独立的技术栈用于实现,通过 REST API 来进行集成,更重要的是,在容错性上(也就是在部署层面)可以做到监控集成与故障转移。

    所以个人认为微服务应该是治理性和维护性上的意义大于具体使用什么语言什么框架这种技术性问题。拆分是一门学问,过早的拆分只会引入没有必要的麻烦,应该站在业务层面还有部署层面上看待这个问题。服务发现、网关、配置、监控等等这些组件都是为了在治理性上尽量做到具有弹性。

    以上这些是我个人的一些想法,无意教大家什么是对的什么是错的,而是想要让大家思考一下微服务在不同层面不同角度带给我们一些启示。
    phpdever
        19
    phpdever  
    OP
       2021-07-02 10:48:15 +08:00
    @qwe520liao 学习了,谢谢大佬
    johnsona
        20
    johnsona  
       2021-07-02 14:01:33 +08:00 via iPhone
    @phpdever 那我没注册成为平台用户 我怎么参加活动呢
    zhuichen
        21
    zhuichen  
       2021-07-02 14:57:18 +08:00
    总结一下,看似问的是技术实现,本质上是业务问题
    phpdever
        22
    phpdever  
    OP
       2021-07-02 15:00:05 +08:00
    @zhuichen 是的,总结的很到位
    phpdever
        23
    phpdever  
    OP
       2021-07-02 17:13:23 +08:00
    @qwe520liao 你好,如果不是跟活动绑定呢?参加 A 活动之后成为旧用户,再去参加 B 活动也是旧用户不能参加,如果想实现这种需求应该怎么办呢? 还请不吝赐教
    palexu
        24
    palexu  
       2021-07-02 17:44:54 +08:00
    A 服务自己维护呀, 比如:活动参与记录表查一下历史参与情况, 方式很多
    timethinker
        25
    timethinker  
       2021-07-02 18:04:39 +08:00   ❤️ 1
    用户服务(授权和用户信息):Service B
    A 活动:Service A1
    B 活动:Service A2

    首先你要知道用户是否已经参加了 A 活动,必然要把这个状态持久化吧,在你的第一个问题中,它是存储在 Service A1 服务上的。
    现在有需求,已经参加 A 活动的无法参加 B 活动,那么 Service A2 肯定是要查询 Service A1 才能知道他是不是已经参加过了对吧?
    至于“旧用户”这个定义,是否具体为“用户参加了 A 活动就算旧用户”,还是取决于你们的需求,我说过了,只要把需求搞明确,做法是不一样的。假设这个“旧用户”是指存储在用户服务的一个标志状态,那么此时就需要查询 Service B,而不是 Service A1 了。
    phpdever
        26
    phpdever  
    OP
       2021-07-04 09:49:24 +08:00
    @qwe520liao 明白明白,谢谢大佬
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2789 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 13:04 · PVG 21:04 · LAX 05:04 · JFK 08:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.