エビフライの唐揚げ

今までのことや、技術的なこと、その他を書いていこうと思います。

HerokuにデプロイしたDjangoに重たい処理をさせたい

HerokuにデプロイしたDjangoに重たい処理をさせたい

Djangoで作成したサイトの情報を更新するのに
別のプログラムを作って管理すると二重管理になって大変ですよね

そんなあなたに朗報です!


ちなみに、普通に重たい処理をWebAPIで作成するとタイムアウトします(たしか30秒)
30秒以上かかる処理は作れないのです。

そのためのスレッド!

 

def ExecuteHevyMethod(request):
    t1 = threading.Thread(target=HevyMethod)
    t1.start()
    return HttpResponse("Start-HevyMethod!")


def HevyMethod():
    #30秒以上かかる重たい処理
    return "complate"

これだけです。これで、裏で重たい処理を動かせます!

【C#】超簡単-非同期/並立実行で結果の順番も保証されるコードコピペでOK

今回はソースのみ。。。

		private async void Execute()
		{
			//タスクを突っ込むリスト(に、メソッドを突っ込む)
			var tasks = new (string, Task<object>)[]{
			("タスク1",Task.Run<object>(()=>HevyMethod(1))),
			("タスク2",Task.Run<object>(()=>HevyMethod(2))),
			("タスク3",Task.Run<object>(()=>HevyMethod(3))),
			};

			//非同期で待つ
			await Task.WhenAll(tasks.Select(p => p.Item2));

			//処理が完了してるので表示
			foreach (var res in tasks)
			{
				Console.WriteLine(res.Item1 + ':' + res.Item2.Result);
			}
		}
		private int HevyMethod(int i)
		{
			Thread.Sleep(i * 1000);
			return i * 2;
		}

firebaseConfigの取得方法

FirebaseのConfigの取得方法

 

Firebase(HostingやRealtimeDatabaseなどを使えるGoogleのサービス)SDKをwebで使用するにあたって、下記のような値を設定する必要があります。

 

 

var firebaseConfig = {
  apiKey
: "api-key",
  authDomain
: "project-id.firebaseapp.com",
  databaseURL
: "https://project-id.firebaseio.com",
  projectId
: "project-id",
  storageBucket
: "project-id.appspot.com",
  messagingSenderId
: "sender-id",
  appID
: "app-id",
};

 

Firebaseについては、色んな記事で書かれているので割愛しますが、肝心なこいつの取得方法がわからなかったので、メモがてらに描きます

 

1.アプリを追加

f:id:littlemore:20200720215439p:plain

 

2.WEBアプリならこれを押す

f:id:littlemore:20200720215635p:plain

 

3.適当に名前を決めてアプリを登録

f:id:littlemore:20200720215855p:plain

4.Configの値が表示されます

 

f:id:littlemore:20200720220019p:plain

 

いや、最近知りました。

知る前までは設定を漁って、値をかき集めて作ってました。。。

アンテナサイト作りました。

f:id:littlemore:20200718184349p:plainまとめターミナル

https://matometerminal.web.app

 

最終的にDjangoでWebAPI作って、Firebaseに静的コンテンツを置いてます。

 

 

1.RSS取得定時実行

サーバ:Heroku

言語:Python

処理:

5分おきに実行

予め設定したまとめサイトから、RSSを取得してHerokuのPostgresに突っ込む

本当は、Django側にRSS取得~DB突っ込み用WebApiを作成しようと思ったが、30秒以内で終わらずエラーになるので、定時実行で処理することにした

ちなみ、Djangoがスリープに入らないように、ついでに叩く。

urlpatterns =[
    path('getsummary/',views.index ,name='index'),
    path('getsummaryrange/',views.range ,name='getsummaryrange'),
    path('wakeup/',views.wakeup ,name='wakeup'),
    # path('makesummary/',views.makesummary ,name='makesummary'),
]

def wakeup(request):
    return HttpResponse("")

こんな感じで空文字返すAPIを作成したw

2.Django

サーバ:Heroku

言語:Python

フレームワークDjango

処理:

WebApiを作っただけ。

HerokuのPostgresからデータを取得して、Jsonを返す。

 

3.フロントエンド

サーバ:Firebase

言語:html,css,javascript

処理:

javascriptでWebAPIを叩いて、表示。

ちなみに、レスポンシブ対応もした。

辛かったけど、出来たら嬉しかった。

 

 

 

静的コンテンツのみでアンテナサイトを作ろうとした話3

3度目の設計変更

前回の設計はアウトなのだ。
何がアウトなのかというと、認証サーバがないこと

javascriptからニフクラを使用するにしてもシークレットキー等が必要で
使うとしたら、シークレットキーをjavascriptに直書きするしか方法がない
直書き市内としても、ユーザーが見えてしまう位置にしか置けない
なので、アウトだ。

1番目の設計のDjangoをHerokuにしようとした
そして、DjangoRSS定時解析機能を実装して、定時解析側から、URLを叩けばサーバーを起こせてRSSの解析が行える一石二鳥になるかと思った、しかしこれもNG。
RSS対象のサイトが100個以上登録されていて、解析に1分くらいかかるのだ。
Herokuの仕様上30秒以内にレスポンスを返さないとタイムアウトが起きてしまう・・・。
なので、1番目の設計に落ち着いた。


AzureFunctionsを使ってみるっていう考えもしたが、どうやら、従量課金制の中に無料枠があるだけらしく
無料枠を超えると料金が発生するらしい。
なので、下手をすると課金される可能性がある。
ということで、やめました。

 

一応、DjangoでWebAPIを作成し、Firebaseに置いたjavascriptで叩く感じにしました。

URL貼ってもいいんですが、NGワード除外とか出来てないので、センシティブな内容まで表示されてしまってるので貼りたくないっす。

静的コンテンツのみでアンテナサイトを作ろうとした話2

まずは、前回ローカルで動いたと言いましたがその際のコードを貼っておきます

 

HTML

<!DOCTYPE html>
<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/list.js/1.5.0/list.min.js"></script>
    <script type="text/javascript" src="script.js" charset="UTF-8"></script>
    <meta charset="utf-8" />
    <title>まとめターミナル</title>
</head>
<body>
    <h1>まとめターミナル</h1>
    <p>まとめのまとめです</p>
    <div id="article-list">
        <ul class="list" id="feed"></ul>
    </div>
</body>
</html>

 

javascript

'use strict';

read_rss("http://blog.livedoor.jp/rbkyn844/index.rdf")
read_rss("http://blog.livedoor.jp/dqnplus/index.rdf")
read_rss("http://alfalfalfa.com/index.rdf")
read_rss("http://himasoku.com/index.rdf")
read_rss("http://hamusoku.com/index.rdf")
read_rss("http://www.2nn.jp/rss/index.rdf")

function read_rss (rdf_url) {
  $.ajax({
    url: rdf_url,
    cache: false,
    dataType: "xml",
    success: function (xml) {
      var feed = document.getElementById('feed');
      $(xml).find('item').each(function () {
        var title = $(this).find('title').text();
        var url = $(this).find('link').text();
        var date = $(this).find('dc\\:date').text();
        var li = document.createElement('li');
        var article = document.createElement('a');
        article.href = url;
        article
        article.className = 'article'

        var time_s = document.createElement('span');
        var dateTime = new Date(date);
        time_s.textContent = toDoubleDigits(dateTime.getHours()) + ':' + toDoubleDigits(dateTime.getMinutes());

        var title_s = document.createElement('span');
        title_s.textContent = title;

        var time_hidden = document.createElement('span');
        time_hidden.textContent = new Date(date).getTime();
        time_hidden.className = 'sort-date';
        time_hidden.style.display ="none";

        article.appendChild(time_s);
        article.appendChild(title_s);
        article.appendChild(time_hidden);

        li.appendChild(article);
        feed.appendChild(li);
        // $('<li></li>').html('<a href="'+url+'">'+title+'</a>').appendTo('ul#feedList');
      });

      var options = {
        // リストカラム名
        valueNames: ['sort-date']
      };

      var articleList = new List('article-list', options);
      articleList.sort('sort-date', { order: "desc" });
    }
  });
};

var toDoubleDigits = function(num) {
  num += "";
  if (num.length === 1) {
    num = "0" + num;
  }
 return num;
}

 

では、次に設計をします・・・。

はじめは、もうこうなったら

Django使うしかねぇ!

と考えて

f:id:littlemore:20200527224346p:plain


定時実行でRSSを見に行き、postgresへ突っ込み
Django側でpostgresから値を引っ張り出して表示!
さらにHerokuがスリープしないように30分に1回HerokuでHerokuを叩くか!と考えていました

 

やっぱりスマートな方法じゃないな

そこで、このブログで過去の作ったものについてまとめているときに思い出したんです。
一時的ならニフクラ使えばいいじゃんと!
そこで設計し直しました。

f:id:littlemore:20200527224421p:plain


定時実行でRSSを見に行くところまでは一緒ですが、データをニフクラに突っ込み
実際サイトの表示自体はFirebaseにデプロイしたjavascriptで行ってhtmlに表示!

これで良いんじゃね?
今これから作っていきます!

静的コンテンツのみでアンテナサイトを作ろうとした話1

結論から言いますが、無理でした。

何故静的コンテンツのみで、というのはサーバー側で処理させたくなかったからです
基本無料プランをモットーにしていて、AzureでもHerokuでも、無料プランの場合は一定時間アクセスが無いと、スリープに入ってしまうんですね、一度スリープに入ると、アクセスしてから実際にサイトが表示されるまで10秒以上待たされることがあり、そんなん実用的なサイトじゃないじゃん!といことで、FirebaseにHTMLとjavascriptを置いてそこですべて完結させようとしました。
Firebaseにhtmlとjavascriptを置くだけであれば、スリープなどしないのですぐにアクセスできるのです。

 

f:id:littlemore:20200527223612p:plain

 

ローカルでは動きました。

しかし、Firebaseに上げると動かないわけです
それはMixed contentエラーというのが原因です

ssl.sakura.ad.jp

 

Firebaseでホスティングした場合、URLが「https」になるのですが、RSSのほうは「http」でセキュリティ上問題があるよーってことでChromeにアクセスを遮断されてしまいます
RSSのURLを単純に「http」から「https」変えたのですが、そうすると今度は「この接続ではプライバシーが保護されません」というエラーでアクセスできません・・・

 

どうにか「https」に変える方法はないのかと考えたところ、短縮URLサービスを使えば良いんじゃないか?と思いました。
たしかに、「https」になる短縮URLサービスも存在しました

is.gd


ですが、リダイレクトしているだけ?のようで、どうも同じくうまくいきません

もっと探して見つけたのがRSSJsonに変換して返してくれるサービスです。

rss2json.com


これであれば、うまくいきました。

サイトにリダイレクトするわけではなく、このサービスの内部処理でRSSからJSONに変換して返してくれていて、かつ「https」なので、Firebaseでもちゃんと表示されたわけです。

しかし、何度かリロードしていると・・・

何故か表示されなくなりました

詳細を見てみると・・・

f:id:littlemore:20200527223642p:plain

{"status":"error","message":"You are converting new feeds in a very short period, please use an API key (https://rss2json.com/docs)."}

要は、めっちゃ短い間隔でコンバートのリクエスト投げてるだろ、会員登録して金払え!ってことですね。
まぁ、そりゃそうですよ、こんな便利なサービスを無料で提供してくれて、無料で全部使えたらただの慈善事業ですからね・・・。


というわけで、基本無料プランの原則に違反するのでこの方法もNG

じゃ、どうしようか
そもそも別に自分で使いたいだけだし、ローカルで見れれば良いのかなぁとか
同じようなサイトいっぱいあるし・・・別に自分が作らなくても・・・

antenam.info


(簡単にできるサービスあるやん・・・)

とか色々思ったのですが、まぁブログの記事にできるし
web系やpythonやりたいし
そもそも、クリエイト欲を満たしたい!という思いで、

Djangoでアンテナサイトを作ろう!

と考えたわけです。

今日はここまで