
ãã®ãããRabbitMQã䜿çšããå ŽåãMegaFonã§äœæ¥ããããã»ã¹ã§åãã¿ã¹ã¯ã«çŽé¢ããå¿
èŠããããŸããã ããã®ãããªã¿ã¹ã¯ã®å®è£
ãåçŽåããã³èªååããæ¹æ³ã¯ïŒããšããçåãèªç¶ã«çããŸãã
é ã«æµ®ãã¶æåã®è§£æ±ºçã¯ãHTTPã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšããããšã§ãããã¡ãããRabbitMQã«ã¯ããã«äœ¿çšã§ããåªããWebã€ã³ã¿ãŒãã§ã€ã¹ãšHTTP APIããããŸãã ããã§ããHTTP APIã®äœ¿çšã¯åžžã«äŸ¿å©ã§ãããšã¯éãããAMQPãããã³ã«ã䜿çšããŠäœæ¥ããå¿
èŠãçãããããªç¬éã«ã¯äžå¯èœãªå ŽåããããŸãïŒååãªã¢ã¯ã»ã¹æš©ããªãããã¡ãã»ãŒãžãå
¬éãããå Žåãªã©ïŒã
ãããã¯ãŒã¯ã®ãªãŒãã³ã¹ããŒã¹ã§èªåã«é©ããæ¢æã®ãœãªã¥ãŒã·ã§ã³ãèŠã€ãããªããããAMQPãããã³ã«ã䜿çšããŠRabbitMQãæäœããããã®å°ããªã¢ããªã±ãŒã·ã§ã³ãäœæããããšã«ããŸãã ã³ãã³ãã©ã€ã³ãä»ããŠèµ·åãã©ã¡ãŒã¿ã転éããæäœéå¿
èŠãªæ©èœã»ãããæäŸããæ©èœïŒ
- 転èš
- æ ¡æ£ã¡ãã»ãŒãž
- åºæ¬çãªã«ãŒãèŠçŽ ã®äœæãšç·šé
Pythonã¯ããã®ãããªã¿ã¹ã¯ãå®è£
ããããã®æãåçŽãªïŒãããŠç§ã®æèŠã§ã¯çŸããïŒããŒã«ãšããŠéžã°ããŸããã ïŒããã§è°è«ããããšãã§ããŸãããäœãå€ããã®ã§ããããïŒïŒ
RabbitMQã®å
¬åŒã¬ã€ãã®ç¿»èš³ïŒ 1å ã 2å ïŒã¯ããã«è¡šç€ºãããŸãããç·Žç¿ããã®ç°¡åãªäŸã圹ç«ã€å ŽåããããŸãã ãã®èšäºã§ã¯ãå°ããªã¢ããªã±ãŒã·ã§ã³ã®äŸã䜿çšããŠãPythonã®AMQPãã£ãã«ã䜿çšããŠãŠãµã®ãæäœãããšãã«çããäž»ãªåé¡ã説æããããšããŸãã ã¢ããªã±ãŒã·ã§ã³èªäœã¯GitHubã§å
¥æã§ããŸã ã
AMQPãããã³ã«ãšRabbitMQã¡ãã»ãŒãžãããŒã«ãŒã«ã€ããŠç°¡åã«èª¬æããŸã
AMQPã¯ã忣ã·ã¹ãã ã®ã³ã³ããŒãã³ãéã§æãäžè¬çãªã¡ãã»ãŒãžã³ã°ãããã³ã«ã®1ã€ã§ãã ãã®ãããã³ã«ã®äž»ãªç¹åŸŽã¯ã ãã¥ãŒãšäº€æãã€ã³ããšãã2ã€ã®äž»èŠãªæ§é èŠçŽ ãå«ãã¡ãã»ãŒãžã«ãŒããæ§ç¯ããæŠå¿µã§ãã ãã¥ãŒã¯ãåä¿¡ããããŸã§ã¡ãã»ãŒãžãèç©ããŸãã 亀æãã€ã³ãã¯ãç®çã®ãã¥ãŒãŸãã¯å¥ã®äº€æãã€ã³ãã«ã«ãŒãã£ã³ã°ããã¡ãã»ãŒãžãã£ã¹ããªãã¥ãŒã¿ãŒã§ãã 亀æãã€ã³ããã¡ãã»ãŒãžã®éä¿¡å
ãæ±ºå®ããé
åžã«ãŒã«ïŒãã€ã³ãã£ã³ã°ïŒã¯ãæå®ããããã¹ã¯ã«æºæ ããŠãããã©ããã¡ãã»ãŒãžã®ã«ãŒãã£ã³ã°ããŒããã§ãã¯ããããšã«åºã¥ããŠããŸã ã AMQPã®ä»çµã¿ã«ã€ããŠã¯ã ãã¡ããã芧ãã ãã ã
RabbitMQã¯ãAMQPãå®å
šã«ãµããŒãããå€ãã®è¿œå æ©èœãæäŸãããªãŒãã³ãœãŒã¹ã¢ããªã±ãŒã·ã§ã³ã§ãã RabbitMQã䜿çšããããã«ãPythonãå«ãããŸããŸãªããã°ã©ãã³ã°èšèªã§å€æ°ã®ã©ã€ãã©ãªãèšè¿°ãããŠããŸãã
Pythonã®å®è£
ãã€ã§ãå人䜿çšã®ããã«ããã€ãã®ã¹ã¯ãªãããæããããšãã§ãããããã®ãã©ãã«ãç¥ããªãããšããããŸãã ååã«ããããåºããããšã«ãªããšããã¹ãŠãããè€éã«ãªããŸãã 誰ããã©ã®ããã«äœãèµ·åããã®ããäœãã©ãã§å€æŽããã®ããã©ãã§ææ°ããŒãžã§ã³ãå
¥æããã®ãããããŠäœã倿Žãããã®ãã瀺ãå¿
èŠããããŸãã 䜿ããããã®ããã«ãã¢ããªã±ãŒã·ã§ã³ã4ã€ã®ã¢ãžã¥ãŒã«ã«åå²ããããšã決å®ãããŸããã
- æçš¿ãæ
åœããã¢ãžã¥ãŒã«
- ãã¥ãŒããã¡ãã»ãŒãžãæžç®ããã¢ãžã¥ãŒã«
- RabbitMQãããŒã«ãŒã®æ§æã倿Žããããã«èšèšãããã¢ãžã¥ãŒã«
- 以åã®ã¢ãžã¥ãŒã«ã«å
±éã®ãã©ã¡ãŒã¿ãŒãšã¡ãœãããå«ãã¢ãžã¥ãŒã«
ãã®ã¢ãããŒãã«ãããäžé£ã®èµ·åãã©ã¡ãŒã¿ãŒãç°¡çŽ åãããŸãã ç®çã®ã¢ãžã¥ãŒã«ãéžæãããã®åäœã¢ãŒãã®1ã€ãéžæããå¿
èŠãªãã©ã¡ãŒã¿ãŒãæž¡ããŸããïŒåäœã¢ãŒããšãã©ã¡ãŒã¿ãŒã®è©³çްã«ã€ããŠã¯ã-helpãã«ããåç
§ïŒã
MegaFonã®ããŠãµã®ãã®æ§é ã¯ååãªæ°ã®ããŒãã§æ§æãããŠããããã䜿çšã®äŸ¿å®äžãããŒãã«æ¥ç¶ããããã®ããŒã¿ã¯ãäžè¬çãªãã©ã¡ãŒã¿ãŒãšã¡ãœããrmq_common_tools.pyã䜿çšããŠã¢ãžã¥ãŒã«ã«è»¢éãããŸãã
Pythonã§AMQPãåŠçããã«ã¯ã Pikaã©ã€ãã©ãªã䜿çšããŸãã
import pika
ãã®ã©ã€ãã©ãªã䜿çšããŠãRabbitMQã§ã®äœæ¥ã¯3ã€ã®äž»èŠãªæ®µéã§æ§æãããŸãã
- æ¥ç¶ã確ç«ãã
- å¿
èŠãªæäœãå®è¡ãã
- æ¥ç¶ãéãã
æåãšæåŸã®ã¹ããŒãžã¯ãã¹ãŠã®ã¢ãžã¥ãŒã«ã§åãã§ããã rmq_common_tools.pyã§å®è£
ãããŸã
æ¥ç¶ã確ç«ããã«ã¯ïŒ
rmq_parameters = pika.URLParameters(rmq_url_connection_str) rmq_connection = pika.BlockingConnection(rmq_parameters) rmq_channel = rmq_connection.channel()
Pikaã©ã€ãã©ãªã䜿çšãããšãRabbitMQã«æ¥ç¶ããããã®ããŸããŸãªèšèšãªãã·ã§ã³ã䜿çšã§ããŸãã ãã®å Žåãæã䟿å©ãªãªãã·ã§ã³ã¯ããã©ã¡ãŒã¿ãŒãURLæååã®åœ¢åŒã§æ¬¡ã®åœ¢åŒã§æž¡ãããšã§ãã
'amqp://rabbit_user:rabbit_password@host:port/vhost'
æ¥ç¶ãéããã«ã¯ïŒ
rmq_connection.close()
転èš
ã¡ãã»ãŒãžã®å
¬éã¯ããããæãç°¡åã§ãããåæã«ãŠãµã®ãæäœããéã®æãäžè¬çãªæäœã§ãã
rmq_publish.pyã§ã³ã³ãã€ã«ããããã¹ããããªãã·ã³ã°ããŒã«
ã¡ãã»ãŒãžãæçš¿ããã«ã¯ãã¡ãœããã䜿çšããŸã
rmq_channel.basic_publish(exchange = params.exch, routing_key = params.r_key, body = text)
ããã§ïŒ
exchange-ã¡ãã»ãŒãžãçºè¡ããã亀æãã€ã³ãã®åå
routing_key-ã¡ãã»ãŒãžã®å
¬éã«äœ¿çšãããã«ãŒãã£ã³ã°ããŒ
body-ã¡ãã»ãŒãžæ¬æ
rmq_publish.pyã¯ãå
¬éçšã«2ã€ã®ã¡ãã»ãŒãžå
¥åã¢ãŒãããµããŒãããŠããŸãã
- ã¡ãã»ãŒãžã¯ãã³ãã³ãã©ã€ã³ïŒfrom_consoleïŒãä»ããŠãã©ã¡ãŒã¿ãŒãšããŠå
¥åãããŸã
- ã¡ãã»ãŒãžã¯ãã¡ã€ã«ïŒfrom_fileïŒããèªã¿åãããŸã
ç§ã®æèŠã§ã¯ã2çªç®ã®ã¢ãŒãã¯ã倧ããªã¡ãã»ãŒãžãŸãã¯ã¡ãã»ãŒãžé
åãåŠçããå Žåã«ãã䟿å©ã§ãã æåã®æ¹æ³ã§ã¯ã远å ã®ãã¡ã€ã«ãªãã§ã¡ãã»ãŒãžãéä¿¡ã§ããŸããããã¯ãã¢ãžã¥ãŒã«ãä»ã®ã·ããªãªã«çµ±åãããšãã«äŸ¿å©ã§ãã
ã¡ãã»ãŒãžãåä¿¡ãã
ã¡ãã»ãŒãžãåä¿¡ãããšããåé¡ã¯ããã¯ãçºè¡ã®ãããªäºçްãªããšã§ã¯ãããŸããã ã¡ãã»ãŒãžã®èªã¿åãã«é¢ããŠã¯ã次ã®ããšãçè§£ããå¿
èŠããããŸãã
- ã¡ãã»ãŒãžã®åä¿¡ã確èªããåŸãã¡ãã»ãŒãžã¯ãã¥ãŒããåé€ãããŸãã ãããã£ãŠããæŠéãè¡ããã¡ãã»ãŒãžãèªã¿åããã¡ã€ã³ã³ã³ã·ã¥ãŒããããéžæãããŸãã ã¡ãã»ãŒãžã®æµãã倱ããããªãããåã«ãã©ããããã§ç§»åããŠããã¡ãã»ãŒãžãçè§£ãããå Žåãæãè«ççãªãªãã·ã§ã³ã¯ãå¥åã®ããã®ã³ã°ããã¥ãŒããŸãã¯ããã©ãããã¥ãŒããšãåŒã°ãããã®ãäœæããããšã§ãã
- éåžžãèªã¿åãã¡ãã»ãŒãžã«ã¯ãããã«åŠçãŸãã¯åæãå¿
èŠã§ããã€ãŸãããªã¢ã«ã¿ã€ã åŠçãäžå¯èœãŸãã¯äžèŠãªå Žåã¯ãã¡ãã»ãŒãžãã©ããã«ä¿åããå¿
èŠããããŸãã
rmq_consume.pyãã¡ã€ã«ã«å®è£
ãããã¡ãã»ãŒãžãªãŒããŒ
次ã®2ã€ã®åäœã¢ãŒããæäŸãããŸãã
- æ¢åã®ãã¥ãŒããã¡ãã»ãŒãžãèªã¿åã
- ãã®ãã¥ãŒããã¡ãã»ãŒãžãèªã¿åãããã®ã¿ã€ã ãã¥ãŒãšã«ãŒãã®äœæ
ãã¥ãŒãšã«ãŒããäœæããåé¡ã«ã€ããŠã¯ã以äžã§æ€èšããŸãã
çŽæ¥æ ¡æ£ã¯æ¬¡ã®ããã«å®è£
ãããŸãã
channel.basic_consume(on_message, queue=params.queue) try: channel.start_consuming() except KeyboardInterrupt: channel.stop_consuming() except Exception: channel.stop_consuming() rmq_tools.console_log(":\n", traceback.format_exc())
ã©ãã§
on_message-ã¡ãã»ãŒãžãã³ãã©ããã·ãŒãžã£
params.queue-æžç®ãè¡ããããã¥ãŒã®åå
ã¡ãã»ãŒãžãã³ãã©ãŒã¯ãèªã¿åãããã¡ãã»ãŒãžã䜿çšããŠäœããã®æäœãå®è¡ããã¡ãã»ãŒãžé
ä¿¡ã確èªããïŒãŸãã¯å¿
èŠã«å¿ããŠç¢ºèªããªãïŒå¿
èŠããããŸãã
def on_message(channel, method_frame, header_frame, body): global all_cnt, lim if all_cnt >= lim: rmq_tools.console_log(' .') raise KeyboardInterrupt body_str = body.decode("utf-8")[:4000] rk = method_frame.routing_key rmq_params.file.write(rk + '\n') rmq_params.file.write(body_str + '\n\n') all_cnt = all_cnt + 1 if (lim != 0) and (rmq_params.file == sys.stdout): sys.stdout.write(f'[{rmq_tools.time_now()}] - {all_cnt} of {lim} messages consumed.\r') channel.basic_ack(delivery_tag=method_frame.delivery_tag)
ã©ãã§
all_cnt-ã°ããŒãã«ã«ãŠã³ã¿ãŒ
lim-èªã¿åãããã¡ãã»ãŒãžã®æ°
ãã®ãããªãã³ãã©ãŒã®å®è£
ã§ã¯ãç¹å®ã®æ°ã®ã¡ãã»ãŒãžãæžç®ããããã¡ã€ã«ã§èšé²ãè¡ãããå Žåã«æžç®ã®é²è¡ç¶æ³ã«é¢ããæ
å ±ãã³ã³ãœãŒã«ã«åºåãããŸãã
èªã¿åãã¡ãã»ãŒãžãããŒã¿ããŒã¹ã«æžã蟌ãããšãã§ããŸãã çŸåšã®å®è£
ã§ã¯ããã®ãããªæ©äŒã¯æç€ºãããŠããŸãããã远å ããããšã¯é£ãããããŸããã
DBã«èšé²ããOracleããŒã¿ããŒã¹ããã³cx_oracleã©ã€ãã©ãªã®ããŒã¿ããŒã¹ã«ã¡ãã»ãŒãžãæžã蟌ãäŸãæ€èšããŸãã
ããŒã¿ããŒã¹ã«æ¥ç¶ãã
ora_adress = 'host:port/dbSID' ora_creds = 'user/pass' connection_ora = cx_Oracle.connect(ora_creds + '@' + ora_address) ora_cursor = connection_ora.cursor()
on_messageãã³ãã©ãŒã«è¿œå ããŸã
global cnt, commit_int insert_rec = 'insert into ' + tab_name + '(routing_key, text) values (:rkey, :text)' ora_cursor.execute(insert_rec, text = body_str, rkey = rk) if cnt > commit_int : ora_cursor.execute('commit') cnt = 1 cnt = cnt + 1
ã©ãã§
cntã¯å¥ã®ã«ãŠã³ã¿ãŒã§ã
commit_int-ããŒã¿ããŒã¹ãžã®æ¿å
¥æ°ããã®åŸããã³ããããããå¿
èŠããããŸãã ãã®ãããªãã©ã¡ãŒã¿ãŒãååšããã®ã¯ãããŒã¿ããŒã¹ã®è² è·ã軜æžãããããã§ãã ãã ããã€ã³ã¹ããŒã«ã¯ããã»ã©å€§ãããããŸããã é害ãçºçããå ŽåãæåŸã®æ£åžžãªã³ãããåŸã«èªã¿åãããã¡ãã»ãŒãžã倱ãå¯èœæ§ããããŸãã
ãããŠãäºæ³ã©ãããäœæ¥ã®æåŸã«æçµã³ããããè¡ããæ¥ç¶ãéããŸã
ora_cursor.execute('commit') connection_ora.close()
ãã®ãããªäœããã¡ãã»ãŒãžãèªãã§ããŸãã æ¢èªã¡ãã»ãŒãžã®æ°ã®å¶éãåé€ãããšãããŠãµã®ãããã®ã¡ãã»ãŒãžãç¶ç¶çã«èªãããã®ããã¯ã°ã©ãŠã³ãããã»ã¹ãäœæã§ããŸãã
æ§æ
AMQPãããã³ã«ã¯äž»ã«ã¡ãã»ãŒãžã®å
¬éãšèªã¿åããç®çãšããŠããŸãããã«ãŒãã®æ§æã䜿çšããŠç°¡åãªæäœãå®è¡ããããšãã§ããŸãïŒãããã¯ãŒã¯æ¥ç¶ããã®ä»ã®RabbitMQèšå®ãã¢ããªã±ãŒã·ã§ã³ãšããŠæ§æããããšã«ã€ããŠã¯è©±ããŠããŸããïŒã
åºæ¬çãªæ§ææäœã¯æ¬¡ã®ãšããã§ãã
- ãã¥ãŒãŸãã¯äº€æãã€ã³ãã®äœæ
- 転éã«ãŒã«ã®äœæïŒãã€ã³ãïŒ
- ãã¥ãŒãŸãã¯äº€æãã€ã³ãã®åé€
- 転éã«ãŒã«ã®åé€ïŒãã€ã³ãïŒ
- ãã¥ãŒã®ã¯ãªã¢
ãããã®ããããã«ã€ããŠãpikaã©ã€ãã©ãªã«æ¢è£œã®æé ããããããèµ·åã®äŸ¿å®äžããããã¯rmq_setup.pyãã¡ã€ã«ã«åçŽã«ã³ã³ãã€ã«ãããŸãã æ¬¡ã«ããã©ã¡ãŒã¿ãŒã«é¢ããããã€ãã®ã³ã¡ã³ããšãšãã«ãpikaã©ã€ãã©ãªãŒããã®æé ããªã¹ãããŸãã
ãã¥ãŒãäœæãã
rmq_channel.queue_declare(queue=params.queue, durable = params.durable)
ããã§ã¯ãã¹ãŠãç°¡åã§ã
queue-äœæãããã¥ãŒã®åå
èä¹
æ§ -è«çãã©ã¡ãŒã¿ãŒãå€ãTrueã®å ŽåããŠãµã®ãåèµ·åããŠããã¥ãŒã¯ååšãç¶ããŸãã Falseã®å Žåããã¥ãŒã¯åèµ·åæã«åé€ãããŸãã éåžžã2çªç®ã®ãªãã·ã§ã³ã¯ãå°æ¥å¿
èŠãšãããªãããšãä¿èšŒãããŠããäžæãã¥ãŒã«äœ¿çšãããŸãã
亀æãã€ã³ãã®äœæïŒäº€æïŒ
rmq_channel.exchange_declare(exchange=params.exch, exchange_type = params.type, durable = params.durable)
ããã«ãæ°ããexchange_typeãã©ã¡ãŒã¿ãŒã衚瀺ãããŸã-亀æãã€ã³ãã®ã¿ã€ãã 亀æãã€ã³ãã®çš®é¡ã«ã€ããŠã¯ã ãã¡ããã芧ãã ãã ã
exchange-äœæããã亀æãã€ã³ãã®åå
ãã¥ãŒãŸãã¯äº€æãã€ã³ãã®åé€
rmq_channel.queue_delete(queue=params.queue) rmq_channel.exchange_delete(exchange=params.exch)
転éã«ãŒã«ã®äœæïŒãã€ã³ãïŒ
rmq_channel.queue_bind(exchange=params.exch, queue=params.queue, routing_key=params.r_key)
exchange-転éãè¡ããã亀æãã€ã³ãã®åå
queue-転éããããã¥ãŒã®åå
routing_key-転éã«äœ¿çšãããã«ãŒãã£ã³ã°ããŒã®ãã¹ã¯ã
æå¹ãªãšã³ããªã¯æ¬¡ã®ãšããã§ãã
- rk.my_keyã* -ãã®ãã¹ã¯ã§ã¯ãã¢ã¹ã¿ãªã¹ã¯ã¯ç©ºã§ãªãæåã»ãããæå³ããŸãã ã€ãŸãããã®ãããªãã¹ã¯ã¯ã rk.my_keyãšãã圢åŒã®ããŒããã¹ãŠã¹ãããããŸãã +ä»ã®äœãããããããŒrk.my_keyãèŠéããªã
- rk.my_keyãïŒ -ãã®ãã¹ã¯ã¯ãåã®+ããŒrk.my_keyãšããŠãã¹ãŠãã¹ãããããŸã
転éã«ãŒã«ã®åé€ïŒãã€ã³ãïŒ
rmq_channel.queue_unbind(exchange=params.exch, queue=params.queue, routing_key=params.r_key)
ãã¹ãŠã転éã«ãŒã«ã®äœæã«äŒŒãŠããŸãã
ãã¥ãŒã®ã¯ãªã¢
rmq_channel.queue_purge(queue=params.queue)
queue-ã¯ãªã¢ãããã¥ãŒã®åå
Pythonã¢ããªã±ãŒã·ã§ã³ã§ã®ã³ãã³ãã©ã€ã³ã€ã³ã¿ãŒãã§ã€ã¹ã®äœ¿çšã«ã€ããŠèµ·åãªãã·ã§ã³ã¯ã人çããã£ãšæ¥œã«ããŸãã åèµ·ååã«ã³ãŒããç·šéããªãããã«ãèµ·åæã«ãã©ã¡ãŒã¿ãŒãæž¡ãããã®ã¡ã«ããºã ãæäŸããããšã¯è«ççã§ãã ãã®ç®çã®ããã«argparseã©ã€ãã©ãªãéžæãããŸããã ãã®äœ¿çšã®è€éãã«ã€ããŠã¯è©³ãã説æããŸããããã®ããŒãã«é¢ããååãªã¬ã€ãããããŸãïŒ1ã2ã3ïŒã ãã®ããŒã«ã¯ãã¢ããªã±ãŒã·ã§ã³ã䜿çšããããã»ã¹ã倧å¹
ã«ç°¡çŽ åããã®ã«åœ¹ç«ã¡ãŸããïŒåŒã³åºãå¯èœãªå ŽåïŒã åçŽãªã³ãã³ãã·ãŒã±ã³ã¹ãã¹ããŒããŠåæ§ã®ã€ã³ã¿ãŒãã§ã€ã¹ã«ã©ãããããšããŠããæ¬æ Œçã§äœ¿ããããããŒã«ãå
¥æã§ããŸãã
æ¥åžžç掻ã§ã®å¿çšã æã䟿å©ã«ãªã£ããã®ã
ããŠãä»ã§ã¯æ¥åžžç掻ã§ã®AMQPã®äœ¿çšã«ã€ããŠå°ãå°è±¡ãåããŸããã
æã人æ°ã®ãã£ãæ©èœã¯ãã¡ãã»ãŒãžã®å
¬éã§ãã ç¹å®ã®ãŠãŒã¶ãŒã®ã¢ã¯ã»ã¹æš©ã§ã¯ãå¿
ãããWebã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšã§ãããšã¯éããŸããããç¹å®ã®ãµãŒãã¹ããã¹ãããã ãã§ããå ŽåããããŸãã ããã§ããã®ãã£ãã«ã䜿çšãããµãŒãã¹ã«ä»£ãã£ãŠAMQPãšæ¿èªãæ¯æŽã«æž¡ãããŸãã
2çªç®ã«äººæ°ããã£ãã®ã¯ãã¿ã€ã ãã¥ãŒããã¡ãã»ãŒãžãèªã¿åãæ©èœã§ãã ãã®æ©èœã¯ãæ°ããã«ãŒããšã¡ãã»ãŒãžãããŒã®èšå®ãããã³äºæ
ã®é²æ¢ã«åœ¹ç«ã¡ãŸãã
ä»ã®å¯èœæ§ããããŸããŸãªã¿ã¹ã¯ã«é©çšãããŸãã