虽然,默认情况下,多个相同的微服务,网关是自动根据微服务的压力情况,把用户请求分配到压力较轻的微服务器上。
但是,在某些业务情景下,我们可能希望人为去控制微服务的请求分配。
举个例子,某个微服务,它会不停地计算用户的一些相关数据,由于计算量比较大,并且要求每次计算,需要在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>>()) { } }