Skip to content

Commit 815c58d

Browse files
committed
upgrade to .NET Core 3.1 and merged with code at #8
1 parent 07cde19 commit 815c58d

29 files changed

+322
-328
lines changed

GrpcJsonTranscoder.sln.DotSettings

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
2+
<s:Boolean x:Key="/Default/UserDictionary/Words/=Grpc/@EntryIndexedValue">True</s:Boolean>
3+
<s:Boolean x:Key="/Default/UserDictionary/Words/=Transcoder/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

NuGet.config

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<packageSources>
55
<clear />
66
<add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" />
7+
<add key="framework.release" value="https://pkgs.dev.azure.com/evolutionwellness/_packaging/framework/nuget/v3/index.json" protocolVersion="3" />
78
</packageSources>
89
<system.net>
910
<defaultProxy useDefaultCredentials="true" enabled="true">

README.md

+14-124
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[![Price](https://img.shields.io/badge/price-FREE-0098f7.svg)](https://github.com/thangchung/GrpcJsonTranscoder/blob/master/LICENSE)
44
[![version](https://img.shields.io/nuget/v/GrpcJsonTranscoder.svg?label=version)](https://www.nuget.org/packages?q=GrpcJsonTranscoder)
55

6-
This is a filter that allows a RESTful JSON API client (Ocelot Gateway) to send requests to .NET Web API (Aggregation Service) over HTTP and get proxied to a gRPC service (on behind).
6+
This is a filter that allows a RESTful JSON API client (Ocelot Gateway) to send requests to .NET Web API (Aggregator Service) over HTTP and get proxied to a gRPC service (on the downstream).
77

88
This project is inspired by [grpc-gateway](https://github.com/grpc-ecosystem/grpc-gateway) which is totally for golang, [grpc-dynamic-gateway](https://github.com/konsumer/grpc-dynamic-gateway) is for nodejs. And especially, [Envoy gRPC-JSON transcoder](https://www.envoyproxy.io/docs/envoy/latest/configuration/http_filters/grpc_json_transcoder_filter) is the best of transcoding in this area, but it is only on the infrastructure level. You also can use it just like my project used at [coolstore-microservices](https://github.com/vietnam-devs/coolstore-microservices/blob/master/deploys/dockers/envoy-proxy/envoy.yaml).
99

@@ -33,10 +33,15 @@ $ start.sh # I haven't done it yet :p
3333

3434
> In the mean time, we open up the visual studio, run multiple projects included OcelotGateway, AggregationRestApi, ProductCatalogGrpcServer and GreatGrpcServer
3535
36-
- OcelotGateway (.NET Core 2.2): http://localhost:5000
37-
- AggregationRestApi (.NET Core 3.0): http://localhost:5001
38-
- ProductCatalogGrpcServer (.NET Core 3.0): http://localhost:5002
39-
- GreatGrpcServer (.NET Core 3.0): http://localhost:5003
36+
- OcelotGateway (.NET Core 3.1):
37+
- REST: http://localhost:5000
38+
- WeatherServer (.NET Core 3.1):
39+
- REST: http://localhost:5001
40+
- ProductCatalogGrpcServer (.NET Core 3.1):
41+
- REST: http://localhost:5002
42+
- gRPC: http://localhost:50022
43+
- GreatGrpcServer (.NET Core 3.1):
44+
- gRPC: http://localhost:5003
4045

4146
Test it as below:
4247

@@ -64,12 +69,14 @@ $ curl -X GET -H 'content-type: application/json' -k http://localhost:5000/weath
6469
$ [{"date":"2019-08-17T18:34:41.1090164+07:00","temperatureC":-6,"temperatureF":22,"summary":"Sweltering"},{"date":"2019-08-18T18:34:41.1090371+07:00","temperatureC":27,"temperatureF":80,"summary":"Hot"},{"date":"2019-08-19T18:34:41.1090499+07:00","temperatureC":33,"temperatureF":91,"summary":"Balmy"},{"date":"2019-08-20T18:34:41.1090617+07:00","temperatureC":-14,"temperatureF":7,"summary":"Chilly"},{"date":"2019-08-21T18:34:41.1090743+07:00","temperatureC":22,"temperatureF":71,"summary":"Hot"}]
6570
```
6671

72+
**Notes**:
73+
- REST method: `content-type: application/json` is for REST method on the downstream services.
74+
- gRPC method: `content-type: application/grpc` is really important if you call to `gRPC endpoint` on the downstream services.
75+
6776
## How to understand it!
6877

6978
The project aims to .NET community and its ecosystem which leverage the power of [Ocelot Gateway](https://github.com/ThreeMammals/Ocelot) which is very powerful in the gateway components were used by various of companies and sample source code when we try to adopt the microservices architecture project.
7079

71-
- Option 1: Use directly with Ocelot
72-
7380
![](assets/overview_option1.png)
7481

7582
That's quite simple with only a few steps to make it work :)
@@ -146,123 +153,6 @@ var configuration = new OcelotPipelineConfiguration
146153
app.UseOcelot(configuration).Wait();
147154
```
148155

149-
- Option 2: Use via an aggregation layer
150-
151-
![](assets/overview_option2.png)
152-
153-
We will normally use Ocelot configuration for the transcode process, the main parser and transformation processes are only happening at aggregation service level so that you will easy to upgrade Ocelot in case we need, but not affect to the grpc-json transcode seats in the aggregation service.
154-
155-
```json
156-
// ocelot.json
157-
{
158-
"ReRoutes": [
159-
{
160-
"UpstreamPathTemplate": "/say/{name}",
161-
"UpstreamHttpMethod": [ "Get" ],
162-
"DownstreamPathTemplate": "/Greet.Greeter/SayHello",
163-
"DownstreamScheme": "http",
164-
"DownstreamHostAndPorts": [
165-
{
166-
"Host": "localhost",
167-
"Port": 5001
168-
}
169-
]
170-
},
171-
{
172-
"UpstreamPathTemplate": "/products",
173-
"UpstreamHttpMethod": [ "Get" ],
174-
"DownstreamPathTemplate": "/ProductCatalog.Product/GetProducts",
175-
"DownstreamScheme": "http",
176-
"DownstreamHostAndPorts": [
177-
{
178-
"Host": "localhost",
179-
"Port": 5001
180-
}
181-
]
182-
},
183-
{
184-
"UpstreamPathTemplate": "/products",
185-
"UpstreamHttpMethod": [ "Post" ],
186-
"DownstreamPathTemplate": "/ProductCatalog.Product/CreateProduct",
187-
"DownstreamScheme": "http",
188-
"DownstreamHostAndPorts": [
189-
{
190-
"Host": "localhost",
191-
"Port": 5001
192-
}
193-
]
194-
}
195-
],
196-
"GlobalConfiguration": {
197-
"BaseUrl": "http://localhost:5000"
198-
}
199-
}
200-
```
201-
202-
and,
203-
204-
```csharp
205-
// Program.cs
206-
var configuration = new OcelotPipelineConfiguration
207-
{
208-
PreQueryStringBuilderMiddleware = async (ctx, next) =>
209-
{
210-
var routes = ctx.TemplatePlaceholderNameAndValues;
211-
ctx.DownstreamRequest.Headers.Add(
212-
"x-grpc-routes",
213-
JsonConvert.SerializeObject(routes.Select(x => new NameAndValue { Name = x.Name, Value = x.Value })));
214-
await next.Invoke();
215-
}
216-
};
217-
218-
app.UseOcelot(configuration).Wait();
219-
```
220-
221-
More at https://github.com/thangchung/GrpcJsonTranscoder/tree/master/samples/OcelotGateway
222-
223-
Then we only put some of the json configurations into `appsettings.json` inside aggregation service to point it to other gRPC services we need.
224-
225-
```json
226-
// appsettings.json
227-
"GrpcJsonTranscoder": {
228-
"GrpcMappers": [
229-
{
230-
"GrpcMethod": "/Greet.Greeter/SayHello",
231-
"GrpcHost": "127.0.0.1:5003"
232-
},
233-
{
234-
"GrpcMethod": "/ProductCatalog.Product/GetProducts",
235-
"GrpcHost": "127.0.0.1:5002"
236-
},
237-
{
238-
"GrpcMethod": "/ProductCatalog.Product/CreateProduct",
239-
"GrpcHost": "127.0.0.1:5002"
240-
}
241-
]
242-
}
243-
```
244-
245-
```csharp
246-
// Startup.cs
247-
public void ConfigureServices(IServiceCollection services)
248-
{
249-
...
250-
251-
services.AddGrpcJsonTranscoder(() => new GrpcAssemblyResolver().ConfigGrpcAssembly(typeof(Greeter.GreeterClient).Assembly));
252-
}
253-
254-
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
255-
{
256-
...
257-
258-
app.UseGrpcJsonTranscoder();
259-
260-
...
261-
}
262-
```
263-
264-
More at https://github.com/thangchung/GrpcJsonTranscoder/tree/master/samples/AggregationRestApi
265-
266156
### **Don't believe what I said. Try it!**
267157

268158
> We haven't tested it with stream and full-duplex transport protocols yet. So we feel free to contribute by the .NET community.

docker-compose.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ services:
3535
context: .
3636
dockerfile: ./samples/ProductGrpcServer/Dockerfile
3737
ports:
38-
- "5002:80"
38+
- "5002:5002"
39+
- "50022:50022"
3940
environment:
4041
- ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT}
4142
networks:

samples/GreatGrpcServer/Dockerfile

+15-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1-
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
2-
WORKDIR /app
3-
EXPOSE 80
1+
FROM mcr.microsoft.com/dotnet/core/sdk:3.1.101-alpine3.10 AS builder
2+
3+
ENV GLIBC_REPO=https://github.com/sgerrand/alpine-pkg-glibc
4+
ENV GLIBC_VERSION=2.30-r0
5+
6+
RUN set -ex && \
7+
apk --update add libstdc++ curl ca-certificates && \
8+
for pkg in glibc-${GLIBC_VERSION} glibc-bin-${GLIBC_VERSION}; \
9+
do curl -sSL ${GLIBC_REPO}/releases/download/${GLIBC_VERSION}/${pkg}.apk -o /tmp/${pkg}.apk; done && \
10+
apk add --allow-untrusted /tmp/*.apk && \
11+
rm -v /tmp/*.apk && \
12+
/usr/glibc-compat/sbin/ldconfig /lib /usr/glibc-compat/lib
413

5-
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
614
WORKDIR /src
715
COPY ["samples/GreatGrpcServer/GreatGrpcServer.csproj", "samples/GreatGrpcServer/"]
816
COPY ["samples/GrpcShared/GrpcShared.csproj", "samples/GrpcShared/"]
@@ -11,10 +19,11 @@ COPY . .
1119
WORKDIR "/src/samples/GreatGrpcServer"
1220
RUN dotnet build "GreatGrpcServer.csproj" -c Release -o /app
1321

14-
FROM build AS publish
22+
FROM builder AS publish
1523
RUN dotnet publish "GreatGrpcServer.csproj" -c Release -o /app
1624

17-
FROM base AS final
25+
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1.1-alpine3.10
1826
WORKDIR /app
27+
EXPOSE 80
1928
COPY --from=publish /app .
2029
ENTRYPOINT ["dotnet", "GreatGrpcServer.dll"]

samples/GreatGrpcServer/GreatGrpcServer.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
</PropertyGroup>
66

77
<ItemGroup>
8-
<PackageReference Include="Grpc.AspNetCore" Version="0.1.22-pre2" />
8+
<PackageReference Include="Grpc.AspNetCore" Version="2.27.0" />
99
</ItemGroup>
1010

1111
<ItemGroup>

samples/GrpcShared/GrpcShared.csproj

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
</ItemGroup>
1515

1616
<ItemGroup>
17-
<PackageReference Include="Google.Protobuf" Version="3.9.1" />
18-
<PackageReference Include="Grpc.Core" Version="1.22.0" />
19-
<PackageReference Include="Grpc.Tools" Version="1.22.0" PrivateAssets="All" />
17+
<PackageReference Include="Google.Protobuf" Version="3.11.4" />
18+
<PackageReference Include="Grpc.Core" Version="2.27.0" />
19+
<PackageReference Include="Grpc.Tools" Version="2.27.0" PrivateAssets="All" />
2020
</ItemGroup>
2121

2222
</Project>

samples/OcelotGateway/Dockerfile

+15-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1-
FROM mcr.microsoft.com/dotnet/core/aspnet:2.2-stretch-slim AS base
2-
WORKDIR /app
3-
EXPOSE 80
1+
FROM mcr.microsoft.com/dotnet/core/sdk:3.1.101-alpine3.10 AS builder
2+
3+
ENV GLIBC_REPO=https://github.com/sgerrand/alpine-pkg-glibc
4+
ENV GLIBC_VERSION=2.30-r0
5+
6+
RUN set -ex && \
7+
apk --update add libstdc++ curl ca-certificates && \
8+
for pkg in glibc-${GLIBC_VERSION} glibc-bin-${GLIBC_VERSION}; \
9+
do curl -sSL ${GLIBC_REPO}/releases/download/${GLIBC_VERSION}/${pkg}.apk -o /tmp/${pkg}.apk; done && \
10+
apk add --allow-untrusted /tmp/*.apk && \
11+
rm -v /tmp/*.apk && \
12+
/usr/glibc-compat/sbin/ldconfig /lib /usr/glibc-compat/lib
413

5-
FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
614
WORKDIR /src
715
COPY ["samples/OcelotGateway/OcelotGateway.csproj", "samples/OcelotGateway/"]
816
COPY ["samples/GrpcShared/GrpcShared.csproj", "samples/GrpcShared/"]
@@ -12,11 +20,12 @@ COPY . .
1220
WORKDIR "/src/samples/OcelotGateway"
1321
RUN dotnet build "OcelotGateway.csproj" -c Release -o /app
1422

15-
FROM build AS publish
23+
FROM builder AS publish
1624
RUN dotnet publish "OcelotGateway.csproj" -c Release -o /app
1725

18-
FROM base AS final
26+
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1.1-alpine3.10
1927
WORKDIR /app
28+
EXPOSE 80
2029
COPY --from=publish /app .
2130
#todo: override configuration.json to ocelot.json
2231
ENTRYPOINT ["dotnet", "OcelotGateway.dll"]

samples/OcelotGateway/OcelotGateway.csproj

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
<Project Sdk="Microsoft.NET.Sdk.Web">
22

33
<PropertyGroup>
4-
<TargetFramework>netcoreapp2.2</TargetFramework>
4+
<TargetFramework>netcoreapp3.1</TargetFramework>
55
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
66
</PropertyGroup>
77

88
<ItemGroup>
99
<PackageReference Include="Microsoft.AspNetCore.App" />
1010
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
11-
<PackageReference Include="Ocelot" Version="13.5.2" />
11+
<PackageReference Include="Ocelot" Version="14.0.11" />
1212
</ItemGroup>
1313

1414
<ItemGroup>

samples/OcelotGateway/Program.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using Ocelot.DependencyInjection;
99
using Ocelot.Middleware;
1010
using System.Threading.Tasks;
11+
using Microsoft.Extensions.Logging;
1112

1213
namespace OcelotGateway
1314
{
@@ -33,7 +34,10 @@ public static IWebHost BuildWebHost(string[] args) =>
3334
})
3435
.ConfigureServices(services =>
3536
{
36-
services.AddGrpcJsonTranscoder(() => new GrpcAssemblyResolver().ConfigGrpcAssembly(typeof(Greeter.GreeterClient).Assembly));
37+
services.AddGrpcJsonTranscoder(() =>
38+
new GrpcAssemblyResolver().ConfigGrpcAssembly(
39+
services.BuildServiceProvider().GetService<ILogger<GrpcAssemblyResolver>>(),
40+
typeof(Greeter.GreeterClient).Assembly));
3741
services.AddOcelot();
3842
services.AddHttpContextAccessor();
3943
})

samples/ProductGrpcServer/Dockerfile

+15-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
1-
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
2-
WORKDIR /app
3-
EXPOSE 80
1+
FROM mcr.microsoft.com/dotnet/core/sdk:3.1.101-alpine3.10 AS builder
2+
3+
ENV GLIBC_REPO=https://github.com/sgerrand/alpine-pkg-glibc
4+
ENV GLIBC_VERSION=2.30-r0
5+
6+
RUN set -ex && \
7+
apk --update add libstdc++ curl ca-certificates && \
8+
for pkg in glibc-${GLIBC_VERSION} glibc-bin-${GLIBC_VERSION}; \
9+
do curl -sSL ${GLIBC_REPO}/releases/download/${GLIBC_VERSION}/${pkg}.apk -o /tmp/${pkg}.apk; done && \
10+
apk add --allow-untrusted /tmp/*.apk && \
11+
rm -v /tmp/*.apk && \
12+
/usr/glibc-compat/sbin/ldconfig /lib /usr/glibc-compat/lib
413

514
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
615
WORKDIR /src
@@ -11,10 +20,11 @@ COPY . .
1120
WORKDIR "/src/samples/ProductGrpcServer"
1221
RUN dotnet build "ProductGrpcServer.csproj" -c Release -o /app
1322

14-
FROM build AS publish
23+
FROM builder AS publish
1524
RUN dotnet publish "ProductGrpcServer.csproj" -c Release -o /app
1625

17-
FROM base AS final
26+
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1.1-alpine3.10
1827
WORKDIR /app
28+
EXPOSE 80
1929
COPY --from=publish /app .
2030
ENTRYPOINT ["dotnet", "ProductGrpcServer.dll"]

samples/ProductGrpcServer/ProductGrpcServer.csproj

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
</PropertyGroup>
66

77
<ItemGroup>
8-
<PackageReference Include="Grpc.AspNetCore" Version="0.1.22-pre2" />
9-
<PackageReference Include="Grpc.AspNetCore.Server" Version="0.1.22-pre2" />
8+
<PackageReference Include="Grpc.AspNetCore" Version="2.27.0" />
9+
<PackageReference Include="Grpc.AspNetCore.Server" Version="2.27.0" />
1010
</ItemGroup>
1111

1212
<ItemGroup>

samples/ProductGrpcServer/Program.cs

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using Microsoft.AspNetCore.Hosting;
22
using Microsoft.Extensions.Hosting;
3-
using System;
3+
using System.Net;
4+
using Microsoft.AspNetCore.Server.Kestrel.Core;
45

56
namespace ProductGrpcServer
67
{
@@ -15,7 +16,16 @@ public static IHostBuilder CreateHostBuilder(string[] args) =>
1516
Host.CreateDefaultBuilder(args)
1617
.ConfigureWebHostDefaults(webBuilder =>
1718
{
18-
19+
webBuilder.ConfigureKestrel((ctx, options) =>
20+
{
21+
options.Limits.MinRequestBodyDataRate = null;
22+
options.Listen(IPAddress.Any, 5002);
23+
options.Listen(IPAddress.Any, 50022, listenOptions =>
24+
{
25+
listenOptions.Protocols = HttpProtocols.Http2;
26+
});
27+
});
28+
1929
webBuilder.UseStartup<Startup>();
2030
});
2131
}

0 commit comments

Comments
 (0)