QNUploadDomainRegion.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. //
  2. // QNUploadServerDomainResolver.m
  3. // AppTest
  4. //
  5. // Created by yangsen on 2020/4/23.
  6. // Copyright © 2020 com.qiniu. All rights reserved.
  7. //
  8. #import "QNUploadDomainRegion.h"
  9. #import "QNResponseInfo.h"
  10. #import "QNUploadServer.h"
  11. #import "QNZoneInfo.h"
  12. #import "QNUploadServerFreezeManager.h"
  13. #import "QNDnsPrefetch.h"
  14. #import "QNLogUtil.h"
  15. #import "QNUtils.h"
  16. @interface QNUploadIpGroup : NSObject
  17. @property(nonatomic, copy, readonly)NSString *groupType;
  18. @property(nonatomic, strong, readonly)NSArray <id <QNIDnsNetworkAddress> > *ipList;
  19. @end
  20. @implementation QNUploadIpGroup
  21. - (instancetype)initWithGroupType:(NSString *)groupType
  22. ipList:(NSArray <id <QNIDnsNetworkAddress> > *)ipList{
  23. if (self = [super init]) {
  24. _groupType = groupType;
  25. _ipList = ipList;
  26. }
  27. return self;
  28. }
  29. - (id <QNIDnsNetworkAddress>)getServerIP{
  30. if (!self.ipList || self.ipList.count == 0) {
  31. return nil;
  32. } else {
  33. return self.ipList[arc4random()%self.ipList.count];
  34. }
  35. }
  36. @end
  37. @interface QNUploadServerDomain: NSObject
  38. @property(atomic , assign)BOOL isAllFrozen;
  39. @property(nonatomic, copy)NSString *host;
  40. @property(nonatomic, strong)NSArray <QNUploadIpGroup *> *ipGroupList;
  41. @end
  42. @implementation QNUploadServerDomain
  43. + (QNUploadServerDomain *)domain:(NSString *)host{
  44. QNUploadServerDomain *domain = [[QNUploadServerDomain alloc] init];
  45. domain.host = host;
  46. domain.isAllFrozen = false;
  47. return domain;
  48. }
  49. - (QNUploadServer *)getServer:(NSArray <QNUploadServerFreezeManager *> *)freezeManagerList{
  50. if (self.isAllFrozen || !self.host || self.host.length == 0) {
  51. return nil;
  52. }
  53. if (!self.ipGroupList || self.ipGroupList.count == 0) {
  54. [self createIpGroupList];
  55. }
  56. // Host解析出IP时:
  57. if (self.ipGroupList && self.ipGroupList.count > 0) {
  58. QNUploadServer *server = nil;
  59. for (QNUploadIpGroup *ipGroup in self.ipGroupList) {
  60. if (![self isGroup:ipGroup.groupType frozenByFreezeManagers:freezeManagerList]) {
  61. id <QNIDnsNetworkAddress> inetAddress = [ipGroup getServerIP];
  62. server = [QNUploadServer server:self.host
  63. host:self.host
  64. ip:inetAddress.ipValue
  65. source:inetAddress.sourceValue
  66. ipPrefetchedTime:inetAddress.timestampValue];
  67. break;
  68. }
  69. }
  70. if (server == nil) {
  71. self.isAllFrozen = true;
  72. }
  73. return server;
  74. }
  75. // Host未解析出IP时:
  76. NSString *groupType = [QNUtils getIpType:nil host:self.host];
  77. if (![self isGroup:groupType frozenByFreezeManagers:freezeManagerList]){
  78. return [QNUploadServer server:self.host host:self.host ip:nil source:nil ipPrefetchedTime:nil];
  79. } else {
  80. self.isAllFrozen = true;
  81. return nil;
  82. }
  83. }
  84. - (BOOL)isGroup:(NSString *)groupType frozenByFreezeManagers:(NSArray <QNUploadServerFreezeManager *> *)freezeManagerList{
  85. if (!groupType) {
  86. return YES;
  87. }
  88. if (!freezeManagerList || freezeManagerList.count == 0) {
  89. return NO;
  90. }
  91. BOOL isFrozen = NO;
  92. for (QNUploadServerFreezeManager *freezeManager in freezeManagerList) {
  93. isFrozen = [freezeManager isFrozenHost:self.host type:groupType];
  94. if (isFrozen) {
  95. break;
  96. }
  97. }
  98. return isFrozen;
  99. }
  100. - (QNUploadServer *)getOneServer{
  101. if (!self.host || self.host.length == 0) {
  102. return nil;
  103. }
  104. if (self.ipGroupList && self.ipGroupList.count > 0) {
  105. NSInteger index = arc4random()%self.ipGroupList.count;
  106. QNUploadIpGroup *ipGroup = self.ipGroupList[index];
  107. id <QNIDnsNetworkAddress> inetAddress = [ipGroup getServerIP];
  108. QNUploadServer *server = [QNUploadServer server:self.host host:self.host ip:inetAddress.ipValue source:inetAddress.sourceValue ipPrefetchedTime:inetAddress.timestampValue];;
  109. return server;
  110. } else {
  111. return [QNUploadServer server:self.host host:self.host ip:nil source:nil ipPrefetchedTime:nil];
  112. }
  113. }
  114. - (void)createIpGroupList{
  115. @synchronized (self) {
  116. if (self.ipGroupList && self.ipGroupList.count > 0) {
  117. return;
  118. }
  119. // get address List of host
  120. NSArray *inetAddresses = [kQNDnsPrefetch getInetAddressByHost:self.host];
  121. if (!inetAddresses || inetAddresses.count == 0) {
  122. return;
  123. }
  124. // address List to ipList of group & check ip network
  125. NSMutableDictionary *ipGroupInfos = [NSMutableDictionary dictionary];
  126. for (id <QNIDnsNetworkAddress> inetAddress in inetAddresses) {
  127. NSString *ipValue = inetAddress.ipValue;
  128. NSString *groupType = [QNUtils getIpType:ipValue host:self.host];
  129. if (groupType) {
  130. NSMutableArray *ipList = ipGroupInfos[groupType] ?: [NSMutableArray array];
  131. [ipList addObject:inetAddress];
  132. ipGroupInfos[groupType] = ipList;
  133. }
  134. }
  135. // ipList of group to ipGroup List
  136. NSMutableArray *ipGroupList = [NSMutableArray array];
  137. for (NSString *groupType in ipGroupInfos.allKeys) {
  138. NSArray *ipList = ipGroupInfos[groupType];
  139. QNUploadIpGroup *ipGroup = [[QNUploadIpGroup alloc] initWithGroupType:groupType ipList:ipList];
  140. [ipGroupList addObject:ipGroup];
  141. }
  142. self.ipGroupList = ipGroupList;
  143. }
  144. }
  145. - (void)freeze:(NSString *)ip freezeManager:(QNUploadServerFreezeManager *)freezeManager frozenTime:(NSInteger)frozenTime{
  146. [freezeManager freezeHost:self.host type:[QNUtils getIpType:ip host:self.host] frozenTime:frozenTime];
  147. }
  148. - (void)unfreeze:(NSString *)ip freezeManager:(NSArray <QNUploadServerFreezeManager *> *)freezeManagerList {
  149. for (QNUploadServerFreezeManager *freezeManager in freezeManagerList) {
  150. [freezeManager unfreezeHost:self.host type:[QNUtils getIpType:ip host:self.host]];
  151. }
  152. }
  153. @end
  154. @interface QNUploadDomainRegion()
  155. // 是否获取过,PS:当第一次获取Domain,而区域所有Domain又全部冻结时,返回一个domain尝试一次
  156. @property(atomic , assign)BOOL hasGot;
  157. @property(atomic , assign)BOOL isAllFrozen;
  158. // 局部冻结管理对象
  159. @property(nonatomic, strong)QNUploadServerFreezeManager *partialFreezeManager;
  160. @property(nonatomic, strong)NSArray <NSString *> *domainHostList;
  161. @property(nonatomic, strong)NSDictionary <NSString *, QNUploadServerDomain *> *domainDictionary;
  162. @property(nonatomic, strong)NSArray <NSString *> *oldDomainHostList;
  163. @property(nonatomic, strong)NSDictionary <NSString *, QNUploadServerDomain *> *oldDomainDictionary;
  164. @property(nonatomic, strong, nullable)QNZoneInfo *zoneInfo;
  165. @end
  166. @implementation QNUploadDomainRegion
  167. - (BOOL)isValid{
  168. return !self.isAllFrozen && (self.domainHostList.count > 0 || self.oldDomainHostList.count > 0);
  169. }
  170. - (void)setupRegionData:(QNZoneInfo *)zoneInfo{
  171. _zoneInfo = zoneInfo;
  172. self.isAllFrozen = NO;
  173. NSMutableArray *serverGroups = [NSMutableArray array];
  174. NSMutableArray *domainHostList = [NSMutableArray array];
  175. if (zoneInfo.domains) {
  176. [serverGroups addObjectsFromArray:zoneInfo.domains];
  177. [domainHostList addObjectsFromArray:zoneInfo.domains];
  178. }
  179. self.domainHostList = domainHostList;
  180. self.domainDictionary = [self createDomainDictionary:serverGroups];
  181. [serverGroups removeAllObjects];
  182. NSMutableArray *oldDomainHostList = [NSMutableArray array];
  183. if (zoneInfo.old_domains) {
  184. [serverGroups addObjectsFromArray:zoneInfo.old_domains];
  185. [oldDomainHostList addObjectsFromArray:zoneInfo.old_domains];
  186. }
  187. self.oldDomainHostList = oldDomainHostList;
  188. self.oldDomainDictionary = [self createDomainDictionary:serverGroups];
  189. QNLogInfo(@"region :%@",domainHostList);
  190. QNLogInfo(@"region old:%@",oldDomainHostList);
  191. }
  192. - (NSDictionary *)createDomainDictionary:(NSArray <NSString *> *)hosts{
  193. NSMutableDictionary *domainDictionary = [NSMutableDictionary dictionary];
  194. for (NSString *host in hosts) {
  195. QNUploadServerDomain *domain = [QNUploadServerDomain domain:host];
  196. [domainDictionary setObject:domain forKey:host];
  197. }
  198. return [domainDictionary copy];
  199. }
  200. - (id<QNUploadServer> _Nullable)getNextServer:(BOOL)isOldServer
  201. responseInfo:(QNResponseInfo *)responseInfo
  202. freezeServer:(id <QNUploadServer> _Nullable)freezeServer{
  203. if (self.isAllFrozen) {
  204. return nil;
  205. }
  206. [self freezeServerIfNeed:responseInfo freezeServer:freezeServer];
  207. NSArray *hostList = isOldServer ? self.oldDomainHostList : self.domainHostList;
  208. NSDictionary *domainInfo = isOldServer ? self.oldDomainDictionary : self.domainDictionary;
  209. QNUploadServer *server = nil;
  210. for (NSString *host in hostList) {
  211. server = [domainInfo[host] getServer:@[self.partialFreezeManager, kQNUploadServerFreezeManager]];
  212. if (server) {
  213. break;
  214. }
  215. }
  216. if (server == nil && !self.hasGot && hostList.count > 0) {
  217. NSInteger index = arc4random()%hostList.count;
  218. NSString *host = hostList[index];
  219. server = [domainInfo[host] getOneServer];
  220. [self unfreezeServer:server];
  221. }
  222. self.hasGot = true;
  223. if (server == nil) {
  224. self.isAllFrozen = YES;
  225. }
  226. QNLogInfo(@"get server host:%@ ip:%@", server.host, server.ip);
  227. return server;
  228. }
  229. - (void)freezeServerIfNeed:(QNResponseInfo *)responseInfo freezeServer:(QNUploadServer *)freezeServer {
  230. if (freezeServer.serverId) {
  231. // 无法连接到Host || Host不可用, 局部冻结
  232. if (!responseInfo.canConnectToHost || responseInfo.isHostUnavailable) {
  233. QNLogInfo(@"partial freeze server host:%@ ip:%@", freezeServer.host, freezeServer.ip);
  234. [_domainDictionary[freezeServer.serverId] freeze:freezeServer.ip
  235. freezeManager:self.partialFreezeManager
  236. frozenTime:kQNGlobalConfiguration.partialHostFrozenTime];
  237. [_oldDomainDictionary[freezeServer.serverId] freeze:freezeServer.ip
  238. freezeManager:self.partialFreezeManager
  239. frozenTime:kQNGlobalConfiguration.partialHostFrozenTime];
  240. }
  241. // Host不可用,全局冻结
  242. if (responseInfo.isHostUnavailable) {
  243. QNLogInfo(@"global freeze server host:%@ ip:%@", freezeServer.host, freezeServer.ip);
  244. [_domainDictionary[freezeServer.serverId] freeze:freezeServer.ip
  245. freezeManager:kQNUploadServerFreezeManager
  246. frozenTime:kQNGlobalConfiguration.globalHostFrozenTime];
  247. [_oldDomainDictionary[freezeServer.serverId] freeze:freezeServer.ip
  248. freezeManager:kQNUploadServerFreezeManager
  249. frozenTime:kQNGlobalConfiguration.globalHostFrozenTime];
  250. }
  251. }
  252. }
  253. - (void)unfreezeServer:(QNUploadServer *)freezeServer {
  254. if (freezeServer == nil) {
  255. return;
  256. }
  257. [_domainDictionary[freezeServer.serverId] unfreeze:freezeServer.ip
  258. freezeManager:@[self.partialFreezeManager, kQNUploadServerFreezeManager]];
  259. [_oldDomainDictionary[freezeServer.serverId] unfreeze:freezeServer.ip
  260. freezeManager:@[self.partialFreezeManager, kQNUploadServerFreezeManager]];
  261. }
  262. - (QNUploadServerFreezeManager *)partialFreezeManager{
  263. if (!_partialFreezeManager) {
  264. _partialFreezeManager = [[QNUploadServerFreezeManager alloc] init];
  265. }
  266. return _partialFreezeManager;
  267. }
  268. @end