Serverless for dummies - pragmatic encounter on azure

栏目: IT技术 · 发布时间: 3年前

内容简介:Serverless in on the rise. Gaining a lot of traction to push new abilities, features and there is more and more hosting/deployment options.It is not only bound to public cloud providers but it’s also getting more popular on on-premise environments where yo

Here I am without the server

Serverless in on the rise. Gaining a lot of traction to push new abilities, features and there is more and more hosting/deployment options.

It is not only bound to public cloud providers but it’s also getting more popular on on-premise environments where you can tune it to your needs. This is backed up by frameworks like OpenFAAS, Kubeless, which are often build in open source world.

Main idea of serverless is to not worry about infrastructure technicalities (no server) and instead focus on solving real problems/writing code.

Serverless code generally is short-living and needs to be stateless, meaning state should be put into/handled by external system, database, etc. Thus it is harder/trickier to do small stateful things like connection pooling (i.e. connections pooling to sql databases).

Serverless for dummies - pragmatic encounter on azure
Best place for servers is in the trash.

When thinking about it in context of cloud platforms (azure, aws), payment model is very interesting:

  • pay as you go
  • scale as you go

On other hand there are some limitations:

  • limited message size
  • limited active connection time(only request reply)
  • limited number of concurrent connections

But What can I build ?

Typical question is what I can build it with it and answer to that is typical it depends or everything .

Most of the time serverless is used as a additional layer on top of typical server-full apps. It fullfils role to solve little problems, threat serverless function as single purpose endpoint that solves one problem. Then compose those little problem-solvers (functions) together to create something bigger .

Not another hello world example

Let’s create something that might be useful.

Function that will accept as a parameter id of spotify playlist and return out of it list of songs together with youtube link.

Here is the final result:

Serverless for dummies - pragmatic encounter on azure
Final look of the app in the browser.

You can experience that by executing, although it might return 500 if youtube api limits were exceeded:

https://spotifytranslatorfunctionapp.azurewebsites.net/api/map?playlist=2GK6j1Wh1NfmIPcFVXC97t

Where:

  • playlist= is a id of spotify playlist

Please note i will focus on local development, thus i won’t go through azure portal and creating/managing/deploying stuff there.

Never the less this of course can be deployed to cloud without a problem.

What we need ?

We will use azure, below are prerequisites:

  • Setup .net core (version 3.1 >= required).
  • Install Azure Functions Core Tools from here.
  • We will need to connect to api of spotify and youtube. Since only limited usage of these api’s is free, we need to create youtube app and spotify app so our usage can be tracked.

Scaffolding

mkdir SpotifyToYoutubeTranslator && cd $_
  func init --worker-runtime dotnet
  func new --language C# --name SpotifyToYoutubeTranslator

Serverless for dummies - pragmatic encounter on azure

Code walkthrough

Entire code is available here. It’s splitted into 3 major sections:

Serverless for dummies - pragmatic encounter on azure

Before we begin

Youtube/spotify application keys need to be stored somewhere safe. Those are secrets that authenticate our app, that can not be compromised. We will use simple approach, which is local.settings.json .

Cloud version is using azure application settings , as secrets from local.settings.json are of course not commited.

Then in code these will be read as follow.

private static readonly string SPOTIFY_APP_KEY =
    System.Environment.GetEnvironmentVariable("SPOTIFY_APP_KEY");
private static readonly string YOUTUBE_APP_KEY =
    System.Environment.GetEnvironmentVariable("YOUTUBE_APP_KEY");

If something more advanced is needed, have a look at azure key-vault . It is ment to store secrets but with more features on top of it :)

Section #1

First we need to know what playlist we want to take from spotify. This is easy as getting playlist id from incoming request query parameters.

var playlist = req.Query["playlist"];

If there is no cached spotify token or it expired, a new one is obtained and cached.

private static async Task<SpotifyItems> GetSpotifyItems(HttpRequest req, string playlist)
{
    if (_spotifyToken == null || _spotifyToken.ExpiryDate < DateTime.UtcNow)
    {
        var fullToken = await GetSpotifyAccessToken();
        _spotifyToken = new SpotifyToken(fullToken["access_token"].ToString(), Int32.Parse(fullToken["expires_in"].ToString()));
    }
    var token = _spotifyToken.Token;

To obtain fresh token, a POST request with spotify app key has to be send to spotify api.

private static async Task<dynamic> GetSpotifyAccessToken()
{
    var tokenHeaders = new FormUrlEncodedContent(new[]{
        new KeyValuePair<string, string>("grant_type", "client_credentials")
    });

    var tokenRequest = new HttpRequestMessage(HttpMethod.Post, "https://accounts.spotify.com/api/token");
    tokenRequest.Content = tokenHeaders;
    tokenRequest.Headers.Add("Authorization", SPOTIFY_APP_KEY);

    var tokenRequestResponse = await _httpClient.SendAsync(tokenRequest);

    return await tokenRequestResponse.Content.ReadAsAsync<dynamic>();
}

Section #2

Secondly, We need actual playlist of songs, given above playlist id . For that, GET request is executed. In the header We pass spotify app token from previous section.

Query parameters contain items, that are going to be returned back by spotify api. In this case we would have:

  • name of a track
  • artist/s
  • name of an album
private static async Task<SpotifyItems> GetSpotifyItems(HttpRequest req, string playlist)
    {
        if (_spotifyToken == null || _spotifyToken.ExpiryDate < DateTime.UtcNow)
        {
            var fullToken = await GetSpotifyAccessToken();
            _spotifyToken = new SpotifyToken(fullToken["access_token"].ToString(), Int32.Parse(fullToken["expires_in"].ToString()));
        }
        var token = _spotifyToken.Token;

        var playlistQuery = HttpUtility.ParseQueryString(string.Empty);
        playlistQuery["fields"] = "items(track(name,artists, album(name))), next";

        string playlistQueryString = playlistQuery.ToString();
        var playlistRequest = new HttpRequestMessage(HttpMethod.Get, $"https://api.spotify.com/v1/playlists/{playlist}/tracks?{playlistQueryString}");
        playlistRequest.Headers.Add("Authorization", $"Bearer {token}");

        var playlistRequestResponse = await _httpClient.SendAsync(playlistRequest);
        playlistRequestResponse.EnsureSuccessStatusCode();

        var spotifyItems = await playlistRequestResponse.Content.ReadAsAsync<SpotifyItems>();
        return spotifyItems;
    }

Section #3

Finally, for each song from the playlist, we need to have link to youtube video and return it as a final response. To do so we call youtube with GET request. For this request no token is needed, we just set the app key in query parameters.

Also in query params we provide:

  • q , search phrase {artist name - track name}
  • type of a resource, hardcoded to video
  • part , we want to get as a result, hardcoded to id
  • maxResults , we are interested only in the first video matching
var resultItems = spotifyItems.Items.Select(async track =>
{
    var youtubeItems = await GetYoutubeItems(track);

    return new ResultItem(
        track.Track.Name,
        track.Track.Artists[0].Name,
        track.Track.Album.Name,
        youtubeItems.Items[0].Id.VideoId
    );
});

return (ActionResult)new OkObjectResult(await Task.WhenAll(resultItems));
private static async Task<YoutubeItems> GetYoutubeItems(SpotifyItem track)
{
    var youtubeRequest =
        new HttpRequestMessage(HttpMethod.Get, $"https://www.googleapis.com/youtube/v3/search?q={track.Track.Artists[0].Name}-{track.Track.Name}&type=video&part=id&maxResults=1&key={YOUTUBE_APP_KEY}");

    var youtubeRequestResponse = await _httpClient.SendAsync(youtubeRequest);
    var youtubeItems = await youtubeRequestResponse.Content.ReadAsAsync<YoutubeItems>();
    return youtubeItems;
}

Final result is composed, by taking ids returned by api and putting them as v query param into youtube video link.

public ResultItem(string name, string artist, string album, string ytId)
{
    Name = name;
    Artist = artist;
    Album = album;
    Url = $"https://www.youtube.com/watch?v={ytId}";
}

Important note - HttpClient is in a static field

We don’t want to create HttpClient for each request. Rather it should be long-lived resource, this will lower memory footprint and it will benefit from reusing tcp connections.

Important thing to remember is that, there won’t be one and only instance of HttpClient , instead each instance of a function runtime will have single HttpClient instance.

For more info about HttpClient checkthis blog post.

Running locally

You can run it locally by cloning repo and creating config file local.settings.json .

  "Values": {
        "AzureWebJobsStorage": "",
        "FUNCTIONS_WORKER_RUNTIME": "dotnet",
        "SPOTIFY_APP_KEY": "Basic YourSpotifyAppKey",
        "YOUTUBE_APP_KEY": "YourYoutubeAppKey"
    }

Then just run func start and call http://localhost:7071/api/map?playlist=YourSpotifyPlaylistId

Have fun :)


以上所述就是小编给大家介绍的《Serverless for dummies - pragmatic encounter on azure》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

精通Python设计模式

精通Python设计模式

[荷] Sakis Kasampalis / 夏永锋 / 人民邮电出版社 / 2016-7 / 45.00元

本书分三部分、共16章介绍一些常用的设计模式。第一部分介绍处理对象创建的设计模式,包括工厂模式、建造者模式、原型模式;第二部分介绍处理一个系统中不同实体(类、对象等)之间关系的设计模式,包括外观模式、享元模式等;第三部分介绍处理系统实体之间通信的设计模式,包括责任链模式、观察者模式等。一起来看看 《精通Python设计模式》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具