前提
最近、ビジネス開発、移転やゲームで忙しく、プラス生ずる時から躊躇し、混乱の舞台をヒット、いくつかの時間のために学業を放棄しました。研究の次の段階をピックアップして寒さは、始まりました。抗登るに基づいて要求のシミュレーションを含むデータ検索プロジェクトのいくつかに先立ち暴露は、ランダムを使用する必要がありますUser Agent
使用はので、Redis
非常に単純な実装UA
プールを。
背景
最近需要、要求論理シミュレーションは、各リクエストのリクエストヘッダに必要とされるUser Agent
以下の点を満足します。
- すべての買収は
User Agent
ランダムです。 - すべての買収
User Agent
(ショート)を繰り返すことはできません。 - すべての取得
User Agent
情報必見の主流とオペレーティングシステムは(することができUinux
、Windows
、IOS
など、とAndroid)。
ここから3ポイントであるUA
データの解決ソースは、実際には、我々は特定の実装に焦点を当てるべきです。次のように単純な分析は、プロセスは次のとおりです。
設計ではUA
、プール際にそのデータ構造と循環キューは非常に似ています。
異なる色を想定し、上記の図は、UA
完全に異なっているUA
、それらは循環キューでシャッフルアルゴリズムプットによって分割されている、という事実は、一つは取り出すことUA
の後だけにカーソルを置くcursor
セルに前方または後方(あるいはカーソルキュー内の任意の要素)に設定。最終的な実現はこれです:ミドルウェア(ちょうどキューではなく、メッセージキュー)を介して分散キューを実現する必要があります。
特定の実装
ミドルウェアの種類を格納するための分散データベースの必要性が準備されていることは間違いありませんUA
、あなたが感じる第一印象はRedis
、より適切であろうが。次は選択する必要がありRedis
、データの種類、主な考慮事項いくつかの側面を:
- これは、キューのプロパティを含んでいます。
- ランダムアクセスをサポートする最高。
- チーム内の要素、チームとランダムアクセス時の複雑さを取得するには、すべての後に、低い
UA
トラフィックインターフェイスが比較的大きくなります。
これらの側面サポートRedis
のデータ型ですList
が、注意List
自体が重い、重い作業は、コード・ロジックで実装されるように行くことができません。その後、クライアントが取得想像しUA
、次のようなプロセスは次のとおりです。
以前の分析を組み合わせて、符号化プロセスは、以下のステップがあります。
- インポートする準備ができて
UA
データがデータソースから読み取ることができ、あなたはまた、ファイルを直接読み込むことができます。 - インポートする必要のため、
UA
多くのではない一般的な意志でデータの収集を、場合、ランダムに散在のこの最初のデータセットを考えるJava
開発直接使用することができるCollections#shuffle()
アルゴリズムをシャッフルもちろん、このアルゴリズムは、ランダムデータ自体を分散することができ、このステップは、いくつかのためでありますアナログ側は厳密に検討するUA
シーン正当性が必要です。 - インポート
UA
にデータRedis
リスト。 - 書く分散循環キューを達成するために、スクリプトを。
RPOP + LPUSH
Lua
例のコーディングとテスト
導入Redis
アドバンストクライアントがLettuce
依存しています:
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>
書くスクリプトを、暫定的に呼ばれるスクリプト名に、ディレクトリ:RPOP + LPUSH
Lua
Lua
L_RPOP_LPUSH.lua
resources/scripts/lua
local key = KEYS[1]
local value = redis.call('RPOP', key)
redis.call('LPUSH', key, value)
return value
このスクリプトは非常にシンプルですが、循環キューの機能を実現しています。残りのテストコード次のように
public class UaPoolTest {
private static RedisCommands<String, String> COMMANDS;
private static AtomicReference<String> LUA_SHA = new AtomicReference<>();
private static final String KEY = "UA_POOL";
@BeforeClass
public static void beforeClass() throws Exception {
// 初始化Redis客户端
RedisURI uri = RedisURI.builder().withHost("localhost").withPort(6379).build();
RedisClient redisClient = RedisClient.create(uri);
StatefulRedisConnection<String, String> connect = redisClient.connect();
COMMANDS = connect.sync();
// 模拟构建UA池的原始数据,假设有10个UA,分别是UA-0 ... UA-9
List<String> uaList = Lists.newArrayList();
IntStream.range(0, 10).forEach(e -> uaList.add(String.format("UA-%d", e)));
// 洗牌
Collections.shuffle(uaList);
// 加载Lua脚本
ClassPathResource resource = new ClassPathResource("/scripts/lua/L_RPOP_LPUSH.lua");
String content = StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8);
String sha = COMMANDS.scriptLoad(content);
LUA_SHA.compareAndSet(null, sha);
// Redis队列中写入UA数据,数据量多的时候可以考虑分批写入防止长时间阻塞Redis服务
COMMANDS.lpush(KEY, uaList.toArray(new String[0]));
}
@AfterClass
public static void afterClass() throws Exception {
COMMANDS.del(KEY);
}
@Test
public void testUaPool() {
IntStream.range(1, 21).forEach(e -> {
String result = COMMANDS.evalsha(LUA_SHA.get(), ScriptOutputType.VALUE, KEY);
System.out.println(String.format("第%d次获取到的UA是:%s", e, result));
});
}
}
次のような結果の実行は、次のとおりです。
第1次获取到的UA是:UA-0
第2次获取到的UA是:UA-8
第3次获取到的UA是:UA-2
第4次获取到的UA是:UA-4
第5次获取到的UA是:UA-7
第6次获取到的UA是:UA-5
第7次获取到的UA是:UA-1
第8次获取到的UA是:UA-3
第9次获取到的UA是:UA-6
第10次获取到的UA是:UA-9
第11次获取到的UA是:UA-0
第12次获取到的UA是:UA-8
第13次获取到的UA是:UA-2
第14次获取到的UA是:UA-4
第15次获取到的UA是:UA-7
第16次获取到的UA是:UA-5
第17次获取到的UA是:UA-1
第18次获取到的UA是:UA-3
第19次获取到的UA是:UA-6
第20次获取到的UA是:UA-9
効果の可視違いは、アルゴリズム、分散に関するデータをシャッフルされていません。
概要
実際には、UA
プールの設計難易度は大きくありません、我々はいくつかの点に注意を払う必要があります。
- システムのバージョン、一般的に主流のモバイルデバイスやデスクトップがあまりありませんが、ソースので、
UA
データがあまりありませんが、最も簡単な実装では、ファイルストレージを使用することができ、直接書き込み、読み取り一度Redis
インチ - ランダム分割する必要性に注意
UA
機器システムの同じタイプのを避けるためにデータをUA
シミュレート特定のリスク管理ルール要求時間をトリガーする避けるために、あまりにも密なデータを。 - あなたは知っておく必要があり
Lua
、すべての後に、構文Redis
原子は、コマンドなければならないLua
スクリプトを。
(本明細書で終わり、C-2-D EA-20191114)
説明リンク
- Githubのページ:のhttp://throwable.club/2019/11/14/redis-in-action-ua-pool/
- ページをコーディングします。http://throwable.coding.me/2019/11/14/redis-in-action-ua-pool/