Ir al contenido principal

Destacado

Spring Cloud Sleuth y StackDriver Trace

Siguiendo con nuestra saga de proyectos de Spring GCP, ahora, nos toca ver Spring Cloud Sleuth.
En proyectos de Arquitectura de Micro servicios es muy importante la información y observabilidad de todo. Si se están realizando llamadas entre servicios A, B y C; es importante entender si estas fueron exitosas o existe latencia entre dichas llamadas.

Nosotros podemos agregar esta dependencia de Sleuth a nuestro proyecto Spring Boot para darle ese "super poder" de tracing distribuido y luego exponer dicha información en un Zipkin o Jaegger por ejemplo.

GCP tiene Stackdriver trace, que es un servicio que nos permite guardar esta data de tracing sin tener que administrar nosotros mismos nuestro Zipking o storage. Stackdriver puede productir reportes de latencia y/o detectar anamalías en la performance.

Existen dos formas de usar Stackdriver Trace en nuestra aplicación Spring Boot:

1. Usas un Stackdriver Trace Zipkin proxy y configurar el Spring Cloud Sleuth para que use este prox…

El nuevo HttpClientModule


HttpClientModule  

Se ha escrito un nuevo HttpClientModule en reemplazo del HttpModule. Este nuevo módulo soluciona ya no exige extraer el JSON de la respuesta de cada request y trea mejoras para hacer nuestro testing al API de forma menos verbosa.

Cambiar tu import de:

import { HttpModule } from '@angular/http';

a:

import { HttpClientModule } from '@angular/common/http';


De un código como este:




import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import { UserModel } from './user.model';

@Injectable()
export class UserService {

  constructor(private http: Http) {}

  list(): Observable {
    return this.http.get('/api/users')
      .map(response => response.json())
  }
}

Lo puedes cambiar a:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { UserModel } from './user.model';

@Injectable()
export class UserService {

  constructor(private http: HttpClient) {}

  list(): Observable {
    return this.http.get('/api/users');
  }
}

Testing

Ahora nuestros tests serán menos verbosos:





describe('UserService', () => {

  beforeEach(() => TestBed.configureTestingModule({
    imports: [HttpClientTestingModule],
    providers: [UserService]
  }));

  it('should list the users', () => {
    const userService = TestBed.get(UserService);
    const http = TestBed.get(HttpTestingController);
    // fake response
    const expectedUsers = [{ name: 'Pepito' }];

    let actualUsers = [];
    userService.list().subscribe((users: Array) => {
      actualUsers = users;
    });

    http.expectOne('/api/users').flush(expectedUsers);

    expect(actualUsers).toEqual(expectedUsers);
  });
});


También podemos añadir headers y parámetros a nuestros requests. Por ejemplo:


const params = new HttpParams().set('page', '1');
this.http.get('/api/users', { params });

const headers = new HttpHeaders().set('Authorization', `Bearer ${token}`);
this.http.get('/api/users', { headers });

El ejemplo anterior es muy útil cuando necesitas establecer el header Authorization cuando trabajas con JWT.

Interceptors

Ahora podemos usar interceptors por cada request y response y así podemos añadir un header a un request o manejar un error de una forma centralizada.

Por ejemplo, agregar un OAUTH Token a cada request de forma centralizada:







@Injectable()
export class BackendAPIInterceptor implements HttpInterceptor {

  intercept(req: HttpRequest, next: HttpHandler): Observable> {

    // if it is a Github API request
    if (req.url.includes('api.backend.com')) {
      // we need to add an OAUTH token as a header to access the Github API
      const clone = req.clone({ setHeaders: { 'Authorization': `token ${OAUTH_TOKEN}` } });
      return next.handle(clone);
    }
    // if it's not a Backend API request, we just handle it to the next handler
    return next.handle(req);
  }

}

Y esas son las novedades por ahora. Enjoy!

Comentarios