Nếu là sự phụ thuộc thì tại sao presentation lại phải thông qua data rồi mới tới domain ? Thằng presenter phải thông qua domain để làm mapper tới data chứ ?
Node.js phù hợp với các ứng dụng nào? Các ứng dụng có số lượng truy cập lớn, yêu cầu cập nhật theo thời gian thực
Đoạn này cũng phải xem lớn là lớn ở mức nào.
Vấn đề ở chỗ nodejs xử lý bất đồng bộ các task ở các event signal, khi nó init quá nhiều event dẫn đến bị bug trong core bộ quản lý signal của Js luôn. Dù nodejs cũng có điểm mạnh/điểm yếu nhưng cái chết của nó là cost/performance chưa được tương xứng, nên các ông lớn không dùng. Ngay như facebook cũng từ bỏ nodejs mà tiếp tục PHP.
và hiện tại Nodejs nó là core rồi tức là k thể nào optimize nó dc nữa
còn Php này kia nó có thể làm dc điều đó thông qua caching
file này khá phức tạp mình up cả lên đây, bạn cần hàm nào thù lấy nhes:
<?phpnamespaceApp\Helpers;useApp\Models\Proxy;useCache;useException;useGuzzleHttp\Client;useLog;useSymfony\Component\Process\Process;classAwsClient{constTIME_CACHE=60;// minutesconstCONNECT_TIME_OUT=20;// secondconstTIME_OUT_RESPONSE=60;// second/**
* get content html from aws via proxy
* @param $url
* @param null $proxy
* @return false|string|array
*/publicstaticfunctiongetContent($url,$proxy=null){$content=self::getData($url,$proxy);Log::debug("content type = ".gettype($content));if($content&&!empty($content)&&is_string($content)){$newContent=str_get_html($content);$titleraw=$newContent->find('title',0);$title=$titleraw->innertext;Log::debug("title = $title");if(trim($title)!='Amazon CAPTCHA'){if($proxy&&!Cache::has('proxy')){Cache::put('proxy',$proxy,self::TIME_CACHE);}self::cleanHtml($newContent);return$content;}else{self::deleteProxyNotWorking($proxy);Log::error("captcha is enabled");}}elseif(isset($content['error'])&&($content['code']==404)){$code=$content['code'];Log::error("Code = $code , URL = ".$url);return['error'=>true,'code'=>$code];}Log::error('Fail to get content URL, start use proxy ='.$url);Log::debug('try to using proxy ...');Cache::forget('proxy');$proxy=self::getNewProxy();if($proxy){returnself::getContent($url,$proxy);}Log::error('Cannot restart by proxy, end crawl!');return['error'=>true,'code'=>500];}publicstaticfunctiongetProxyType($proxy){$ip="{$proxy['ip']}:{$proxy['port']}";$proxyType=$ip;if($proxy['socks5']){$proxyType="socks5://$ip";}if($proxy['ssl']){$proxyType="https://$ip";}if($proxy['socks4']){$proxyType="socks4://$ip";}if($proxy['http']){$proxyType="http://$ip";}Log::debug('proxy type = ',[$proxyType]);return$proxyType;}publicstaticfunctiongetData($url,$proxy=false){$client=newClient();try{if(!$proxy){$content=$client->get($url);return$content->getBody()->getContents();}$content=$client->get($url,['proxy'=>$proxy,'connect_timeout'=>self::CONNECT_TIME_OUT,'timeout'=>self::TIME_OUT_RESPONSE,'allow_redirects'=>false,'headers'=>['User-Agent'=>'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13',]]);return$content->getBody()->getContents();}catch(Exception$exception){Log::error("(getData) Exception messages = {$exception->getMessage()}");Log::error("(getData) status code = {$exception->getCode()}");return['error'=>true,'code'=>$exception->getCode()];}}publicstaticfunctiongetNewProxy(){Log::debug('============= start new proxy ==========');$proxy=self::getProxyFromDB();if(!$proxy){Log::debug('============= empty proxy in db, start using docker ==========');$proxy=self::getNewProxyDocker();if($proxy){return$proxy;}returnfalse;}if(self::checkProxyWorking($proxy)){Log::debug("============= new proxy is = {$proxy} ==========");return$proxy;}returnself::getNewProxy();}publicstaticfunctiongetNewProxyDocker(){Log::error("=============== start restart docker ================");$dockerContainerId=env('DOCKER_CONTAINER_ID');$proxy=env('DOCKER_IPV4');if(!$dockerContainerId||!$proxy){Log::error('not found docker container id, please insert it in env');returnfalse;}Log::debug("DOCKER_CONTAINER_ID = $dockerContainerId");Log::debug("DOCKER_IPV4 = $proxy");$process=newProcess(["docker restart $dockerContainerId"]);$process->run();$process=newProcess(["curl -Lx http://172.17.0.2:8118 http://jsonip.com/"]);echo$process->run();//shell_exec("docker restart $dockerContainerId");sleep(10);// $ipProxy = self::getData('http://jsonip.com/', env('DOCKER_IPV4'));// Log::debug("ipProxy = $ipProxy");return$proxy;}functiongetRandomUserAgent(){$userAgents=array("Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6","Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)","Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)","Opera/9.20 (Windows NT 6.0; U; en)","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 8.50","Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.1) Opera 7.02 [en]","Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; fr; rv:1.7) Gecko/20040624 Firefox/0.9","Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/48 (like Gecko) Safari/48","Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/48 (like Gecko) Safari/48",);$random=rand(0,count($userAgents)-1);return$userAgents[$random];}publicstaticfunctiongetProxyFromDB(){$proxyData=Proxy::where('status',Proxy::WORKING)->inRandomOrder()->first();if(!$proxyData){Log::debug("proxy empty in database!");returnfalse;}$proxy=self::getProxyType($proxyData->toArray());return$proxy;}/**
* check proxy is working with aws
* @param $proxy
* @return bool|resource
*/publicstaticfunctioncheckProxyWorking($proxy){try{$fixUrlToCheck="https://www.amazon.co.jp";$content=self::getData($fixUrlToCheck,$proxy);Log::debug("content type = ".gettype($content));if($content&&!empty($content)&&is_string($content)){$newContent=str_get_html($content);$titleraw=$newContent->find('title',0);$title=$titleraw->innertext;Log::debug("title = $title");if(trim($title)!='Amazon CAPTCHA'){self::cleanHtml($newContent);returntrue;}}}catch(Exception$exception){Log::error("Exception messages (checkProxyWorking) = {$exception->getMessage()}");Log::error("Exception code (checkProxyWorking) = {$exception->getCode()}");}self::deleteProxyNotWorking($proxy);returnfalse;}/**
* check proxy is alive
* @param $proxy
* @return bool
*/publicstaticfunctioncheckProxyAlive($proxy){$proxy_arr=explode(':',$proxy);$host=$proxy_arr[0];$port=$proxy_arr[1];$waitTimeoutInSeconds=10;$check= @fsockopen($host,$port,$errCode,$errStr,$waitTimeoutInSeconds);if($check){returntrue;}Log::error("proxy [$proxy] not alive");self::deleteProxyNotWorking($host);returnfalse;}publicstaticfunctiondeleteProxyNotWorking($proxy){if($proxy){Log::debug('start delete proxy not working = '.$proxy);$proxy=explode(':',$proxy);$ip=str_replace('//','',$proxy[1]);Proxy::where('ip',trim($ip))->delete();}}/**
* run when not have any proxy in DB
* @return bool|string
*/publicstaticfunctiongetProxyFromApi($proxy=null){Log::debug('start get proxy from api');if(Cache::has('API_PROXY')){Log::error('api proxy error, try after one hour');returnfalse;}try{$code=config('common.API_PROXY_CODE');if(!$code){Log::error('not found API_PROXY_CODE');returnfalse;}$urlApi="http://incloak.com/api/proxylist.php?type=h&out=js&code={$code}&maxtime=500";$client=NewClient();if(!$proxy){$content=$client->get($urlApi);$body=$content->getBody()->getContents();}else{$content=$client->get($urlApi,['proxy'=>"tcp://$proxy"]);$body=$content->getBody()->getContents();}$body=json_decode($body,true);foreach($bodyas$data){$proxy="{$data['ip']}:{$data['port']}";if(self::checkProxyWorking($proxy)){return$proxy;}}returnfalse;}catch(Exception$exception){Cache::put('API_PROXY',1,60);Log::error("cannot get proxy from api server, mess= ".$exception->getMessage());}returnfalse;}publicstaticfunctioncleanHtml($html){if($html){$html->clear();unset($html);}}}
Về phía người dùng có thể ngăn chặn bằng cách cài các extension như uMatrix hay noScript. Cái uMatrix thì có thể dễ dàng thiết đặt để nó tự chặn script và iframe được chèn từ tên miền bên thứ 3 :v
THẢO LUẬN
Nếu là sự phụ thuộc thì tại sao presentation lại phải thông qua data rồi mới tới domain ? Thằng presenter phải thông qua domain để làm mapper tới data chứ ?
Cảm ơn tác giả vì bài viết nhé. Mong sớm nhận thêm được những bài thế này
Cảm ơn bạn. Rất mong được đọc phần tiếp theo.
Very Nice, Mr, Chaudhary
いいですね。ありがとうございました。







Hình 1 nói về sự phụ thuộc (dependence), hình 2 nói về workflow. Bạn đang hiểu sai.
cảm ơn ạ, thông tin rất hữu ích. 勉強になりました。
Cảm ơn bạn, thông tin hữu ích quá
Đoạn này cũng phải xem
lớnlà lớn ở mức nào. Vấn đề ở chỗ nodejs xử lý bất đồng bộ các task ở các event signal, khi nó init quá nhiều event dẫn đến bị bug trong core bộ quản lý signal của Js luôn. Dù nodejs cũng có điểm mạnh/điểm yếu nhưng cái chết của nó là cost/performance chưa được tương xứng, nên các ông lớn không dùng. Ngay như facebook cũng từ bỏ nodejs mà tiếp tục PHP. và hiện tại Nodejs nó là core rồi tức là k thể nào optimize nó dc nữa còn Php này kia nó có thể làm dc điều đó thông qua cachingHay quá bác, hiếm khi thấy bài viết dễ hiểu và chi tiết như vậy
hình như chưa có phần router anh ơi. =))))
Impliment 1 singleton chuyên đếm trên tầng app thì sao nếu không có load balance thì cũng không đến nỗi.
mình cũng định bổ sung việc bảo vệ ở phía người dùng mà viết xong mới nhớ ra, sẽ edit thêm sau ạ. Cảm ơn bạn đã góp ý cho mình

file này khá phức tạp mình up cả lên đây, bạn cần hàm nào thù lấy nhes:
Trong phần script deploy ấy bạn, có chỗ post-deploy, bạn có thể thêm script vào đó.
Dịch bằng google translate mà k có chọn lọc.
Helper AwsClient, sao k show luôn b.
Như này là chưa cài thành công đúng k b?
./configureVề phía người dùng có thể ngăn chặn bằng cách cài các extension như uMatrix hay noScript. Cái uMatrix thì có thể dễ dàng thiết đặt để nó tự chặn script và iframe được chèn từ tên miền bên thứ 3 :v