Our mobile application uses a REST API to communicate with our server.
At the beginning I wanted to keep it RESTful, and keep using good practices. But:
our API will never be public (only internal use)
the application is more and more complex, and the number of requests are growing a lot
I have observed that public API from big services are not really RESTful, because it's hard to respect all constraints.
So do you think instead of making 5 requests to retrieve some data, I can make only one request, then parse the json on the client side?
It breaks an important REST rule, but that would significantly improve performance on the mobile application?
Thanks
Being RESTful by itself provides almost no benefit. The benefits of REST come from its individual properties (statelessness, client-server, resource-based), but not from being completely RESTful (or from using that word). You can pick the most important properties of REST, implement them, and not do the rest (no pun intended).
For example you don't need good URLs and meaningful verbs for your internal API. They are aethetic, but do not help you be more productive. Example: SOAP-based web-services do away with some of the less important REST principles but keep some of the good ones. Webservices are are productive technology, which is what counts.
You should probably use a middleware package for your internal API based on some standard protocols like WS-* and SOAP. A web-services framework solves the RPC-part of your internal API. You don't need to create/parse URLs and you don't need to deal with serialization.
Related
I am Spring Boot dev.
I develop RESTful web services.
One of my colleagues developed an API and it does two things on the basis of operation type.
If opType = Set, the api sets/unsets a flag at the backend and if opType = Get, the api gets the status of the flag.
Does this not break the architecture of REST APIs?
We have Post/Put to change some data at backend, either create or update.
And we have Get, to get the status of some thing from backend.
Now, I want to opinion of better developers!
Should this be allowed, like having multiples operations with one API call, or should we create multiple apis for each of the tasks.
Also, the front end devs in my team, don’t like integrating multiple apis somehow, suggesting that more the api calls, poorer user experience, customer will have.
Is this the normal practice among app developers?
Comments requested.
GET requests in REST are not supposed to change the state of the server, these are read operations, whereas PUT/POST do modifications to the state of the server in the most general sense.
So usually you should have two endpoints GET to read the state of the flag and put/post for creating and modifying the state.
Having said that there is nothing that can technically restrict you from implementing everything in one API, such an API won't adhere to REST conventions, that's true, but from the client-server communication standpoint (HTTP based usually), it's still perfectly doable.
Sure thing, the separation to two endpoints makes the API more clear, easier to debug and maintain the code. But besides being "restful" this can be treated as an opinionated claim.
I didn't really get the argument of integrating multiple APIs - in my understanding, the effort is the same, and even more clear to front-enders, but they might have their own arguments.
For microservices, the common design pattern used is API-Gateway. I am a bit confused about its implementation and implications. My questions/concerns are as follows:
Why other patterns for microservices are not generally discussed? If they are, then did I miss them out?
If we deploy a gateway server, isn't it a bottleneck?
Isn't the gateway server vulnerable to crashes/failures due to excessive requests at a single point? I believe that the load would be enormous at this point (and keeping in mind that Netflix is doing something like this). Correct me if I am wrong in understanding.
Stream/download/upload data (like files, videos, images) will also be passing through the gateway server with other middleware services?
Why can't we use the proxy pattern instead of Gateway?
From my understanding, in an ideal environment, a gateway server would be entertaining the requests from clients and responding back after the Microservices has performed the due task.
Additionally, I was looking at Spring Cloud Gateway. It seems to be something that I am looking for in a gateway server but the routing functionality of it confuses me if it's just a routing (redirect) service and the microservice would be directly responsible for the response to the client.
The gateway pattern is used to provide a single interface to a bunch of different microservices. If you have multiple microservices providing data for your API, you don't want to expose all of these to your clients. Much better for them to have just a single point of entry, without having to think about which service to poll for which data. It's also nice to be able to centralise common processing such as authentication. Like any design pattern, it can be applied very nicely to some solutions and doesn't work well for others.
If throughput becomes an issue, the gateway is very scalable. You can just add more gateways and load balance them
There are some subtle differences between proxy pattern and API gateway pattern. I recommend this article for a pretty straightforward explanation
https://blog.akana.com/api-proxy-or-gateway/
In the area of microservices the API-Gateway is a proven Pattern. It has several advantages e.g:
It encapsulate several edge functionalities (like authentication, authorization, routing, monitoring, ...)
It hides all your microservices and controls the access to them (I don't think, you want that your clients should be able to access your microservices directly).
It may encapsulate the communication protocols requested by your microservices (sometimes the service may have a mixture of protocols internally which even are only allowed within a firewall).
An API-Gateway may also provide "API composition" (orchestrating the calls to several services an merge their results to one). It s not recommended, to implement a such composition in a microservice.
and so on
Implementing all these feature in a proxy is not trivial. There is a couple of API-Gateways which provide all these functionalities and more like the Netflix-Zuul, Spring-Gateway or the Akana Gateway.
Furthermore, in order to avoid your API-Gateway from being a bottleneck you may :
Scale your API-Gateway and load balance it (as mentioned above by Arran_Duff)
Your API-Gateway should not provide a single one-size-fits-all API for all your clients. Doing so you will, in the case of huge request amount (or large files to down/up load) for sure encounter the problems you mentioned in questions 3 and 4. Therefore in order to mitigate a such situation your Gateway e.g may provide each client with a client specific API (a API-Gateway instance serves only a certain client type or business area..). This is exactly what Netflix has done to resolve this problem (see https://medium.com/netflix-techblog/embracing-the-differences-inside-the-netflix-api-redesign-15fd8b3dc49d)
1.Why other patterns for microservices are not generally discussed? If they are, then did I miss them out?
There are many microservice pattern under different categories such as database , service etc .This is a very good article https://microservices.io/patterns/index.html
2.If we deploy a gateway server, isn't it a bottleneck?
Yes to some extent .Q3's answers image will answer this.
3.Isn't the gateway server vulnerable to crashes/failures due to excessive requests at a single point? I believe that the load would be enormous at this point (and keeping in mind that Netflix is doing something like this). Correct me if I am wrong in understanding.
4.Stream/download/upload data (like files, videos, images) will also be passing through the gateway server with other middleware services?
Why can't we use the proxy pattern instead of Gateway?
The use case for an API Proxy versus an API Gateway depends on what kinds of capabilities you require and where you are in the API Lifecycle. If you already have an existing API that doesn’t require the advanced capabilities that an API Gateway can offer than an API Proxy would be a recommended route.
You can save valuable engineering bandwidth because proxies are much easier to maintain and you won’t suffer any negligible performance loss. If you need specific capabilities that a proxy doesn’t offer you could also develop an in-house layer to accommodate your use case. If you are earlier in the API lifecycle or need the extra features that an API Gateway can provide, then investing in one would pay dividends.
I'm trying to start a little microservice application, but I'm a little bit stuck on some technicalities.
I'm trying to build an issue tracker application as an example.
It has 2 database tables, issues and comments. These will also be separate microservices, for the sake of the example.
It has to be a separate API that can be consumed by multiple types of clients e.g. mobile, web etc..
When using a monolitic approach, all the codebase is coupled together, and when making a request to let's say the REST API, I would handle for example the '/issues/19' request
to fetch the issue with the id '19' and it's corresponding comments by means of the following pseudocode.
on_request_issue(id) # handler for the route '/issues/<id>'
issue = IssuesModel.findById(id)
issue.comments = CommentsModel.findByIssueId(id)
return issue
But I'm not sure on how I should approach this with microservices. Let's say that we have microservice-issues and microservice-comments.
I could either let the client send a request to both '/issues/19' and '/comments/byissueid/19'. But that doesn't work nice in my point of view, since if we're having multiple things
we're sending alot of requests for one page.
I could also make a request to the microservice-issues and in that one also make a request to the microservice-comments, but that looks even worse to me than the above, since from what
I've read microservices should not be coupled, and this couples them pretty hard.
So then I read about API gateways, that they could/should receive a request and fan out to the other microservices but then I couldn't really figure out how to use an API gateway. Should
I write code in there for example to catch the '/issues/19' request, then fan out to both the microservice-issues and microservice-commetns, assemble the stuff and return it?
In that case, I'm feeling I'm doing the work double, won't the API gateway become a new monolith then?
Thank you for your time
API gateway sounds like what you need.
If you'll keep it simple, just to trigger internal API, it will not become your new monolith.
It will allow you do even better processing when your application grows with new microservices, or when you have to support different clients (browser, mobile apps, watch, IOT, etc)
BTW, the example you show sounds like a good exercise, in reality, for most webapps, it looks like over design. I would not break every DB call to its own microservices.
One of the motivations for breaking something to small(er) services is service autonomy, in this case the question is, when the comments service is down should you display the issue or not- if they are always coupled anyway, they probably shouldn't reside in two services, if they aren't then making two calls will let you get this decoupling
That said, you may still need an API Gateway to solve CORS issues with your client
Lastly, comments/byissueid is not a good REST interface the issueId should be a parameter /comments/?issueId=..
In a micro-services architecture we can have:
A single API gateway providing a single API for all clients.
A single API gateway providing an API for each kind of client.
A per-client API gateway providing each client with an API. which is the BFF pattern.
Netflix uses the second style Inside the Netflix API Redesign. we can surely say that they have created a smart-piece of middleware in their architecture that takes on multiple responsibilities.
But how much work this single API back-end can handle, it seems that it can become a bottleneck so easily.
So my question is what are the benefits of choosing the single API to handle requests for more than 1000 clients instead of creating an API Gateway specifically designed to one type of clients? Aren't they facing many challenges to manage and maintain this complex piece?
It all depends where your end users are, in case of Netflix, they have differnt types of clients, web/mobile/streaming sticks/bluray players/what not, while web (updated to latest all the time), mobile (updated to latest eventually), bluray player with pre-installed app for example may never get updated.
And you have to version your apis accordingly for each platform and maintain them based on client update cycle for backward compatibility. If you have too many variations in a single api it will be hard to maintain instead it is easier to write an api for each type of client. Unless you have real need for #3 and have enough resources to develop for each type of client I wouldn't jump into it, as you have to maintain many variations of api for the same purpose.
I would start small with #1.
I am planning a new application and have been experimenting with GWT as a possible frontend. The design question I am facing is this.
Should I use
Option A: GWT-RPC and build the app quickly
Option B: Build a REST backend using Spring MVC 3.0 with all the great #Controller, #Service, #Repository annotations and build a client side library to talk to the backend using the GWT overlay features and the GWT Request builder?
I am interested in all the pros and cons and people experiences with this type of design?
Ask yourself the question: "Will I need to reuse the server-side interface with a non-GWT front-end?"
If the answer is "no, I'll just have a GWT client": You can use GWT-RPC, and take advantage of the fact that you can use your Java objects both on the server and the client-side. This can also make the communication a bit more efficient, at least when used with <inherits name="com.google.gwt.user.RemoteServiceObfuscateTypeNames" />, which shortens the type names to small numeric values. You'll also get the advantage of better error handling (using Exceptions), type safety, etc.
If the answer is "yes, I'll make my service accessible for multiple kinds of front-ends": You can use REST with JSON (or XML), which can also be understood by non-GWT clients. In addition to switching clients, this would also allow you to switch to a different server implementation (maybe non-Java) in the future more easily. The disadvantage is, that you'll probably have to write wrappers (JavaScript Overlay Types) or transformation code on the GWT client side to build nice Java objects from the JSON objects. You'll have to be especially careful when you deploy a new version of the service, which brings us back to the lack of type safety.
The third option of course would be to build both. I'd choose this option, if the public REST interface should be different from the GWT-RPC interface anyway - maybe providing just a subset of easy to use services.
You can do both if use also use the RestyGWT project. It will make calling REST based JSON resources as easy as using GWT-RPC. Plus you can typically reuse the same request response DTOs from the server side on the client side.
We ran into the same issue when we created the Spiffy UI Framework. We chose REST and I would never go back. I'd even say GWT-RPC is a GWT Anti-pattern.
REST is a good idea even if you never intend to expose your REST endpoints. Creating a REST API will make your UI faster, your API better, and your entire application more maintainable.
I would say build a REST backend. In my last project we started by developing using GWT-RPC for the first few months, we wanted fast bootstrapping. Later on, when we needed the REST API, it was so expensive to do the refactoring we ended up with two backend APIs (REST and RPC)
If you build a proper REST backend, and a deserialization infra on the client side (to transform the json\xml to GWT Java objects) then the benefit of the RPC is almost nothing.
Another sometimes forgotten advantage of the REST approach is that it's more natural to the browser running the client, RPC is a propitiatory protocol, where all the requests are using POST. You can benefit from client side caching when reading resources in the standard way.
Answering ams comments:
Regarding the RPC protocol, last time I "sniffed" it using firebug it didn't look like json, so I don't know about that. Though, even if it is json based, it still uses only the HTTP POST method to communicate with the server, so my point here about caching is still valid, the browser won't cache POST requests.
Regarding the retrospective and what could have done better, writing the RPC service in a resource oriented architecture could lead later to easier porting to REST. remember that in REST one usually exposes resources with the basic CRUD operations, if you focus on that approach when writing the RPC service then you should be fine.
The REST architectural style promotes inspectable messages (which aids debugging and security), API evolution, multiple platforms, simple interfaces, failure recovery, high scalability, and (optionally) extensible systems via code on demand. It trades per-interaction performance for overall network efficiency. It reduces the server's control over consistent application behavior.
The "RPC style" (as we speak of it in opposition to REST) promotes platform uniformity, interface variability, code generation (and thereby the ability to pretend the network doesn't exist, but see the Fallacies), and customized interactions. It trades overall network efficiency for high per-interaction performance. It increases the server's control over consistent application behavior.
If your application desires the former qualities, use the REST style. If it desires the latter, use the RPC style.
If you're planning on using using Hibernate/JPA on the server-side and sending the resulting POJO's with relational data in them to the client (ie. an Employee object with a collection of Phones), definitely go with the REST implementation.
I started my GWT project a month ago using GWT RPC. All was well until I tried to serialize an object from the underlying db with a One-To-Many relationship in it. And got the dreaded:
com.google.gwt.user.client.rpc.SerializationException: Type 'org.hibernate.collection.PersistentList' was not included in the set of types which can be serialized by this SerializationPolicy
If you encounter this and want to stay with GWT RPC you will have to use something like:
GWT Request Factory (www.gwtproject.org/doc/latest/DevGuideRequestFactory.html) - which forces you to write 3+ classes/interfaces per POJO you want to share with the client. OUCH!
Gilead (sourceforge.net/projects/gilead/) - which appears to a dead project.
I'm now using RestyGWT. The switch was fairly painless and my POJO's serialize without issue.
I would say that this depends on the scope of your total application. If your backend should be used by other clients, needs to be extendable etc. then create a separate module using REST. If the backend is to be used by only this client, then go for the GWT-RPC solution.