Lets say I have x amount of instances for a microservice. They all register with a Eureka server.
Some random user wants to make use of this microservice to fetch some data. Obviously they can pick an instance to use. But if they want to use the Eureka discovery service, do they have to implement a Eureka client? If so, how to prevent them from registering to the Eureka server?
Would it be best to create a "master service" that implements a Eureka client for this random user call so they don't have to worry about Eureka at all? Does below diagram make sense?
I'm not familiar with the Eureka Discovery service, but in general most web services will have you sign up for an API token. The API token should then be used by the microservice to make requests to the Eureka Discovery service on the end user's behalf. The "random client" does not need to know about the Eureka Discovery service or how to communicate with it, it should only know how to communicate with your microservice. Using some kind of "master service" would defeat the purpose of a microservice architecture which is primarily scalability, a "master service" would most likely become a bottleneck.
In general you would expect to see an application designed with a microservice architecture configured as follows:
Obviously is a very basic example, it does not consider persistence, caching, etc. But it should give you the basic idea.
Related
I am developing a website using which is based on a microservices architecture which is containerized with docker. Now I want to communicate with microservices using rest API. I read some articles which show some diagrams that API gateway make some connections to microservices. I am confused about the main purpose of the API gateway.
Gateways are used for cross cutting concerns like authentication, logging and redirect to respective backend services. They are usual the single point of entry for applications and are exposed publicly. the rest of the services can sit behind the firewall that your gateway has access to making backend services secure. you also write your resiliency logic in the gateway by implementing retry or circuit breaker patterns etc.
Since gateway has advantages but it can be single point of failure. so make sure it's highly available by deploying redundant copies
I have two Spring Boot web applications. Both applications have different databases and different sets of users. Also, both applications use Spring Security for authentication and authorisation which works properly.
At any given point I will have one instance of the first application running and multiple instances of the 2nd web application running.
I want to expose REST APIs from 1st web application (one instance running) and be able to use that REST APIs from 2nd web application (multiple instances running).
How do I make sure that REST APIs can be accessed securely with proper authentication and by instances of the 2nd applications only.
If you could change your security, I would recommend you to use OAUTH2. Basically it generates a token that is used in your APP2 instances to make the API calls.
You can see more here.
https://spring.io/guides/tutorials/spring-boot-oauth2/
http://websystique.com/spring-security/secure-spring-rest-api-using-oauth2/
But if you can't change your APP's security, you can continue using your current schema. In the APP1 you can create an user for the API calls, this user only has access to the API services. In your APP2 you need to store the credentials to access the APP1. Finally you do login into APP1 and invoke the API using HTTP client, you can use Spring RestTemplate or Apache HttpComponents Client.
SSL based authentication could be an option, if you seriously thinking about the security aspects.
Assume that you REST api exposed by App 1 is over HTTPs, then you can configure the App 1 to ask the client to give their SSL/TLS certificate when they try to access this REST API (exposed by App 1).
This will help us identify that the client is indeed a client from app 2.
Two More Cents:
In case if your App 1 REST API calls needs load balancing, NGINX should be your chose. The SSL client certificate based authentication can be offloaded to NGINX and Your Spring boot app no more worry about the SSL related configurations.
The solution we went with was to secure both using an OAuth2 client_credentials workflow. That is the OAuth2 flow where clients request a token on behalf of themselves, not a calling User.
Check out Spring Cloud Security
1) Secure your services using #EnableResourceServer
#SpringBootApplication
#EnableResourceServer
public class Application ...
2) Make calls from one service to another using an OAuth2RestTemplate
Check out Resource Server Token Relay in http://cloud.spring.io/spring-cloud-security/spring-cloud-security.html which will specify how to configure an Oauth2RestTemplate to forward on security context details (token) from one service to another.
3) Service A and Service B should be able to communicate using these techniques if they are configured using the same Oauth2 Client and Secret. This will be configured in the applications' application.properties file, hopefully injected by the environment. Oauth2 Scopes can be used as role identifiers. You could therefore say that only a Client with Scopes (api-read, api-write) should have access to Endpoint A in Service A. This is configurable using Spring Security's Authorization configuration as well as #EnableGlobalMethodSecurity
There is an external web-service (REST based) which provides logistics service. In order to consume it from our application (which is java stack), I created a client library (using jersey and jackson, which is a self-contained jar file, and gives simple getters and setters to work with). All that is needed to consume this REST service is this jar file (which is being used as re-usable asset).
However, one of our clients asked, "since we already have ESB (a middleware from IBM) for our existing integrations, why can we not have this integration also through ESB ?"
Is it possible to consume the REST based service using a middleware such as ESB(or MQ) ? If so, how ?
Will it be wise to do it ?
What arguments can I posit to my client to tell them this may not work ?
Thanks.
Is it possible to consume the REST based service using a middleware such as ESB(or MQ) ? If so, how ? -
Yes. Every ESB has its syntax/APIs. Should not be difficult to understand if you are already working with REST/http requests. Note, MQ is a message broker that will allow asynchronous communication. For example, the application that wants to consume the REST service can send a message to the broker and not wait for a response from the external service. The message broker in turn can talk REST to the external service. The message broker might expose a REST interface to consume messages. But it all depends on the use case. You may want to call REST service synchronously.
Most ESBs support calling external web services REST/SOAP. So an ESB does not necessarily mean MQ.
Will it be wise to do it ?
It depends. Many organizations set up ESB/Gateway as a policy and to route/filter/govern all external routings. Also to manage load, HA etc.
What arguments can I posit to my client to tell them this may not work ?
It will most certainly work. You should assess if using an ESB is an overhead based on your requirements.
Here is usecase:
I have two apps in Bluemix: app1 and app2
app1 is accessible through the internet using its route (e.g. app1.mybluemix.net)
app2 doesn't have any route to prevent from being accessible through the internet.
app2 may expose a REST API.
How do I call app2 from app1 inside Bluemix?
An example of communicating to an application without a route is implemented in this Microservice Shipping sample.
This is an EJB Liberty application that runs on Bluemix without a route and subscribes to the Bluemix MQ Light service. The sender of the messages is the Microservice Orders sample application, which binds to the same MQ Light service.
Going the REST API route will mean you must have an externally accessible route. However, you could secure it using keys and tokens.
It would be easier to use one of the services in Bluemix as an "RPC" layer between the two applications. You could use one of the queue services (MQLight, RabbitMQ) or Redis to pass messages between the applications to execute commands.
These service bindings are internal and won't be exposed externally unlike the REST API.
Alternatively, you could expose the REST API from App2 and use authentication to control access.
There are two ways you can prevent access.
Put your microservice inside a Bluemix Container and utilize private IPs https://new-console.ng.bluemix.net/docs/containers/container_security_network.html#container_cli_ips_byoip
Use API Connect as a API Gateway/proxy to the private IP being in your container microservice.
Use Bluemix Dedicated to deploy app2. Bluemix dedicated provides firewall capabilities and you could set it up so that it only accepts requests from app1's IP address.
Use Bluemix Local when it becomes available with the same approach where you use your corporate firewall to only accept requests that come from your App1 IP Address. This is an expensive alternative compared to a public PAAS.
Use the API Connect Service which replaced the API Management Service to:
Specify what users can access your apis
Specify the number of requests per day or other unit of time
Provides a API Gateway to securely call the other service App2.
I expect at some point a software network defined solution will be considered as part of the offering.
After watching the BUILD conference videos for Azure Service Fabric, I'm left imagining how this might be a good fit for our current microservice-based architecture. There is one thing I'm not entirely sure how I would go about solving, however - the API gateway/proxy.
Consider a less-than-trivial microservice architecture where you have N number of services running within the Azure Service Fabric exposing REST endpoints. In many situations, you want to package these fragmented API endpoints up into a single-entry API for consumers to use, to avoid having them connecting to the service fabric-instances directly. The Azure Service Fabric solution seems so complete in every way that I'm sort of wondering if I missed something obvious when I don't see a way to trivially solve this within the capabilities mentioned during the BUILD talks.
Services like Vulcan aim to solve this problem by having the services register the paths they want routed to them in etcd. I'm guessing one way of solving this may be to create a separate stateful web service that other services can register themselves with, providing service name and the paths they need routed to them. The stateful web service can then route traffic to the correct instance based on its state. This doesn't seem entirely ideal, though, with stuff like removing routes when applications are removed and generally keeping the state in sync with the services deployed within the cluster. Has anybody given this any thought, or have any ideas how one might go about solving this within Azure Service Fabric?
The service registration/discoverability you need to do this is actually already there. There's a stateful system service called the Naming Service, which is basically a registrar of service instances and the endpoints they're listening on. So when you start up a service - either stateless or stateful - and open some listener on it, the address gets registered with the Naming Service.
Now the part you'd need to fill in is the "gateway" that users interact with. This doesn't have to be stateful because the Naming Service manages the stateful part. But you'd have to come up with an addressing scheme that works for you, and then it would just forward requests along to the right place. Basically something like this:
Receive request.
Use NS to find the service that can take the request.
Forward the request to it and the response back to the user.
If the service doesn't exist anymore, 404.
In general we don't like to dictate anything about how your services talk to each other, but we are thinking of ways to solve this problem for HTTP as a complete built-in solution.
We implemented a HTTP gateway service for this purpose as well. To make sure we can have one HTTP gateway for any internal protocol, we implemented the gateway for HTTP based internal services (like ASP.NET WebAPIs) using an ASP.NET 5 middleware. It routes requests from e.g /service to an internal Service Fabric address like fabric:/myapp/myservice by using the ServicePartitionClient and some retry logic from CommunicationClientFactoryBase.
We open-sourced this middleware and you can find it here:
https://github.com/c3-ls/ServiceFabric-HttpServiceGateway
There's also some more documentation in the wiki of the project.
This feature is build in for http endpoints, starting with release 5.0 of service fabric. The documentation is available at https://azure.microsoft.com/en-us/documentation/articles/service-fabric-reverseproxy/
We have used an open source project called Traefik with amazing success. There is an Azure Service Fabric wrapper around it - it's essentially a GoLang exe that is deployed onto the cluster as Managed Executable.
It supports circuit breakers, weighted round robin LB, path & header version routing (this is awesome for hosting multiple API versions), the list goes on. And its got a handy portal to view the config and health stats.
The real power in it lies in how you configure it. It's done via the service itself in the ServiceManifest.xml. This allows you to deploy new services and have them immediately able to be routed to - no need to update a routing table etc.
Example
<StatelessServiceType ServiceTypeName="WebServiceType">
<Extensions>
<Extension Name="Traefik">
<Labels xmlns="http://schemas.microsoft.com/2015/03/fabact-no-schema">
<Label Key="traefik.frontend.rule.example">PathPrefixStrip: /a/path/to/service</Label>
<Label Key="traefik.enable">true</Label>
<Label Key="traefik.frontend.passHostHeader">true</Label>
</Labels>
</Extension>
</Extensions>
</StatelessServiceType>
Highly recommended!
Azure Service Fabric makes it easy to implement the standard architecture for this scenario: a gateway service as a frontend for the clients to connect to and all the N backend services communicating with the front end gateway. There are a few communication API stacks available as part of Service Fabric that make it easy to communicate from clients to services and within services themselves. The communication API stacks provided by Service Fabric hide the details of discovering, connecting and retrying connections so that you can focus on the actual exchange of information. When using the Service Fabric communication APIs the services do not have to implement the mechanism of registering their names and endpoints to a specific routing service except what are the usual steps as part of creating the service itself. The communication APIs take in the service URI and partition key and automatically resolve and connect to the right service instance. This article provides a good starting point to help make a decision with regards to which communication APIs will be best suited for your particular case depending on whether you are using Reliable Actors or Reliable Services, or protocols such as HTTP or WCF, or the choice of programming language that the services are written in. At the end of the article you will find links to more detailed articles and tutorials for different communication APIs. For a tutorial on communication in Web API services see this.
We are using SF with a gateway pattern and about 13 services behind the gateway. We use the built in DNS service that SF provides, see: https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-dnsservice, this allows the internal service to service calls with known (internal to SF) DNS names, including gateway service to internal services. There are some well known asp.net core gateways (Ocelot, ProxyKit) to use, but we rolled our own. We have an external load balancer to route to multiple gateway instances in SF.
When a service is started, it registers it's endpoint with the fabric naming service. Using the Fabric client APIs you can then ask fabric for the registered endpoints, associated with the registered service name.
So yes, just as you described your case, you would have a gateway that would accept an incoming URI for connection, and then use that path information as the service name lookup, to then create a proxy connection between the incoming request and the actual internal endpoint location.
Looks like the team as posted one the samples that shows how to do this: https://github.com/Azure/servicefabric-samples/tree/master/samples/Services/VS2015/WordCount