当前位置: 首页 > news >正文

建网站一般用什么工具郑州哪家医院看妇科比较专业

建网站一般用什么工具,郑州哪家医院看妇科比较专业,福田人才市场,yandex网站推广首先说声抱歉#xff0c;可能是因为假期综合症#xff08;其实就是因为懒哈#xff09;的原因#xff0c;已经很长时间没更新博客了#xff0c;现在也调整的差不多了#xff0c;准备还是以每周1-2篇的进度来更新博客#xff0c;并完成本项目所有功能。言归正传#xff… 首先说声抱歉可能是因为假期综合症其实就是因为懒哈的原因已经很长时间没更新博客了现在也调整的差不多了准备还是以每周1-2篇的进度来更新博客并完成本项目所有功能。言归正传本重构项目是在我根据实际需求重构由于还未完全写完所以也没进行压测在2月份时张善友老师给我留言说经过压测发现我重构的Ocelot网关功能性能较差其中根本原因就是缓存模块由于重构项目的缓存强依赖Redis缓存造成性能瓶颈发现问题后我也第一时间进行测试性能影响很大经过跟张老师请教可以使用二级缓存来解决性能问题首先感谢张老师关注并指点迷津于是就有了这篇文章如何把现有缓存改成二级缓存并使用。为了解决redis的强依赖性首先需要把缓存数据存储到本地所有请求都优先从本地提取如果提取不到再从redis提取如果redis无数据在从数据库中提取。提取流程如下MemoryCache Redis db此种方式减少提取缓存的网络开销也合理利用了分布式缓存并最终减少数据库的访问开销。但是使用此种方案也面临了一个问题是如何保证集群环境时每个机器本地缓存数据的一致性这时我们会想到redis的发布、订阅特性在数据发生变动时更新redis数据并发布缓存更新通知由每个集群机器订阅变更事件然后处理本地缓存记录最终达到集群缓存的缓存一致性。但是此方式对于缓存变更非常频繁的业务不适用比如限流策略准备还是使用分布式redis缓存实现但是可以扩展配置单机限流时使用本地缓存实现如果谁有更好的实现方式也麻烦告知下集群环境下限流的实现不胜感激。改造代码首先需要分析下目前改造后的Ocelot网关在哪些业务中使用的缓存然后把使用本地缓存的的业务重构增加提取数据流程最后提供网关外部缓存初始化接口便于与业务系统进行集成。1重写缓存方法找到问题的原因后就可以重写缓存方法增加二级缓存支持默认使用本地的缓存新建CzarMemoryCache类来实现IOcelotCacheT方法实现代码如下。❈using Czar.Gateway.Configuration;using Czar.Gateway.RateLimit;using Microsoft.Extensions.Caching.Memory;using Ocelot.Cache;using System;namespace Czar.Gateway.Cache {    /// summary    /// 金焰的世界    /// 2019-03-03    /// 使用二级缓存解决集群环境问题    /// /summary    public class CzarMemoryCacheT : IOcelotCacheT    {        private readonly CzarOcelotConfiguration _options;        private readonly IMemoryCache _cache;        public CzarMemoryCache(CzarOcelotConfiguration options,IMemoryCache cache)        {            _options options;            _cache cache;        }        public void Add(string key, T value, TimeSpan ttl, string region)        {            key CzarOcelotHelper.GetKey(_options.RedisOcelotKeyPrefix,region, key);            if (_options.ClusterEnvironment)            {                var msg value.ToJson();                if (typeof(T) typeof(CachedResponse))                {//带过期时间的缓存                    _cache.Set(key, value, ttl); //添加本地缓存                    RedisHelper.Set(key, msg); //加入redis缓存                    RedisHelper.Publish(key, msg); //发布                }                else if (typeof(T) typeof(CzarClientRateLimitCounter?))                {//限流缓存直接使用redis                    RedisHelper.Set(key, value, (int)ttl.TotalSeconds);                }                else                {//正常缓存,发布                    _cache.Set(key, value, ttl); //添加本地缓存                    RedisHelper.Set(key, msg); //加入redis缓存                    RedisHelper.Publish(key, msg); //发布                }            }            else            {                _cache.Set(key, value, ttl); //添加本地缓存            }        }        public void AddAndDelete(string key, T value, TimeSpan ttl, string region)        {            Add(key, value, ttl, region);        }        public void ClearRegion(string region)        {            if (_options.ClusterEnvironment)            {                var keys RedisHelper.Keys(region *);                RedisHelper.Del(keys);                foreach (var key in keys)                {                    RedisHelper.Publish(key, ); //发布key值为空处理时删除即可。                }            }            else            {                _cache.Remove(region);            }        }        public T Get(string key, string region)        {            key CzarOcelotHelper.GetKey(_options.RedisOcelotKeyPrefix, region, key);            if(region CzarCacheRegion.CzarClientRateLimitCounterRegion _options.ClusterEnvironment)            {//限流且开启了集群支持默认从redis取                return RedisHelper.GetT(key);            }            var result _cache.GetT(key);            if (result null _options.ClusterEnvironment)            {                result RedisHelper.GetT(key);                if (result ! null)                {                    if (typeof(T) typeof(CachedResponse))                    {//查看redis过期时间                        var second RedisHelper.Ttl(key);                        if (second 0)                        {                            _cache.Set(key, result, TimeSpan.FromSeconds(second));                        }                    }                    else                    {                        _cache.Set(key, result, TimeSpan.FromSeconds(_options.CzarCacheTime));                    }                }            }            return result;        }    } }❈上面就段代码实现了本地缓存和Redis缓存的支持优先从本地提取如果在集群环境使用增加redis缓存支持但是此种方式不适用缓存变更非常频繁场景比如客户端限流的实现所以在代码中把客户端限流的缓存直接使用redis缓存实现。2注入实现和订阅有了实现代码后发现还缺少添加缓存注入和配置信息修改。首先需要修改配置文件来满足是否开启集群判断然后需要实现redis的不同部署方式能够通过配置文件配置进行管理避免硬编码导致的不可用问题。配置文件CzarOcelotConfiguration.cs修改代码如下namespace Czar.Gateway.Configuration{    /// summary    /// 金焰的世界    /// 2018-11-11    /// 自定义配置信息    /// /summary    public class CzarOcelotConfiguration    {        /// summary        /// 数据库连接字符串使用不同数据库时自行修改,默认实现了SQLSERVER        /// /summary        public string DbConnectionStrings { get; set; }        /// summary        /// 金焰的世界        /// 2018-11-12        /// 是否启用定时器默认不启动        /// /summary        public bool EnableTimer { get; set; } false;        /// summary        /// 金焰的世界        /// 2018-11.12        /// 定时器周期单位毫秒默认30分总自动更新一次        /// /summary        public int TimerDelay { get; set; } 30 * 60 * 1000;        /// summary        /// 金焰的世界        /// 2018-11-14        /// Redis连接字符串        /// /summary        public string RedisConnectionString { get; set; }        /// summary        /// 金焰的世界        /// 2019-03-03        /// 配置哨兵或分区时使用        /// /summary        public string[] RedisSentinelOrPartitionConStr { get; set; }        /// summary        /// 金焰的世界        /// 2019-03-03        /// Redis部署方式默认使用普通方式        /// /summary        public RedisStoreMode RedisStoreMode { get; set; } RedisStoreMode.Normal;        /// summary        /// 金焰的计界        /// 2019-03-03        /// 做集群缓存同步时使用会订阅所有正则匹配的事件        /// /summary        public string RedisOcelotKeyPrefix { get; set; } CzarOcelot;        /// summary        /// 金焰的世界        /// 2019-03-03        /// 是否启用集群环境如果非集群环境直接本地缓存数据库即可        /// /summary        public bool ClusterEnvironment { get; set; } false;        /// summary        /// 金焰的世界        /// 2018-11-15        /// 是否启用客户端授权,默认不开启        /// /summary        public bool ClientAuthorization { get; set; } false;        /// summary        /// 金焰的世界        /// 2018-11-15        /// 服务器缓存时间默认30分钟        /// /summary        public int CzarCacheTime { get; set; } 1800;        /// summary        /// 金焰的世界        /// 2018-11-15        /// 客户端标识默认 client_id        /// /summary        public string ClientKey { get; set; } client_id;        /// summary        /// 金焰的世界        /// 2018-11-18        /// 是否开启自定义限流默认不开启        /// /summary        public bool ClientRateLimit { get; set; } false;    } }在配置文件中修改了redis相关配置支持使用redis的普通模式、集群模式、哨兵模式、分区模式配置方式可参考csrediscore开源项目。然后修改ServiceCollectionExtensions.cs代码注入相关实现和redis客户端。 builder.Services.AddMemoryCache(); //添加本地缓存#region 启动Redis缓存并支持普通模式 官方集群模式 哨兵模式 分区模式if (options.ClusterEnvironment) {//默认使用普通模式var csredis new CSRedis.CSRedisClient(options.RedisConnectionString);switch (options.RedisStoreMode) {case RedisStoreMode.Partition:var NodesIndex options.RedisSentinelOrPartitionConStr; Funcstring, string nodeRule null; csredis new CSRedis.CSRedisClient(nodeRule, options.RedisSentinelOrPartitionConStr);break;case RedisStoreMode.Sentinel: csredis new CSRedis.CSRedisClient(options.RedisConnectionString, options.RedisSentinelOrPartitionConStr);break; }//初始化 RedisHelper RedisHelper.Initialization(csredis); }#endregion builder.Services.AddSingletonIOcelotCacheFileConfiguration, CzarMemoryCacheFileConfiguration(); builder.Services.AddSingletonIOcelotCacheInternalConfiguration, CzarMemoryCacheInternalConfiguration(); builder.Services.AddSingletonIOcelotCacheCachedResponse, CzarMemoryCacheCachedResponse(); builder.Services.AddSingletonIInternalConfigurationRepository, RedisInternalConfigurationRepository(); builder.Services.AddSingletonIOcelotCacheClientRoleModel, CzarMemoryCacheClientRoleModel(); builder.Services.AddSingletonIOcelotCacheRateLimitRuleModel, CzarMemoryCacheRateLimitRuleModel(); builder.Services.AddSingletonIOcelotCacheRemoteInvokeMessage, CzarMemoryCacheRemoteInvokeMessage(); builder.Services.AddSingletonIOcelotCacheCzarClientRateLimitCounter?, CzarMemoryCacheCzarClientRateLimitCounter?();现在需要实现redis订阅来更新本地的缓存信息在项目启动时判断是否开启集群模式如果开启就启动订阅实现代码如下public static async TaskIApplicationBuilder UseCzarOcelot(this IApplicationBuilder builder, OcelotPipelineConfiguration pipelineConfiguration){//重写创建配置方法var configuration await CreateConfiguration(builder); ConfigureDiagnosticListener(builder); CacheChangeListener(builder);return CreateOcelotPipeline(builder, pipelineConfiguration);}/// summary/// 金焰的世界/// 2019-03-03/// 添加缓存数据变更订阅/// /summary/// param namebuilder/param/// returns/returnsprivate static void CacheChangeListener(IApplicationBuilder builder){var config builder.ApplicationServices.GetServiceCzarOcelotConfiguration();var _cache builder.ApplicationServices.GetServiceIMemoryCache();if (config.ClusterEnvironment) {//订阅满足条件的所有事件 RedisHelper.PSubscribe(new[] { config.RedisOcelotKeyPrefix * }, message {var key message.Channel; _cache.Remove(key); //直接移除如果有请求从redis里取//或者直接判断本地缓存是否存在如果存在更新可自行实现。 }); }}使用的是从配置文件提取的正则匹配的所有KEY都进行订阅由于本地缓存增加了定时过期策略所以为了实现方便当发现redis数据发生变化所有订阅端直接移除本地缓存即可如果有新的请求直接从redis取然后再次缓存防止集群客户端缓存信息不一致。为了区分不同的缓存实体便于在原始数据发送变更时进行更新定义CzarCacheRegion类。namespace Czar.Gateway.Configuration{    /// summary    /// 缓存所属区域    /// /summary    public class CzarCacheRegion    {        /// summary        /// 授权        /// /summary        public const string AuthenticationRegion CacheClientAuthentication;        /// summary        /// 路由配置        /// /summary        public const string FileConfigurationRegion CacheFileConfiguration;        /// summary        /// 内部配置        /// /summary        public const string InternalConfigurationRegion CacheInternalConfiguration;        /// summary        /// 客户端权限        /// /summary        public const string ClientRoleModelRegion CacheClientRoleModel;        /// summary        /// 限流规则        /// /summary        public const string RateLimitRuleModelRegion CacheRateLimitRuleModel;        /// summary        /// Rpc远程调用        /// /summary        public const string RemoteInvokeMessageRegion CacheRemoteInvokeMessage;        /// summary        /// 客户端限流        /// /summary        public const string CzarClientRateLimitCounterRegion CacheCzarClientRateLimitCounter;    } }现在只需要修改缓存的region为定义的值即可唯一需要改动的代码就是把之前写死的代码改成如下代码即可。var enablePrefix CzarCacheRegion.AuthenticationRegion;3开发缓存变更接口现在整个二级缓存基本完成但是还遇到一个问题就是外部如何根据数据库变更数据时来修改缓存数据这时就需要提供外部修改api来实现。添加CzarCacheController.cs对外部提供缓存更新相关接口,详细代码如下using Czar.Gateway.Authentication;using Czar.Gateway.Configuration;using Czar.Gateway.RateLimit;using Czar.Gateway.Rpc;using Microsoft.AspNetCore.Authorization;using Microsoft.AspNetCore.Mvc;using Microsoft.Extensions.Caching.Memory;using Ocelot.Configuration;using Ocelot.Configuration.Creator;using Ocelot.Configuration.Repository;using System;using System.Threading.Tasks;namespace Czar.Gateway.Cache{    /// summary    /// 提供外部缓存处理接口    /// /summary    [Authorize]    [Route(CzarCache)]    public class CzarCacheController : Controller    {        private readonly CzarOcelotConfiguration _options;        private readonly IClientAuthenticationRepository _clientAuthenticationRepository;        private IFileConfigurationRepository _fileConfigurationRepository;        private IInternalConfigurationCreator _internalConfigurationCreator;        private readonly IClientRateLimitRepository _clientRateLimitRepository;        private readonly IRpcRepository _rpcRepository;        private readonly IMemoryCache _cache;        public CzarCacheController(IClientAuthenticationRepository clientAuthenticationRepository, CzarOcelotConfiguration options,          IFileConfigurationRepository fileConfigurationRepository,          IInternalConfigurationCreator internalConfigurationCreator,          IClientRateLimitRepository clientRateLimitRepository,          IRpcRepository rpcRepository,          IMemoryCache cache)        {            _clientAuthenticationRepository clientAuthenticationRepository;            _options options;            _fileConfigurationRepository fileConfigurationRepository;            _internalConfigurationCreator internalConfigurationCreator;            _clientRateLimitRepository clientRateLimitRepository;            _rpcRepository rpcRepository;            _cache cache;        }        /// summary        /// 更新客户端地址访问授权接口        /// /summary        /// param nameclientid客户端ID/param        /// param namepath请求模板/param        /// returns/returns        [HttpPost]        [Route(ClientRule)]        public async Task UpdateClientRuleCache(string clientid, string path)        {            var region CzarCacheRegion.AuthenticationRegion;            var key CzarOcelotHelper.ComputeCounterKey(region, clientid, , path);            key CzarOcelotHelper.GetKey(_options.RedisOcelotKeyPrefix, region, key);            var result await _clientAuthenticationRepository.ClientAuthenticationAsync(clientid, path);            var data new ClientRoleModel() { CacheTime DateTime.Now, Role result };            if (_options.ClusterEnvironment)            {                RedisHelper.Set(key, data); //加入redis缓存                RedisHelper.Publish(key, data.ToJson()); //发布事件            }            else            {                _cache.Remove(key);            }        }        /// summary        /// 更新网关配置路由信息        /// /summary        /// returns/returns        [HttpPost]        [Route(InternalConfiguration)]        public async Task UpdateInternalConfigurationCache()        {            var key CzarCacheRegion.InternalConfigurationRegion;            key CzarOcelotHelper.GetKey(_options.RedisOcelotKeyPrefix, , key);            var fileconfig await _fileConfigurationRepository.Get();            var internalConfig await _internalConfigurationCreator.Create(fileconfig.Data);            var config (InternalConfiguration)internalConfig.Data;            if (_options.ClusterEnvironment)            {                RedisHelper.Set(key, config); //加入redis缓存                RedisHelper.Publish(key, config.ToJson()); //发布事件            }            else            {                _cache.Remove(key);            }        }        /// summary        /// 删除路由配合的缓存信息        /// /summary        /// param nameregion区域/param        /// param namedownurl下端路由/param        /// returns/returns        [HttpPost]        [Route(Response)]        public async Task DeleteResponseCache(string region,string downurl)        {            var key CzarOcelotHelper.GetKey(_options.RedisOcelotKeyPrefix, region, downurl);            if (_options.ClusterEnvironment)            {                await RedisHelper.DelAsync(key);                RedisHelper.Publish(key, );//发布时间            }            else            {                _cache.Remove(key);            }        }        /// summary        /// 更新客户端限流规则缓存        /// /summary        /// param nameclientid客户端ID/param        /// param namepath路由模板/param        /// returns/returns        [HttpPost]        [Route(RateLimitRule)]        public async Task UpdateRateLimitRuleCache(string clientid, string path)        {            var region CzarCacheRegion.RateLimitRuleModelRegion;            var key clientid path;            key CzarOcelotHelper.GetKey(_options.RedisOcelotKeyPrefix, region, key);            var result await _clientRateLimitRepository.CheckClientRateLimitAsync(clientid, path);            var data new RateLimitRuleModel() { RateLimit result.RateLimit, rateLimitOptions result.rateLimitOptions };            if (_options.ClusterEnvironment)            {                RedisHelper.Set(key, data); //加入redis缓存                RedisHelper.Publish(key, data.ToJson()); //发布事件            }            else            {                _cache.Remove(key);            }        }        /// summary        /// 更新客户端是否开启限流缓存        /// /summary        /// param namepath/param        /// returns/returns        [HttpPost]        [Route(ClientRole)]        public async Task UpdateClientRoleCache(string path)        {            var region CzarCacheRegion.ClientRoleModelRegion;            var key path;            key CzarOcelotHelper.GetKey(_options.RedisOcelotKeyPrefix, region, key);            var result await _clientRateLimitRepository.CheckReRouteRuleAsync(path);            var data new ClientRoleModel() { CacheTime DateTime.Now, Role result };            if (_options.ClusterEnvironment)            {                RedisHelper.Set(key, data); //加入redis缓存                RedisHelper.Publish(key, data.ToJson()); //发布事件            }            else            {                _cache.Remove(key);            }        }        /// summary        /// 更新呢客户端路由白名单缓存        /// /summary        /// param nameclientid/param        /// param namepath/param        /// returns/returns        [HttpPost]        [Route(ClientReRouteWhiteList)]        public async Task UpdateClientReRouteWhiteListCache(string clientid, string path)        {            var region CzarCacheRegion.ClientReRouteWhiteListRegion;            var key clientid path;            key CzarOcelotHelper.GetKey(_options.RedisOcelotKeyPrefix, region, key);            var result await _clientRateLimitRepository.CheckClientReRouteWhiteListAsync(clientid, path);            var data new ClientRoleModel() { CacheTime DateTime.Now, Role result };            if (_options.ClusterEnvironment)            {                RedisHelper.Set(key, data); //加入redis缓存                RedisHelper.Publish(key, data.ToJson()); //发布事件            }            else            {                _cache.Remove(key);            }        }        [HttpPost]        [Route(Rpc)]        public async Task UpdateRpcCache(string UpUrl)        {            var region CzarCacheRegion.RemoteInvokeMessageRegion;            var key UpUrl;            key CzarOcelotHelper.GetKey(_options.RedisOcelotKeyPrefix, region, key);            var result await _rpcRepository.GetRemoteMethodAsync(UpUrl);            if (_options.ClusterEnvironment)            {                RedisHelper.Set(key, result); //加入redis缓存                RedisHelper.Publish(key, result.ToJson()); //发布事件            }            else            {                _cache.Remove(key);            }        }    } }现在基本实现整个缓存的更新策略只要配合后台管理界面在相关缓存原始数据发送变更时调用对应接口即可完成redis缓存的更新并自动通知集群的所有本机清理缓存等待重新获取。接口的调用方式参考之前我写的配置信息接口变更那篇即可。性能测试完成了改造后我们拿改造前网关、改造后网关、原始Ocelot、直接调用API四个环境分别测试性能指标由于测试环境有效我直接使用本机环境然后是Apache ab测试工具测试下相关性能本测试不一定准确只作为参考指标测试的方式是使用100个并发请求10000次测试结果分别如下。改造网关性能测试改造后网关测试Ocelot默认网关性能直接调用API性能本测试仅供参考因为由于网关和服务端都在本机环境部署所以使用网关和不使用网关性能差别非常小如果分开部署可能性别差别会明显写这不是本篇讨论的重点。从测试中可以看到重构的网关改造前和改造后性能有2倍多的提升且与原生的Ocelot性能非常接近。最后本篇主要讲解了如何使用redis的发布订阅来实现二级缓存功能并提供了缓存的更新相关接口供外部程序调用避免出现集群环境下无法更新缓存数据导致提取数据不一致情况但是针对每个客户端独立限流这块集群环境目前还是采用的redis的方式未使用本地缓存如果有写的不对或有更好方式的也希望多提宝贵意见。。
http://www.yutouwan.com/news/92005/

相关文章:

  • 商业网站开发实训报告网站建设与栏目设置
  • 网站后台使用app推广视频
  • 衡阳百度网站建设全屋定制都包括什么
  • 培训机构网站建设要求怎么样在网站做产品推广
  • wordpress move 下载win7最好的优化软件
  • 浙江艮威水利建设有限公司网站wordpress 七牛云图床
  • 光通信网站模板郑州百度搜索优化
  • 电商网站商品中心设计方案一家专门做内部优惠的网站
  • 代理网页地址青岛网站关键字优化
  • 中山 网站建设一条龙服务做网站花了三万块
  • 襄阳做网站公司哪家好网站空间在哪买
  • 自己做的网站如何在网络上展示多用户自助建站
  • 长沙经开区建管站甘肃新闻最新消息今天
  • 网站菜单怎么做有自己的域名怎么建设网站
  • 网站开发时间进度品牌策划ppt案例
  • 网站用什么语言wordpress查看数据库文件
  • 网络推广公司有哪些邢台谷歌seo
  • 企业展示型网站建设方案网站建设行业税率
  • 网站售后服务模板网络营销推广与策划实训总结
  • 怎样用自己的pid做搜索网站网站描述多个词怎么分隔
  • 湘潭网站设计外包服务太原网站建设总部地址
  • 建设一个网站费用wordpress用户访问频率
  • 欢迎访问语文建设杂志网站网络的结构
  • 手机网站免费模板wap手机网站静态模板
  • 淘宝做网站退款十大外贸电商平台
  • 给漫画网站做推广wordpress禁止下载图片
  • 电子商务网站建设与管理课程心得怀化优化办
  • 让网站会员做产品标签确认厦门做网站哪家好
  • 自适应网站建设做微课常用的网站
  • 加强网站建设 通知网站要和别人做api 链接