JMS微服务开发示例(九)相同的微服务,按用户id来分配使用

虽然,默认情况下,多个相同的微服务,网关是自动根据微服务的压力情况,把用户请求分配到压力较轻的微服务器上。

但是,在某些业务情景下,我们可能希望人为去控制微服务的请求分配。

举个例子,某个微服务,它会不停地计算用户的一些相关数据,由于计算量比较大,并且要求每次计算,需要在1秒内完成,这样,当用户量越来越大,就不可能把所有的用户计算,都放在一台微服务器上执行。

这时候,我们就可以部署多个相同的微服务器,每台微服务器,负责一部分用户的计算,这样,不管用户量如何增长,我们只需要增加微服务器即可。

但是,这样做就带来了一个问题,因为,计算好的数据,我们是保存在内存里,并不会放到数据库、或者redis这样的缓存中(因为redis相对内存还是太慢),这样,当客户端需要读取某个用户的数据,就不能让网关随意分配一个微服务,

必须找到负责这个用户的微服务,访问它才能读取到正确的数据。

为了实现这个功能,在最新版的网关,还有1.0.1.12版本后的JMS.ServiceProvider 类库,在MicroServiceHost中加入了ClientCheckCode属性,可以设置一段验证代码,验证当前的客户端,是否可以调用当前的微服务。

            var microServiceHost = new MicroServiceHost(services);
            microServiceHost.ClientCheckCode = @"
                        try
                        {
                           var number = Convert.ToInt64(arg);
                            return number >= 0 && number <= 10000;
                        }
                        catch 
                        {
                        }
                        return false;
            ";
            microServiceHost.Register<Controllers.UserInfoController>("UserInfoService");
            microServiceHost.ServiceProviderBuilded += Msp_ServiceProviderBuilded;
            microServiceHost.Build(port, HostEnvironment.GatewayAddresses)
                .Run();

在微服务启动前(也可以在启动后动态更改),设置microServiceHost.ClientCheckCode为一段c#代码,其中arg,就是客户端在获取微服务实例时,传过去的userid。

这段代码比较简单,意思就是当userid小于等于10000,允许访问这台微服务器。

下面是应用层获取微服务实例的代码:

            using (var client = new MicroServiceClient())
            {
                //根据用户id,获取微服务实例
                var service = client.GetMicroService<MicroServices.UserInfoService>(this.UserInfo.userid.ToString());
                
                //调用微服务
                var ret = service.GetUserInfo();
            }




    public class MicroServiceClient : JMSClient
    {
        static NetAddress[] GatewayAddresses;
        static IConfiguration Configuration;
        static MicroServiceClient()
        {
            var builder = new ConfigurationBuilder();
            builder.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
            Configuration = builder.Build();
            ConfigurationChangeCallback(null);
        }

        static void ConfigurationChangeCallback(object p)
        {
            Configuration.GetReloadToken().RegisterChangeCallback(ConfigurationChangeCallback, null);

            GatewayAddresses = Configuration.GetSection("Gateways").Get<NetAddress[]>();
        }
        public MicroServiceClient():base(GatewayAddresses , null , Global.ServiceProvider.GetService<ILogger<JMSClient>>())
        {

        }
    }