Serverless for dummies - pragmatic encounter on azure

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

内容简介: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》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

阿里巴巴

阿里巴巴

邓肯·克拉克 (Duncan Clark) / 中信出版社 / 2016-8-22 / CNY 58.00

阿里巴巴的故事在中国已是家喻户晓,马云的个人魅力和非凡的商业头脑也早已声名远扬。而一千个人眼中会有一千个不一样的马云, 一个外国投资人、咨询顾问眼中的马云和阿里巴巴会是什么样的?1994年就来到中国,阿里巴巴创业早期的咨询顾问克拉克先生将阿里巴巴帝国崛起过程中他的见闻、感触和思考结合深入的访谈、研究写成了这本书。 书中既可以读到阿里巴巴艰辛的创业历程、惊心动魄的商业对垒,也不乏有趣好玩儿的背......一起来看看 《阿里巴巴》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具